简体   繁体   English

使用Node-webkit触摸Mithril

[英]Touch for Mithril with Node-webkit

I've been trying to get mithril touch to work using a good code on github: https://gist.github.com/webcss/debc7b60451f2ad2af41 我一直在尝试使用github上的一个好代码让mithril触摸工作: 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);
                });
            };
        }
    };        
};

The only thing I've added is import m from 'mithril' . 我添加的唯一一件事是import m from 'mithril' Launching the app I can see that everything is registering as should through the console, however, in my main code I want to use that touch data: 启动应用程序我可以看到所有内容都通过控制台注册,但是,在我的主代码中我想使用该触摸数据:

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

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

However, this function is not triggered. 但是,不会触发此功能。

I don't know how much Mithril has changed since February 2017 (I have only recently picked up Mithril), but that m.touchHelper seems weird. 我不知道Mithril自2017年2月以来有多少变化(我最近才拿起Mithril),但那个m.touchHelper似乎很奇怪。 What are element , initialized and context ? 什么是elementinitializedcontext Why is a function returned; 为什么返回一个函数; is it ever called? 它被称为?

Using m.touchHelper with the config attribute seems also weird. 使用带有config属性的m.touchHelper似乎也很奇怪。 When you do this: 当你这样做:

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

the resulting DOM element looks like this: 生成的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. 请参阅JSFiddle和您的代码。 (Note that I added missing }) to the end of app 's view method.) (注意我添加了缺失})appview方法的末尾。)


I would change m.touchHelper to something like this: 我会把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
};

And call it in a component's oncreate lifecycle method: 并在组件的oncreate生命周期方法中调用它:

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

Then it seems to work. 然后它似乎工作。 See JSFiddle with updated code. 请参阅JSFiddle更新的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM