首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Node-webkit触摸Mithril

使用Node-webkit触摸Mithril
EN

Stack Overflow用户
提问于 2017-02-03 14:43:39
回答 1查看 199关注 0票数 1

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

代码语言:javascript
复制
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'。启动应用程序,我可以看到一切都在通过控制台进行注册,然而,在我的主代码中,我想使用该触摸数据:

代码语言:javascript
复制
const app = {
  view: vnode => {
    return m('.main', {config: m.touchHelper({ 'tap': consoleLog})
  }
}

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

但是,此函数不会被触发。

EN

回答 1

Stack Overflow用户

发布于 2018-01-16 16:51:35

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

使用带有config属性的m.touchHelper似乎也很奇怪。执行此操作时:

代码语言:javascript
复制
return m('.main', {config: m.touchHelper({'tap': consoleLog})})

生成的DOM元素如下所示:

代码语言:javascript
复制
<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更改为如下所示:

代码语言:javascript
复制
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生命周期方法中调用它:

代码语言:javascript
复制
const app = {
    oncreate(vnode) {
        m.touchHelper(vnode, {'tap': consoleLog});
    },
    view: vnode => {
        return m('.main');
    }
};

然后,它似乎起作用了。See JSFiddle with updated code.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42018254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档