写在前面

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

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

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

演示

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

使用

  1. ; (function () {
  2. var Stage = ARE.Stage, Textbox = ARE.Textbox;
  3. var stage = new Stage("#ourCanvas", true);
  4. var textbox = new ARE.Textbox({
  5. fontSize: 22,
  6. color: "red",
  7. width: 200,
  8. height: 26
  9. });
  10. textbox.x = 50;
  11. textbox.y = 50;
  12. textbox.focus();
  13. stage.add(textbox);
  14. })();

原理(都在注释里)

  1. ; (function () {
  2. //先把要使用类的赋给临时变量,以后就不用打点了:)
  3. var Stage = ARE.Stage, Container = ARE.Container, Graphics = ARE.Graphics, Text = ARE.Text;
  4. //文本框集成自容器
  5. ARE.Textbox = Container.extend({
  6. //构造函数
  7. ctor: function (option) {
  8. //把容器的属性和方法搞给自己
  9. this._super();
  10. //鼠标移上去指针的形状,AlloyRenderingEngine会自动帮你显示鼠标移上去时候的形状
  11. this.cursor = "text";
  12. //文本框的边框
  13. this.box = new Graphics()
  14. //直接根据传进的宽和高画个矩形
  15. this.box.strokeRect(0, 0, option.width, option.height);
  16. //文本框的背景,这里接近透明,为什么要设置背景是因为鼠标一上去要触发一个事件,
  17. //而AlloyRenderingEngine的默认触发是像素级别,
  18. //会根据getImageData得到该点的rgba的a是否为0去判断是否触发事件
  19. //所以铺一个接近透明的背景
  20. //主要是为了触发的事件是:鼠标移到文本框上面,鼠标形状要变成cursor:text
  21. this.box.fillStyle("rgba(255,255,255,0.1)").fillRect(0, 0, option.width, option.height);
  22. //把边框添加到自身(因为自身就是容器,继承自Container,所以有了add方法)
  23. this.add(this.box);
  24. //绑定事件
  25. this._bindEvent();
  26. //合并默认配置
  27. this.option = {
  28. fontSize: option.fontSize || 12,
  29. fontFamily: option.fontFamily || "arial",
  30. color: option.color || "black",
  31. width: option.width
  32. };
  33. //cursorText代表文本框中闪烁的光标,自己用黑色的Text去模拟
  34. this.cursorText = new Text("|", this.option.fontSize + "px " + this.option.fontFamily, "black");
  35. //真正的input!!!!哈哈,玄机就在于此 = =!
  36. this.realTextbox = document.createElement("input");
  37. this.realTextbox.type = "text";
  38. this.realTextbox.style.position = "fixed";
  39. this.realTextbox.style.left= "-200px"
  40. this.realTextbox.style.top= "0px"
  41. document.body.appendChild(this.realTextbox);
  42. //canvas中显示的文本
  43. this.text = new Text("", this.option.fontSize + "px " + this.option.fontFamily, this.option.color);
  44. //measureCtx是专门用于测量canvas中文本宽度的
  45. this.measureCtx = document.createElement("canvas").getContext("2d");
  46. this.measureCtx.font = this.option.fontSize + "px " + this.option.fontFamily;
  47. this.add(this.text, this.cursorText);
  48. //tickFPS是该容器tick执行的频率,AlloyRenderingEngine会自动帮你执行tick方法
  49. this.tickFPS = 20;
  50. },
  51. //获取焦点
  52. focus: function () {
  53. var self = this;
  54. //真正的input也同时获取焦点
  55. this.realTextbox.focus();
  56. //Canvas中的光标闪烁
  57. this.loop = setInterval(function () {
  58. self.cursorText.visible = !self.cursorText.visible;
  59. }, 500);
  60. },
  61. //失去焦点
  62. blur: function () {
  63. clearInterval(this.loop);
  64. //真正的input也同时失去焦点
  65. this.realTextbox.blur();
  66. //隐藏Canvas中的光标
  67. this.cursorText.visible = false;
  68. },
  69. _bindEvent: function () {
  70. var self = this;
  71. this.onClick(function (evt) {
  72. //真正的input也同时获取焦点
  73. self.realTextbox.focus();
  74. //显示光标
  75. self.cursorText.visible = true;
  76. //自己也假装获取焦点
  77. self.focus();
  78. //阻止冒泡
  79. evt.stopPropagation();
  80. });
  81. //点击文本框的其他区域触发失去焦点
  82. document.addEventListener("mousedown", function () {
  83. //失去焦点
  84. self.blur();
  85. }, false);
  86. },
  87. //计算合适的显示文本,这主要是解决文本超出了文本框的宽度时候的显示问题
  88. getFitStr: function (str, index) {
  89. //利用measureText计算文本宽度
  90. var width = this.measureCtx.measureText(str.substring(index, str.length - 1)).width;
  91. if (width < this.option.width - this.option.fontSize) {
  92. return this.getFitStr(str, --index);
  93. } else {
  94. return str.substring(index++, str.length - 1)
  95. }
  96. },
  97. tick: function () {
  98. //利用measureText计算文本宽度,并把该宽度赋值给光标的偏移
  99. this.cursorText.x = this.measureCtx.measureText(this.realTextbox.value).width;
  100. //如果宽度超了
  101. if (this.cursorText.x > this.option.width) {
  102. this.text.value = this.getFitStr(this.realTextbox.value, this.realTextbox.value.length - 2);
  103. this.cursorText.x = this.measureCtx.measureText(this.text.value).width;
  104. } else {//如果宽度没超
  105. this.text.value = this.realTextbox.value;
  106. }
  107. }
  108. });
  109. })();

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

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. postgresql 基本语法

    postgresql数据库创建/修改/删除等写入类代码语法总结: 1,创建库 2,创建/删除表 2.1 创建表 create table myTableName 2.2 如果表不存在则创建表 crea ...

  2. 自制Azure中国版“加血包”

    Micrsoft Azure中国版的国际出口最近升级为电话线拨号模式,目测为10个用户共享一条56kb的电话线拨号链路.有图有真相: 中国的IT从业者,有三分之一的职业生涯时间是在跟网络斗智斗勇.这点 ...

  3. TCP三次握手图解

  4. EMD分析 Matlab 精华总结 附开源工具箱(全)

    前言: 本贴写于2016年12与15日,UK.最近在学习EMD(Empirical Mode Decomposition)和HHT(Hilbert-Huang Transform)多分辨信号处理,FQ ...

  5. 通过Mono 在 Heroku 上运行 .NET 应用

    英文原文:Running .NET on Heroku 中文原文:在 Heroku 上运行 .NET 应用 自从加入了Heroku之后,我就想在这个平台上运行.NET程序.现在我很高兴向大家宣布,我们 ...

  6. opengl 笔记(2)

    /*- * Opengl Demo Test * * Fredric : 2016-7-10 */ #include <GLUT/GLUT.h> #include <stdlib.h ...

  7. 关于JavaScript中的delete操作

    关于JavaScript中的delete操作 看到一道题,是这样的: (function(x){ delete x; return x; })(1); 1 null undefined Error 我 ...

  8. Docker之Compose服务编排

    Compose是Docker的服务编排工具,主要用来构建基于Docker的复杂应用,Compose 通过一个配置文件来管理多个Docker容器,非常适合组合使用多个容器进行开发的场景. 说明:Comp ...

  9. Microsoft Visual Studio 2013 — Project搭载IIS配置的那些事

    前段时间在改Bug打开一个project时,发生了一件奇怪的事,好好的一直不能加载solution底下的这个project,错误如下图所示:大致的意思就是这个project的web server被配置 ...

  10. 编程之美—烙饼排序问题(JAVA)

    一.问题描述 星期五的晚上,一帮同事在希格玛大厦附近的"硬盘酒吧"多喝了几杯.程序员多喝了几杯之后谈什么呢?自然是算法问题.有个同事说:"我以前在餐      馆打工,顾 ...