转载

AlloyRenderingEngine文本框组件

写在前面

Github: https://github.com/AlloyTeam/AlloyGameEngine

在dom元素里,自带了input标签,设置其type为text,它就是一个文本框。

那么在Canvas中模拟input文本框是不是闲的没事找事?绝对不是!因为在游戏当中可以统一化像素管理,具体统一化像素管理有什么好处,以后新开文章详细讨论。

上面的文本框就是使用AlloyRenderingEngine渲染出来的。

; (function () {  var Stage = ARE.Stage, Textbox = ARE.Textbox;  var stage = new Stage("#ourCanvas", true);  var textbox = new ARE.Textbox({   fontSize: 22,   color: "red",   width: 200,   height: 26  });  textbox.x = 50;  textbox.y = 50;  textbox.focus();  stage.add(textbox); })(); 

原理(都在注释里)

; (function () {  //先把要使用类的赋给临时变量,以后就不用打点了:)  var Stage = ARE.Stage, Container = ARE.Container, Graphics = ARE.Graphics, Text = ARE.Text;  //文本框集成自容器  ARE.Textbox = Container.extend({   //构造函数   ctor: function (option) {    //把容器的属性和方法搞给自己    this._super();    //鼠标移上去指针的形状,AlloyRenderingEngine会自动帮你显示鼠标移上去时候的形状    this.cursor = "text";    //文本框的边框    this.box = new Graphics()    //直接根据传进的宽和高画个矩形    this.box.strokeRect(0, 0, option.width, option.height);    //文本框的背景,这里接近透明,为什么要设置背景是因为鼠标一上去要触发一个事件,    //而AlloyRenderingEngine的默认触发是像素级别,    //会根据getImageData得到该点的rgba的a是否为0去判断是否触发事件    //所以铺一个接近透明的背景    //主要是为了触发的事件是:鼠标移到文本框上面,鼠标形状要变成cursor:text    this.box.fillStyle("rgba(255,255,255,0.1)").fillRect(0, 0, option.width, option.height);    //把边框添加到自身(因为自身就是容器,继承自Container,所以有了add方法)    this.add(this.box);    //绑定事件    this._bindEvent();    //合并默认配置    this.option = {     fontSize: option.fontSize || 12,     fontFamily: option.fontFamily || "arial",     color: option.color || "black",     width: option.width    };         //cursorText代表文本框中闪烁的光标,自己用黑色的Text去模拟    this.cursorText = new Text("|", this.option.fontSize + "px " + this.option.fontFamily, "black");    //真正的input!!!!哈哈,玄机就在于此 =   =!    this.realTextbox = document.createElement("input");    this.realTextbox.type = "text";    this.realTextbox.style.position = "fixed";    this.realTextbox.style.left= "-200px"    this.realTextbox.style.top= "0px"    document.body.appendChild(this.realTextbox);    //canvas中显示的文本    this.text = new Text("", this.option.fontSize + "px " + this.option.fontFamily, this.option.color);    //measureCtx是专门用于测量canvas中文本宽度的    this.measureCtx = document.createElement("canvas").getContext("2d");    this.measureCtx.font = this.option.fontSize + "px " + this.option.fontFamily;    this.add(this.text, this.cursorText);    //tickFPS是该容器tick执行的频率,AlloyRenderingEngine会自动帮你执行tick方法    this.tickFPS = 20;   },   //获取焦点   focus: function () {    var self = this;    //真正的input也同时获取焦点    this.realTextbox.focus();    //Canvas中的光标闪烁    this.loop = setInterval(function () {     self.cursorText.visible = !self.cursorText.visible;    }, 500);   },   //失去焦点   blur: function () {    clearInterval(this.loop);    //真正的input也同时失去焦点    this.realTextbox.blur();    //隐藏Canvas中的光标    this.cursorText.visible = false;   },   _bindEvent: function () {    var self = this;    this.onClick(function (evt) {     //真正的input也同时获取焦点     self.realTextbox.focus();     //显示光标     self.cursorText.visible = true;     //自己也假装获取焦点     self.focus();     //阻止冒泡     evt.stopPropagation();    });    //点击文本框的其他区域触发失去焦点    document.addEventListener("mousedown", function () {     //失去焦点     self.blur();    }, false);   },   //计算合适的显示文本,这主要是解决文本超出了文本框的宽度时候的显示问题   getFitStr: function (str, index) {    //利用measureText计算文本宽度    var width = this.measureCtx.measureText(str.substring(index, str.length - 1)).width;    if (width < this.option.width - this.option.fontSize) {     return this.getFitStr(str, --index);    } else {     return str.substring(index++, str.length - 1)    }   },   tick: function () {    //利用measureText计算文本宽度,并把该宽度赋值给光标的偏移    this.cursorText.x = this.measureCtx.measureText(this.realTextbox.value).width;    //如果宽度超了    if (this.cursorText.x > this.option.width) {     this.text.value = this.getFitStr(this.realTextbox.value, this.realTextbox.value.length - 2);     this.cursorText.x = this.measureCtx.measureText(this.text.value).width;    } else {//如果宽度没超     this.text.value = this.realTextbox.value;    }   }  }); })(); 

大部分代码都做了解释,不再重复阐述。

Github: https://github.com/AlloyTeam/AlloyGameEngine

正文到此结束
Loading...