虽然要讲解的知识点是通用的,但是还是要介绍下我的应用场景和测试环境。

0.1 应用场景和测试环境

我的应用是一块使用Html Canvas开发的黑板,在黑板上实现简单的文字编辑功能。

操作系统:win10

设备:为触屏和非触屏设备若干(一体机,surface,笔记本电脑)

主要浏览器: chrome 58

1.png

0.2 监控文字输入的方法

使用Canvas实现文字编辑器的细节这里就不讲了,原理大致都相同。一个必要条件是需要一个隐藏的textarea监听文字输入,因为canvas是无法记录文字选中、换行等信息的,也没有办法直接激活输入法和软键盘。textarea 如下:


复制代码

很多情况下,我们需要实时监控文字输入的变化,下面是几种选择。

0.2.1 键盘事件

监听keydown 和 keyup事件是最直接的方法,通过keyCode我们可以获取按键值。

     this.hiddenTextArea.onkeyup = (e) => {console.log("textKeyup",e.keyCode);             }this.hiddenTextArea.onkeydown = (e) => {console.log("textKeydown",e.keyCode);}复制代码

0.2.2 oninput事件

input事件在keydown事件触发之后被触发,这是input类型元素使用的标准事件,表示有文字输入。

2.png

从上图中我们可以看到,触发的事件为InputEvent,从该事件对象的data属性中可以获取到当前输入的按键值。

正常情况下,每一次按键都会触发oninput事件。

0.2.3 onpropertychange 事件

该事件主要是为了兼容IE9及以下浏览器对oninput事件的处理。

在监听到 onpropertychange 事件后,可以使用 event 的 propertyName 属性来获取发生变化的属性名称。

 // Internet Explorerfunction OnPropChanged (event) {if (event.propertyName.toLowerCase () == "value") {alert ("The new content: " + event.srcElement.value);}}复制代码

0.3 非直接输入模式

我们把及时响应键盘按键输入单个按键代表的字符到文本框的行为称为直接输入模式,相对的非直接输入模式,通常是输入法拦截了按键消息之后的输入,以中文输入法为例,通常是回车或者空格后完成输入。

3.png

在非直接输入模式下,我们期待的结果是当用户完成输入的时候(按了空格或者回车键)触发一次oninput事件。但是很不幸,每次按键都会触发oninput事件,这会导致我们不知道用户正在输入的是不是中文,也不知道什么时候结束的输入,也就没办法及时对输入的中文进行处理。 为了解决这个问题,我们看一下非直接输入情况下几个有用的属性和事件。

0.3.1 selectionStart 和 selectionEnd

这两个属性是textarea对文字选中区域的标识,从0开始,简化分析,我们只考虑正常文字输入,不考虑有选中的情况,首先是直接输入模式。

4.png

上图是我在oninput事件中打的日志,可以明显的看到每次oninput触发之后,selectionStart和selectionEnd的值都相同而且表示最后一个文本,视觉上是我们看到的光标所在的位置,如果我们挪动光标,这两个值也会变化。这里我们提取两个关键特征,在及时输入的情况下:

  1. selectionStart和selectionEnd随光标位置变化而变化
  2. selectionStart和selectionEnd值相等

下面我们再看非直接输入模式。

5.png

从上图中,我们可以看到在非直接输入模式下,在未完成输入之前,selectionStart一直为0,selectonEnd随着输入一直变化。完成输入时,selectionStart与selectonEnd值会相等。

0.3.2 value

从0.3.1的图中我们可以看到拼音输入法输入过程中,value值的变化,在完成输入之前这个值是由输入法控制的,完成之后,value的值会变为输入的文字内容。

0.3.3 compositionstart 与 compositionend 事件

这是一对事件,当非直接输入开始第一个按键的时候,触发compositionstart事件,非直接输入结束的时候触发compositionend事件, 在直接输入情况下,这两个事件都不会触发。我们添加对这两个事件的监听:

   this.hiddenTextArea.addEventListener('compositionstart', function () {console.log("compositionstart");that.isCompositionsting = false;})this.hiddenTextArea.addEventListener('compositionend', function () {console.log("compositionend");that.isCompositionsting = false;})复制代码
6.png

