AS3中将TUIO协议转换到传统触摸事件
TUIO是一个用途广泛,支持厂商众多的多点触摸协议。 其编码采用XML抽象描述,所以任何支持XML的语言都可以使用TUIO协议的触摸设备。另外,TUIO不受windows触摸点上限限制,即设备支持多少个点,你就能使用多少个。
现在最新的TUIO协议版本是2.0 , 但是仍然没有普及,现有设备还是以1.0为默认支持。
希望在设备中使用TUIO,必须要与TUIO服务建立一个连接,TUIO协议的默认端口为 3000,这里跳过连接直接进入主题。
这是一个TUIO协议的一个数据包,其包含至少3个名为MESSAGE子项,每个子项的第一个子项的value属性定义了此子项的数据类型,
以此例为示,它有3个子项,第1个子项(alive)代表着当前存在的触摸点,这里是指所有在设备上的触摸点,包括那些正在移动的和静止的。第2个子项(set)对应了一个触摸点的详细数据,第3个子项(fseq)定义了包的序列ID。
- <OSCPACKET ADDRESS="127.0.0.1" PORT="55448" TIME="-3736546999771946328">
- <MESSAGE NAME="/tuio/2Dcur">
- <ARGUMENT TYPE="s" VALUE="alive"/>
- <ARGUMENT TYPE="i" VALUE="4"/>
- </MESSAGE>
- <MESSAGE NAME="/tuio/2Dcur">
- <ARGUMENT TYPE="s" VALUE="set"/>
- <ARGUMENT TYPE="i" VALUE="4"/>
- <ARGUMENT TYPE="f" VALUE="0.014778325123152709"/>
- <ARGUMENT TYPE="f" VALUE="0.03414634146341464"/>
- <ARGUMENT TYPE="f" VALUE="0"/>
- <ARGUMENT TYPE="f" VALUE="0"/>
- <ARGUMENT TYPE="f" VALUE="0"/>
- </MESSAGE>
- <MESSAGE NAME="/tuio/2Dcur">
- <ARGUMENT TYPE="s" VALUE="fseq"/>
- <ARGUMENT TYPE="i" VALUE="3"/>
- </MESSAGE>
- </OSCPACKET>
<OSCPACKET ADDRESS="127.0.0.1" PORT="55448" TIME="-3736546999771946328"><MESSAGE NAME="/tuio/2Dcur"><ARGUMENT TYPE="s" VALUE="alive"/><ARGUMENT TYPE="i" VALUE="4"/></MESSAGE><MESSAGE NAME="/tuio/2Dcur"><ARGUMENT TYPE="s" VALUE="set"/><ARGUMENT TYPE="i" VALUE="4"/><ARGUMENT TYPE="f" VALUE="0.014778325123152709"/><ARGUMENT TYPE="f" VALUE="0.03414634146341464"/><ARGUMENT TYPE="f" VALUE="0"/><ARGUMENT TYPE="f" VALUE="0"/><ARGUMENT TYPE="f" VALUE="0"/></MESSAGE><MESSAGE NAME="/tuio/2Dcur"><ARGUMENT TYPE="s" VALUE="fseq"/><ARGUMENT TYPE="i" VALUE="3"/></MESSAGE>
</OSCPACKET>
事实上,我们只需要使用alive和set消息,其他的消息都不在我们的考虑之内,
set消息传过来的参数只是TUIO设备上的坐标比例,从0-1,将其与本地舞台大小相乘才能得到舞台坐标。
alive消息描述了当前存在的点,根据这个参数我们可以排除那些已经消失的点。首先,我们先创建一个触摸点类
- import flash.display.InteractiveObject;
- public class TuioObject
- {
- /** 触摸id */
- public var id:int;
- /** 远程触摸编号 */
- public var remoteID:int;
- /** 指针对象 */
- public var target:InteractiveObject;
- /** 屏幕上的位置 */
- public var x:int;
- /** 屏幕上的位置 */
- public var y:int;
- /** 生效时候的位置 */
- public var startX:Number;
- /** 生效时候的位置 */
- public var startY:Number;
- /** 是否存在 */
- public var isExist:Boolean;
- public function TuioObject(touchID:int,x:Number,y:Number)
- {
- id = touchID;
- this.x = startX = x;
- this.y = startY = y;
- isExist = true;
- }
import flash.display.InteractiveObject;public class TuioObject{/** 触摸id */public var id:int;/** 远程触摸编号 */public var remoteID:int;/** 指针对象 */public var target:InteractiveObject;/** 屏幕上的位置 */public var x:int;/** 屏幕上的位置 */public var y:int;/** 生效时候的位置 */public var startX:Number;/** 生效时候的位置 */public var startY:Number;/** 是否存在 */public var isExist:Boolean;public function TuioObject(touchID:int,x:Number,y:Number){id = touchID;this.x = startX = x;this.y = startY = y;isExist = true;}
这个类描述了一个TUIO触摸点,每次出现新的触摸点时我们实例化一个与其相对应的触摸点。由于传输过来的数据并没有告诉我们某个触摸点是刚出现的,我们必须从现有的触摸点集合中查找ID,如果没有找到则判断为新的触摸事件。
- //根据ID查找TOUCH
- private function searchByRemoteName(remoteID:int):TuioObject{
- for each(var touch:TuioObject in _touchList){
- if(touch.remoteID == remoteID){
- return touch;
- }
- }
- return null;
- }
//根据ID查找TOUCHprivate function searchByRemoteName(remoteID:int):TuioObject{for each(var touch:TuioObject in _touchList){if(touch.remoteID == remoteID){return touch;}}return null;}
当有一个新点出现时,我们必须为它指定一个指向显示对象,以便从其向舞台冒泡事件,如果从这个点没有找到显示对象,则直接对舞台抛事件。注意,只有InteractiveObject才能抛出触摸事件,而Bitmap或Shape则不能接受鼠标事件
- //搜索舞台元素
- private function findDisplayObject(x:Number,y:Number):InteractiveObject{
- var obj:DisplayObject;
- var objArray:Array = _stage.getObjectsUnderPoint(new Point(x,y));
- if(objArray.length>0){
- obj=objArray[objArray.length-1];
- if(!(obj is InteractiveObject)){
- obj = obj.parent;
- }
- return obj;
- }else{
- return _stage;
- }
- }
//搜索舞台元素 private function findDisplayObject(x:Number,y:Number):InteractiveObject{var obj:DisplayObject;var objArray:Array = _stage.getObjectsUnderPoint(new Point(x,y));if(objArray.length>0){obj=objArray[objArray.length-1];if(!(obj is InteractiveObject)){obj = obj.parent;}return obj;}else{return _stage;}}
而由于从tuio里发送过来的事件都是以TUIO自己习惯进行编号的,为了防止与本地的触摸冲突,我们需要给每个触摸点一个本地的ID,本地的触摸编号从1开始到255结束,我们就从256开始,上限随你设定,尽管你设置的上限足够大,但是必须为其准备一个超出上限了就返回-1的默认值
- private function getFreeID():int{
- for(var i:int=256;i<1024;i++){
- var used:Boolean=false;
- for each(var temp:TuioObject in _touchList){
- used = i == temp.id;
- }
- if(!used)return i;
- }
- return -1;
- }
private function getFreeID():int{for(var i:int=256;i<1024;i++){var used:Boolean=false;for each(var temp:TuioObject in _touchList){used = i == temp.id;}if(!used)return i;}return -1;}
为了让程序更清晰一点,我们将 触摸点生效、触摸点移动、触摸点消失 三个状态的处理函数分开来写。
- //应用新的触摸点
- private function addTouch(touchPoint:TuioObject):void{
- touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);
- if(touchPoint.target == _stage){
- _stage.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,
- true,false,touchPoint.id,false,touchPoint.x,touchPoint.y));
- }else{
- var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));
- touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,
- true,false,touchPoint.id,false,local.x,local.y));
- }
- }
- //触摸点移动
- private function moveTouch(touchPoint:TuioObject):void{
- var oldTarget:InteractiveObject = touchPoint.target;
- touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);
- var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));
- if(touchPoint.target == oldTarget){
- oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,
- true,false,touchPoint.id,false,local.x,local.y));
- }else{
- var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));
- oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,
- true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));
- touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,
- true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));
- touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,
- true,false,touchPoint.id,false,local.x,local.y));
- }
- }
- //触摸点消失
- private function removeTouch(touchPoint:TuioObject):void{
- var oldTarget:InteractiveObject = touchPoint.target;
- touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);
- var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));
- if(touchPoint.target == oldTarget){
- oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,
- true,false,touchPoint.id,false,local.x,local.y));
- }else{
- var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));
- oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,
- true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));
- touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,
- true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));
- touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,
- true,false,touchPoint.id,false,local.x,local.y));
- }
- bsp; }
//应用新的触摸点private function addTouch(touchPoint:TuioObject):void{touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);if(touchPoint.target == _stage){_stage.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,true,false,touchPoint.id,false,touchPoint.x,touchPoint.y));}else{var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_BEGIN,true,false,touchPoint.id,false,local.x,local.y));}}//触摸点移动private function moveTouch(touchPoint:TuioObject):void{var oldTarget:InteractiveObject = touchPoint.target;touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));if(touchPoint.target == oldTarget){oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,true,false,touchPoint.id,false,local.x,local.y));}else{var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_MOVE,true,false,touchPoint.id,false,local.x,local.y));}}//触摸点消失private function removeTouch(touchPoint:TuioObject):void{var oldTarget:InteractiveObject = touchPoint.target;touchPoint.target = findDisplayObject(touchPoint.x,touchPoint.y);var local:Point = touchPoint.target.globalToLocal(new Point(touchPoint.x,touchPoint.y));if(touchPoint.target == oldTarget){oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,true,false,touchPoint.id,false,local.x,local.y));}else{var old:Point = oldTarget.globalToLocal(new Point(touchPoint.x,touchPoint.y));oldTarget.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT,true,false,touchPoint.id,false,old.x,old.y,NaN,NaN,NaN,touchPoint.target));touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER,true,false,touchPoint.id,false,local.x,local.y,NaN,NaN,NaN,touchPoint.target));touchPoint.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_END,true,false,touchPoint.id,false,local.x,local.y));}}
最后 关键的处理TUIO的xml消息的函数
- //解析消息
- private function processMessage(msg:XML):void{
- //点是否存在 不存在则从列表中移除
- var node:XML;
- var touch:TuioObject;
- for each(node in msg.MESSAGE)
- {
- if(node.ARGUMENT[0].@VALUE == "alive")
- {
- for each (touch in _touchList)touch.isExist=false;
- for each(var aliveItem:XML in node.ARGUMENT.(@VALUE != "alive"))
- {
- touch = searchByRemoteName(int(aliveItem.@VALUE));
- if(touch){
- touch.isExist=true;
- }
- }
- }
- }
- //处理事件
- var remoteID:int;
- var x:Number;
- var y:Number;
- var touchObj:TuioObject;
- for each(node in msg.MESSAGE)
- {
- if(node.ARGUMENT[0] && node.@NAME == "/tuio/2Dcur")
- {
- if(node.ARGUMENT[0].@VALUE == "set")
- {
- remoteID = int(node.ARGUMENT[1].@VALUE);
- x = Number(node.ARGUMENT[2].@VALUE) * _stageWidth;
- y = Number(node.ARGUMENT[3].@VALUE) * _stageHeight;
- touchObj=searchByRemoteName(remoteID);
- if(!touchObj){
- var id:int = getFreeID();
- if(id == -1)return;
- touchObj = new TuioObject(id,x,y);
- touchObj.remoteID = remoteID;
- _touchList.push(touchObj);
- addTouch(touchObj);
- }else{
- touchObj.x = x ;touchObj.y = y;
- moveTouch(touchObj);
- }
- }
- }
- }
- //处理不存在的点
- for(var i:int=_touchList.length-1;i>=0;i--){
- if(!_touchList[i].isExist){
- removeTouch(_touchList[i]);
- _touchList.splice(i,1);
- }
- }
- }
AS3中将TUIO协议转换到传统触摸事件相关推荐
- h5滚动时侧滑出现_HTML5移动端触摸事件以及滑动翻页效果
HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享.今天为大家介绍的事件主 ...
- 移动端触屏网页的触摸事件
PC端网页从无到有发展至今,人们习惯了鼠标与键盘的人机交互模式,因此在PC端网页开发中一般使用鼠标事件和键盘事件. mouse事件: onclick事件:在单击鼠标左键或右键时发生. ondouble ...
- iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控
-- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...
- 移动开发:iphone开发之触摸事件详解
转:http://blog.sina.com.cn/s/blog_8988732e01012eaf.html iPhoneOS中的触摸事件基于多点触摸模型.用户不是通过鼠标和键盘,而是通过触摸设备的屏 ...
- Android Studio笔记4.2 安卓触摸事件
文章目录 一.前言 二.笔记4.2 安卓触摸事件 (一)安卓触摸事件概述 1.触摸分类 (1).单点触摸 (2).多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸 ...
- 3.2 安卓触摸事件
文章目录 一.安卓触摸事件概述 1.触摸分类 (1)单点触摸 (2)多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸事件处理机制 二.案例演示:通过单点触摸移动米 ...
- Android基础学习笔记13:安卓触摸事件触摸按键
学习目标 了解安卓触摸动作 熟悉触摸监听器与方法 掌握单点触摸与多点触摸 在Android系统中,触摸是用户最常用,最基础的交互方式,只有弄通触摸事件在系统中的传递处理机制才能更好地增强用户的交互体验 ...
- Android Studio 笔记4.2 安卓触摸事件
文章目录 一.前言 二.笔记4.2 安卓触摸事件 (一)安卓触摸事件概述 1.触摸分类 (1).单点触摸 (2).多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸 ...
- Android Studio学习:安卓触摸事件
(一)安卓触摸事件概述 1.触摸分类 (1)单点触摸 单点触控,只能识别和支持每次一个手指的触控.点击,若同时有两个以上的点被触碰,就不能做出正确反应.很多医院.图书馆等的大厅都有这种触控技术的电脑, ...
- 4.2 安卓触摸事件
文章目录 一.简介 二.概述 (一)安卓触摸事件概述 1.触摸分类 (1)单点触摸 (2)多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸事件处理机制 (二)案例 ...
最新文章
- VUE中让由全局变量添加生成的新数组不随全局变量的变化而变化
- redmine3.3.1安装与常用插件安装
- “sockaddr_in”:“struct”类型重定义
- 开课吧python视频百度云-做摄影2年,工资5000,兼职2W...
- javabean简述
- 更新Oracle的Date字段
- 腾讯游戏学院专家分析:Unity在移动设备的GPU内存机制
- JavaScript文档对象模型DOM节点操作之兄弟节点(4)
- 【动漫推荐】Specail A--特优生
- Chrome拓展插件篇
- mysql省市联动_sql全国 省市 联动级联
- android自定义系统屏保Dream
- 2020浙江省赛打铁记
- 【漏洞扫描与复现】Kali之Metasploit渗透测试
- 木瓜移动再求上市:毛利率走低、盈利能力弱,沈思“迷恋”相亲
- android堆内存解析,heapsnap HeapSnap 是一款针对 Android 进程堆内存进行追踪、定位,以便查出泄露位置的工具 @codeKK c开源站...
- 单片机C语言中的位运算符,单片机c语言教程第八课 运算符和表达式(位运算符)...
- 如何利用pyecharts绘制酷炫的桑基图?
- 《护理教育学》名词解释、简答题、问答题汇总
- Android实现网页图片下载器