前面示例都只是展示在桌面浏览器显示,当用手机浏览器打开时发现无法拖动元素,虽然实际业务上,手机也只是用来查看的,但为了论证手机上的触摸事件,我还是在本节做个演示。

手机上触控有三个重要事件touchstart,touchmove,touchend,分别表示开始触摸,移动,及结束,与鼠标的mousedown,mousemove,mouseup对应。

基于前面示例代码,因此把原来mousedown,mousemove,mouseup中的代码抽象一下,Component中增加onDragStart,onDraging,onDragEnd三个方法,这样无论是鼠标还是触摸都调同样的方法,

    Component.prototype.onDragStart=function()
    {
        this.drag = true;
    }
    Component.prototype.onDraging=function(delta)
    {
        this.unselect(); //取消选中状态
        if (this.connector) //在拖动元素时如果有连线指示器则清除。
        {
            this.destroy();
            this.connector = null;
        }
            this.properties.x += delta.x;
        this.properties.y += delta.y;
        this.group.translate(delta.x,delta.y);
        this.redrawLines();
        document.body.style.cursor = 'move';
    }
    Component.prototype.onDragEnd=function()
    {

    }

修改Component中原来鼠标事件的代码:

        this.group.onMouseDown = function (event) {
            if (!me.designer.lining && !me.isLine) //非画线状态才允许拖动
            if (event.event.button == 0)
                me.onDragStart();
            else if (!me.isLine)
                me.designer.lineManager.dragStart(me.connector,event.point)
        }
        this.group.onMouseUp = function (event) {
            if (me.drag){
                me.drag = false;
                me.onDragEnd()
            }
            else  if (me.designer.lining && me.connector){
                me.designer.lineManager.dragEnd(me.connector,event.point)
             }

            document.body.style.cursor = 'default';
        }
        this.group.onMouseDrag = function (event) {
            if (me.drag && !me.designer.lining) //非画线状态才允许拖动
            {
                me.onDraging(event.delta)
            }
        }

这样修改后,鼠标操作(拖动组件移动位置)还是与原来一致,那现在我们要定义触控事件,paperjs没有touch的相关事件,那解决的思路是html5的canvas元素是支持触摸事件的,通过试验发现,触控的坐标pageX是基于页面的,而我们需要相对于画布左上角,所以还需要$(this).offset()获取画布本身的偏移量,再查paperjs的说明文档,发现group.hitTest(point)就是我们想要,遍历所有组件,找到触控位置的组件,然后调用组件的方法,代码如下:(为了调试,在触摸移动时输出当前坐标)

var touchComponent=null; //当前拖动的组件
        var touchPos=null; //上次位置
        this.$element.on("touchstart",function(event){
            event.preventDefault();
            var touch=event.originalEvent.touches[0]||event.originalEvent.changedTouches[0];
            var offset=$(this).offset();
            $.each(me.nodes,function(idx,val){
                try{
                    if(val.group){
                        var group=val.group.hitTest([touch.pageX-offset.left,touch.pageY-offset.top])
                        if (group)
                        {
                            if (!me.textPos)
                                me.textPos = new paper.PointText({
                                    point: [20, 40],
                                    content: '拖动:x:'+touch.pageX+",y:"+touch.pageY,
                                    fillColor: 'blue',
                                    fontFamily: '宋体',
                                    fontWeight: 'bold',
                                    fontSize: 14
                                });
                            else
                                me.textPos.set({ content: '拖动:x:'+touch.pageX+",y:"+touch.pageY})
                            touchPos={x:touch.pageX-offset.left,y:touch.pageY-offset.top};
                            touchComponent=val;
                            val.onDragStart();
                            return false;
                        }
                    }
                }
                catch(e){
                    me.textPos = new paper.PointText({
                        point: [20, 40],
                        content: '错误:'+e,
                        fillColor: 'blue',
                        fontFamily: '宋体',
                        fontWeight: 'bold',
                        fontSize: 14
                    });
                }
            })
        })
        this.$element.on("touchmove",function(event){
            event.preventDefault();
            if (touchComponent)
            {
                var touch=event.originalEvent.touches[0]||event.originalEvent.changedTouches[0];
                var offset=$(this).offset();
                //当前位置减去上次位置,获得偏移量
                var delta={x:touch.pageX-offset.left-touchPos.x,y:touch.pageY-offset.top-touchPos.y};
                touchComponent.onDraging(delta);
                touchPos={x:touch.pageX-offset.left,y:touch.pageY-offset.top};//当前位置
            }

        })
        this.$element.on("touchend",function(event){
            event.preventDefault();
            if (touchComponent)
            {
                touchComponent.onDragEnd()
                touchComponent=null;
            }

        })

发布到网站上,用手机浏览器看看,是不是就可以触控拖动元素了,而且连线也会跟随重绘呢?

后记:当然我们也可以更进一步的增加比如将组件拖动到画布上,删除等效果,只是逻辑类似,本节就不再演示了。

源代码:sample.1.10.rar

直接运行查看

(本文为原创,在引用代码和文字时请注明出处)

 
关键字
:设计器源代码,Web设计器,工作流设计器,jQuery插件,组态设计器,SCADA系统设计器,流程图设计,表单设计建模,报表设计,可视化,设计时,运行时,轻量级开放平台。