观察上图的输出内容,各个事件的执行顺序为:

keydown-->compositionstart-->input-->keyup....-->input-->compositionend-->keyup。

0.3.4 keyCode

现在我们观察下在非直接模式下,按键的值。

   this.hiddenTextArea.onkeyup = (e) => {console.log("keydowncode",e.keyCode);}this.hiddenTextArea.onkeydown = (e) => {console.log("keyupcode",e.keyCode);}复制代码
7.png

通过上图,我们可以看到不论你按下的是什么键,keycode都被重置为229了。当然这并不是什么标准,不同输入法的行为还是不一样的。不过目前我们能接触到的中文输入法,正常情况下都是229。

0.4 思路整理

通过上面的分析,我们重新整理下及时响应非直接输入的思路。

0.4.1 如何知道正非直接输入的开始和结束

  • 响应compositionstart事件和compositionend事件
  • 比较selectionStart 和 selectionEnd是否相等。通常需要一个变量来标识开始和结束,考虑有选中的情况,这两个值可能会经历“相等--不等--相等”(或者 “不等--不等(相差为1)--不等(值增加)--相等”)的流程。
    *判断按键的code是否为229,当然这也需要额外的变量来记录开始,还需要结合electionStart 和 selectionEnd才能判断出结束。

下面以selectionStart 和 selectionEnd为例,判断中文输入的开始和结束(非完整代码)。

 this.hiddenTextArea.oninput = (e) => {                 if (textArea.selectionStart == textArea.selectionEnd) {editor.bdCanvas.textEditor.currentText.text = textArea.value;if (!isCompositionsting && 没有文字选中情况) {//直接插入ascii字符} else {//插入文字(如果有部分文字被选中并替换)//先删除被选中的文字if (isCompositionsting) {//中文(中文输入法按空格之后,或者回车后输入的字符)isCompositionsting = false;} else {//英文、数字 (有选中内容被替换)}}} else {//到这儿说明输入的是中文(中文输入法未按空格之前)isCompositionsting = true;}}复制代码

上面的代码引入了isCompositionsting变量,结合selectionStart和selectionEnd来做文字处理。其他方法同理,这里就不过多讲解了。下面我们来分析点异常情况。

0.5 搜狗输入法的非常规套路

8.png

这是我安装的最新的搜狗输入法,下面要说的非正常情况,只在这一个版本下会出现。

我们在代码中对keydown,keyup,input,compositionstart和compositionend同时做事件监听,然后使用这个版本的搜狗输入法做输入。结果如下:

9.png

在未按下回车或者空格键之前,我们看到:

  • textarea只响应了keydown和keyup事件
  • keyup时keyCode并不是229
  • 过程中没有触发input事件

再看结束输入时的情况:

10.png

上图红框内的内容为结束输入时的记录,此时触发一次input事件,selectionStart和selectionEnd相等。
这种情况,结束输入触发一次input,我倒是认为很合理的做法,这样很多情况我们不用关心是否是中文输入了,input的时候获取新的value,记录上一次的selectionstart就可以了。
这种特殊行为我没有具体研究是输入法本身的问题,还是和浏览器、操作系统共同作用的结果。如果你编写类似的程序,需要额外注意下。

0.6 小结

本篇文章只是分析记录了一些现象,并没有什么技术含量,欢迎留言讨论。

玄魂工作室

textarea 的中文输入判断与搜狗输入法的特殊行为相关推荐

  1. 搜狗输入法在idea打不了汉字_IDEA开发软件在linux环境下使用搜狗输入法无法进行中文输入...

    IDEA开发软件在linux环境下使用搜狗输入法无法进行中文输入 找到bin目录下的idea.sh文件(其他编辑器也是一样如pycharm.sh.clion.sh).使用文本编译器打开,找到 # -- ...

  2. 享受中文输入,快乐信息分享 --拼音输入法所谓的经验谈

    享受中文输入,快乐信息分享 --拼音输入法所谓的经验谈 本文摘要:拼音输入法如果合理利用自己的语言常识,尽量回避单字,多打词语.短语或短句,把匹配工作交给输入法的词库和智能组词来做.实在避不开的单字通 ...

  3. c#中利用keybd_event函数+自定义软键盘实现中文输入时的问题

    (一)声明外部方法 [DllImport("User32.dll")]         public static extern void keybd_event(byte bVK ...

  4. sublime text3配置搜狗中文输入

    引文:http://my.oschina.net/daleyjh/blog/151457 最新消息:优麒麟14.04版自带搜狗输入法,http://www.ubuntukylin.com/,以下可以省 ...

  5. input在限制长度时,输入中文输入会自动清空(将拼音的长度计算在内)

    描述 在使用oninput监控输入框内容变化时,我们期望仅在value值变化时,才触发oninput事件,而在中文输入下,未选词时的按键也会触发oninput事件. 现象 input限制长度,输入中文 ...

  6. 这个“1句话生成视频”AI爆火:支持中文输入,分辨率达到480×480,清华智源出品...

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 一周不到,AI ...

  7. 【Qt】Qt Creator中文输入设置

    #[Qt]Qt Creator中文输入设置 一.ubuntu中文输入法的设置 1.在终端中输入: $ ibus-setup 弹出界面如图: 2.选择中文输入法 3.点击右上角设置–>选择系统设置 ...

  8. Android中文输入的新选择——搜狗拼音输入法

    如果不是我的Google拼音输入法出了点问题,我大概不会去尝试搜狗的Android平台拼音输入法.虽然全键盘在竖屏的情况下非常难用,不过横屏的时候还是可以接受的,何况G1有物理键盘. 现在的问题是,我 ...

  9. Ubantu 16.04中文输入问题解疑

    最近研究git与nodejs,看到linux与windows的许多不同的特性.结合微软这两年开始拥抱linux,决心拾起linux,研究一下基于linux优秀的软件设计思想,进行深入探究. linux ...

  10. iOS textView在调用textViewDidChange方法,中文输入的问题

    有时候,需要在textViewDidChange处理时,在中文输入的情况下,例如输入"中",对应的拼音"zhong", 在textViewDidChange的方 ...

最新文章

  1. 【怎样写代码】参数化类型 -- 泛型(六):泛型接口
  2. 四:(之六_镜像发布)Dockerfile语法梳理和实践
  3. 史上最全 | 数据分析技能详细拆解,一张图覆盖全流程知识细节和资源推荐(附下载)...
  4. 76.数据库操纵语言DML 定义语言 DDL 控制语言DCL
  5. linux系统运行快捷键,Linux操作系统下运行命令时CTRL+Z的作用
  6. 在gridview里查找模板里的button控件
  7. oracle 拼接sql 日期,动态SQL对日期处理注意事项
  8. jdk jre jvm 关系
  9. mysql select into和insert into select
  10. Asp.net防止盗链
  11. swf文件转mp4视频格式的失败与成功
  12. poi合并单元格后居中
  13. 1.Linux系统编程-进程
  14. 【分享】超级菜鸟另类玩swf反汇编
  15. 北邮校长方滨兴临别奉送学生“六好”锦囊
  16. [数分提高]2014-2015-2第6教学周第1次课讲义 3.3 Taylor 公式
  17. 01-Redis核心数据结构和高性能原理
  18. SqlParameter[]写法
  19. 知识图谱核心技术(一):知识图谱的概述
  20. 2019年如何抓住社交电商的风口

热门文章

  1. Atitit. visual studio vs2003 vs2005 vs2008  VS2010 vs2012 vs2015新特性 新功能.doc
  2. 银监会再出新规!银行数据治理与监管评级挂钩
  3. Rust : Box 为什么这里并不需要拆箱?
  4. Julia : Formatting库的 fmt Base.@sprintf
  5. 快讯丨业界首本云网络图书发布
  6. 不想买Xbox?没关系,微软正打算让你在电视上也能玩游戏
  7. 首届!「中国云计算基础架构开发者大会」征稿启动
  8. 【图像处理基础】基于matlab图像RGB+HSV分布图【含Matlab源码 234期】
  9. 【图像融合】基于matlab IHS变换与自适应区域特征遥感图像融合【含Matlab源码 1636期】
  10. 【时间序列预测】基于matlab CNN优化LSTM时间序列预测(单变量单输出)【含Matlab源码 1688期】