写在前面

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

AlloyRenderingEngine文本框组件的更多相关文章

  1. Flutter学习笔记(21)--TextField文本框组件和Card卡片组件

    如需转载,请注明出处:Flutter学习笔记(21)--TextField文本框组件和Card卡片组件 今天来学习下TextField文本框组件和Card卡片组件. 只要是应用程序就少不了交互,基本上 ...

  2. Flutter——TextField组件(文本框组件)

    TextField组件的常用属性: 属性 描述 maxLines 设置此参数可以把文本框改为多行文本框 onChanged 文本框改变的时候触发的事件 decoration hintText 类似 h ...

  3. javaSwing文本框组件

    public class JTextFieldTest extends JFrame{    private static final long serialVersionUID = 1L;    p ...

  4. xmlplus 组件设计系列之三 - 文本框

    文本框是页面中最常用的输入组件,它的默认使用方式如下: <input type='text'/> 当然,这里的 `type='text' 可以略去不写.大部分情况下,使用默认的文本框作为输 ...

  5. Python Tkinter 文本框(Entry)

    Python Tkinter 文本框用来让用户输入一行文本字符串. 你如果需要输入多行文本,可以使用 Text 组件. 你如果需要显示一行或多行文本且不允许用户修改,你可以使用 Label 组件. 语 ...

  6. [js开源组件开发]js文本框计数组件

    js文本框计数组件 先上效果图: 样式可以自行调整 ,它的功能提供文本框的实时计数,并作出对应的操作,比如现在超出了,点击下面的按钮后,文本框会闪动两下,阻止提交.具体例子可以点击demo:http: ...

  7. Android开发10.2:UI组件AutoCompleteTextView(自动完成文本框)

    概述 AutoCompleteTextVeiw(自动完成文本框)从 EditText派生而出  PS :EditText用法介绍           当用户输入一定字符后,自动完成自动完成文本框会显示 ...

  8. 『Asp.Net 组件』第一个 Asp.Net 服务器组件:自己的文本框控件

    代码: using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace DemoWebControl ...

  9. 使用ErrorProvider组件验证文本框输入

    实现效果: 知识运用: ErrorProvider组件的BlinkStyle属性 //指示错误图标的闪烁时间 public ErrorBlinkStyle BlinkStyle{ get;set; } ...

随机推荐

  1. Java实现FTP文件与文件夹的上传和下载

    Java实现FTP文件与文件夹的上传和下载 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于Internet上的控制 ...

  2. exp/imp 与 expdp/impdp 区别

    在平常备库和数据库迁移的时候,当遇到大的数据库的时候在用exp的时候往往是需要好几个小时,耗费大量时间.oracle10g以后可以用expdp来导出数据库花费的时间要远小于exp花费的时间,而且文件也 ...

  3. 解决mysql插入数据时出现Incorrect string value: '\xF0\x9F...' for column 'name' at row 1的异常

    这个问题,原因是UTF-8编码有可能是两个.三个.四个字节.Emoji表情或者某些特殊字符是4个字节,而MySQL的utf8编码最多3个字节,所以数据插不进去. 我的解决方案是这样的 1.在mysql ...

  4. 【转】 XenServer的架构

    一.Dom0或者控制域 XenServer从安装上看起来像是一个Linux,所以有些同学认为XenServer就是Linux或者是Linux修改的.真实的XenServer和Linux的关系是这样的: ...

  5. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  6. 免费开源的 .NET 分布式组件库 Exceptionless Foundatio

    前言 在互联网时代,分布式应用.系统变得越来越多,我们在使用 .Net 技术构建分布式系统的时候,需要使用到一些组件或者是助手库来帮助我们提高生产力以及应用程序解耦,但是纵观.Net圈,能够符合要求的 ...

  7. 页面元素坐标和偏移(clientX/pageX/screenX/layerX/offsetWidth/scrollWidth/clientWidth等)相关整理

    鼠标事件都是在特定位置发生的,我们可以通过event事件对象的各种属性来获得事件发生的坐标位置,有相对于视口的,有相对于整个文档的,同样页面元素的位置也有相对视口的,也有滚动后的,这些都比较容易混淆, ...

  8. [源码]Literacy 快速反射读写对象属性,字段

    Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...

  9. salesforce 零基础学习(六十一)apex:component简单使用以及图片轮转播放的实现

    有的时候,我们项目有可能有类似需求:做一个简单的图像轮转播放功能,不同的VF页面调用可以显示不同的图片以及不同的图片描述.这种情况,如果在每个页面单独处理相关的图像轮转播放则显得代码特别冗余,此种情况 ...

  10. javascript关于立即函数

    以前的知识总是忘,遇到代码又看不懂.要再复习一下,顺便记录一下. 关于立即执行函数:  函数声明:function fnName () {…};使用function关键字声明一个函数,再指定一个函数名 ...