【问题标题】:Touch for Mithril with Node-webkit使用 Node-webkit 触摸秘银
【发布时间】:2017-02-03 06:43:38
【问题描述】:

我一直在尝试使用 github 上的一个好的代码让 mithril touch 工作: https://gist.github.com/webcss/debc7b60451f2ad2af41

import m from 'mithril'

/*****************************************
/* DOM touch support module
/*****************************************/
if (!window.CustomEvent) {
    window.CustomEvent = function (event, params) {
        params = params || { bubbles: false, cancelable: false, detail: undefined };
        var evt = document.createEvent('CustomEvent');
        evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
        return evt;
    };
    window.CustomEvent.prototype = window.Event.prototype;
}

(function(document) {
    var TAPTRESHOLD = 200, // time within a double tap should have happend
        TAPPRECISION = 60 / 2, // distance to identify a swipe gesture
        touch = { },
        tapCount = 0, // counts the number of touchstart events
        tapTimer = 0, // timer to detect double tap
        isTouchSwipe = false, // set to true whenever 
        absolute = Math.abs,
        touchSupported = 'ontouchstart' in window;

    function parentIfText (node) {

        return 'tagName' in node ? node : node.parentNode;
    }

    function dispatchEvent(type, touch) {
        if(touchSupported) {
            touch.originalEvent.preventDefault();
            touch.originalEvent.stopImmediatePropagation();
        }
        var event = new CustomEvent(type, {
            detail: touch,
            bubbles: true,
            cancelable: true
        });
        touch.target.dispatchEvent(event);
        console.log(type);

        touch = { };
        tapCount = 0;

        return event;
    }

    function touchStart(e) {
        if( !touchSupported || e.touches.length === 1) { 
            var coords = e.targetTouches ? e.targetTouches[0] : e;
            touch = {
                originalEvent: e,
                target: parentIfText(e.target),
                x1: coords.pageX,
                y1: coords.pageY,
                x2: coords.pageX,
                y2: coords.pageY
            };
            isTouchSwipe = false;
            tapCount++;
            if (!e.button || e.button === 1) {
                clearTimeout(tapTimer);
                tapTimer = setTimeout(function() {
                    if(absolute(touch.x2 - touch.x1) < TAPPRECISION &&
                       absolute(touch.y2 - touch.y2) < TAPPRECISION &&
                       !isTouchSwipe) {
                        dispatchEvent((tapCount===2)? 'dbltap' : 'tap', touch);
                        clearTimeout(tapTimer);
                    }
                    tapCount = 0;
                }, TAPTRESHOLD); 
            }
        }
    }

    function touchMove(e) {
        var coords = e.changedTouches ? e.changedTouches[0] : e;
        isTouchSwipe = true;
        touch.x2 = coords.pageX;
        touch.y2 = coords.pageY;
        /* the following is obsolete since at least chrome handles this 
        // if movement is detected within 200ms from start, preventDefault to preserve browser scroll etc. 
        // if (touch.target && 
        //         (absolute(touch.y2 - touch.y1) <= TAPPRECISION || 
        //          absolute(touch.x2 - touch.x1) <= TAPPRECISION)
        //     ) {   
        //         e.preventDefault();
        //         touchCancel(e);
        // }
        */
    }

    function touchCancel(e) {
        touch = {};
        tapCount = 0;
        isTouchSwipe = false;
    }

    function touchEnd(e) {
        var distX = touch.x2 - touch.x1,
            distY = touch.y2 - touch.y1,
            absX  = absolute(distX),
            absY  = absolute(distY);
        // use setTimeout here to register swipe over tap correctly,
        // otherwise a tap would be fired immediatly after a swipe
        setTimeout(function() {
            isTouchSwipe = false;
        },0);
        // if there was swipe movement, resolve the direction of swipe
        if(absX || absY) {
            if(absX > absY) {
                dispatchEvent((distX<0)? 'swipeleft': 'swiperight', touch);
            } else {
                dispatchEvent((distY<0)? 'swipeup': 'swipedown', touch);
            }
        }        
    }

    document.addEventListener(touchSupported ? 'touchstart' : 'mousedown', touchStart, false);
    document.addEventListener(touchSupported ? 'touchmove' : 'mousemove', touchMove, false);
    document.addEventListener(touchSupported ? 'touchend' : 'mouseup', touchEnd, false);
    // on touch devices, the taphold complies with contextmenu
    document.addEventListener('contextmenu', function(e) {
            e.preventDefault();
            e.stopImmediatePropagation();
            dispatchEvent('taphold', {
                originalEvent: e,
                target: parentIfText(e.target)
            });
        }, false);

    if (touchSupported) { 
        document.addEventListener('touchcancel', touchCancel, false);          
    }

}(window.document));

m.touchHelper = function(options) {
    return function(element, initialized, context) {
        if (!initialized) {
            Object.keys(options).forEach(function(touchType) {
                element.addEventListener(touchType, options[touchType], false);
            });
            context.onunload = function() {
                Object.keys(options).forEach(function(touchType) {
                    element.removeEventListener(touchType, options[touchType], false);
                });
            };
        }
    };        
};

我唯一添加的是import m from 'mithril'。 启动应用程序,我可以看到所有内容都在通过控制台注册,但是,在我的主代码中,我想使用该触摸数据:

const app = {
  view: vnode => {
    return m('.main', {config: m.touchHelper({ 'tap': consoleLog})
  }
}

function consoleLog() {
  console.log('Triggered')
}

但是,这个函数并没有被触发。

【问题讨论】:

    标签: javascript events touch node-webkit mithril.js


    【解决方案1】:

    我不知道自 2017 年 2 月以来秘银发生了多大的变化(我最近才拿起秘银),但 m.touchHelper 似乎很奇怪。 elementinitializedcontext 是什么?为什么返回一个函数;它曾经被调用过吗?

    m.touchHelperconfig 属性一起使用似乎也很奇怪。当你这样做时:

    return m('.main', {config: m.touchHelper({'tap': consoleLog})})
    

    生成的 DOM 元素如下所示:

    <div config="function(element, initialized, context) {
            if (!initialized) {
                Object.keys(options).forEach(function(touchType) {
                    element.addEventListener(touchType, options[touchType], false);
                });
                context.onunload = function() {
                    Object.keys(options).forEach(function(touchType) {
                        element.removeEventListener(touchType, options[touchType], false);
                    });
                };
            }
        }" class="main"></div>
    

    See JSFiddle with your code.(注意我在appview方法的末尾添加了缺少的})。)


    我会将m.touchHelper 更改为这样的:

    m.touchHelper = function(vnode, options) {
        if (vnode.state.initialized) return;
    
        vnode.state.initialized = true;
    
        Object.keys(options).forEach(function(touchType) {
            vnode.dom.addEventListener(touchType, options[touchType], false);
        });
    
        // Note that I removed the `context.unload` part as I'm unsure what its purpose was
    };
    

    并在组件的oncreate生命周期方法中调用它:

    const app = {
        oncreate(vnode) {
            m.touchHelper(vnode, {'tap': consoleLog});
        },
        view: vnode => {
            return m('.main');
        }
    };
    

    然后它似乎工作。 See JSFiddle with updated code.

    【讨论】:

      猜你喜欢
      • 2014-05-19
      • 2012-02-04
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 2014-05-07
      • 2015-07-24
      相关资源
      最近更新 更多