"pointermove"事件无法与触摸配合使用.为什么不? [英] `pointermove` event not working with touch. Why not?

查看:210
本文介绍了"pointermove"事件无法与触摸配合使用.为什么不?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这支笔:

https://codepen.io/anon/pen/eyKeqK

如果您在触摸屏设备上进行尝试(例如,通过手机上的 ),您会注意到,拖动时,白光(小球)仅移动了一点点,然后停止工作.

If you try it on a touch-screen device (f.e. visit the pen on your phone) you'll notice that when you drag, the white light (the little sphere) only moves for a tiny bit then it stops working.

移动的逻辑在pointermove事件处理程序中.使用鼠标(而不是触摸),它可以在桌面上正常工作.

The logic for the movement is in the pointermove event handler. It works fine on Desktop using a mouse, just not with touch.

我们如何解决此问题,以使光线在触摸拖动时保持移动(不只是一小会儿),并且作为奖励,我们如何防止下拉时刷新页面?

How do we fix this so the light keeps moving while touch dragging (not just for a moment), and as bonus how do we prevent it from refreshing the page when we pull down?

这是笔的代码:

HTML(精简版):

/! Made with http://github.com/trusktr/infamous

script src="https://cdn.rawgit.com/trusktr/e37dbc24c51b9d3e2f9e508e75cf8f99/raw/2a3fee4ee506a05cc4ac509f592f0c3af1ddfed4/infamous-mixed-mode-3.js"
script src="https://unpkg.com/tween.js@16.6.0/src/Tween.js"

i-scene experimental-webgl="true" id="scene" TODO-perspective="800" backgroundColor="0 0 0" backgroundOpacity="0" style="perspective: 800px" shadowmap-type="pcfsoft"

    i-ambient-light color="#404040" intensity="1"

    i-dom-plane id="bg" sizeMode="proportional proportional" size="1 1 0"

        i-node id="button-container" position="0 0 6" size="600 31 0" align="0.5 0.5 0" mountPoint="0.5 0.5 0"

            - for n in (0..4)
                i-dom-plane sizeMode="literal proportional" size="100 1 0" align="#{n*0.25} 0 0" mountPoint="#{n*0.25} 0 0"
                    button button #{n+1}

        i-point-light id="light" color="white" position="300 300 120" size="0 0 0" cast-shadow="true" intensity="1"
            i-mesh has="sphere-geometry basic-material" size="10 10 10" color="white" receive-shadow="false" cast-shadow="false" style="pointer-events: none"

CSS(手写笔):

body, html
    width 100%
    height 100%
    margin 0
    padding 0
    font-family sans-serif

i-node
    text-align center

#bg
    background #62B997

button
    width 100%
    height 100%
    white-space nowrap
    border-radius 0px
    border 1px solid #534334
    background lighten(#FB752C, 20%)
    color darken(#534334, 10%)
    outline none // remove those darn ugly browser-specific outlines
    &:focus, &:hover
        background #FB752C
        color darken(#534334, 20%)

JavaScript:

infamous.html.useDefaultNames()
const Motor = infamous.core.Motor

light.threeObject3d.shadow.radius = 3
light.threeObject3d.distance = 20000
light.threeObject3d.shadow.bias = 0.00001

document.addEventListener('pointermove', e => {
    e.preventDefault()
    light.position.x = e.clientX
    light.position.y = e.clientY
})

let downTween, upTween, pressedButton

// On mouse down animate the button downward
document.addEventListener('pointerdown', e => {
    if ( is( e.target, 'button' ) ) {

        pressedButton = e.target

        if (upTween) {
            upTween.stop()
            upTween = null
        }

        downTween = new TWEEN.Tween(e.target.parentNode.position)
            .to({z: -6}, 75)
            .start()
            .onComplete(() => downTween = null)

        Motor.addRenderTask(time => {
            if (!downTween) return false
            downTween.update(time)
        })

    }
})

// On mouse up animate the button upward
document.addEventListener('pointerup', e => {
    if ( pressedButton ) {

        if (downTween) {
            downTween.stop()
            downTween = null
        }

        upTween = new TWEEN.Tween(pressedButton.parentNode.position)
            .to({z: 0}, 75)
            .start()
            .onComplete(() => upTween = null)

        Motor.addRenderTask(time => {
            if (!upTween) return false
            upTween.update(time)
        })

    }
})

// The following is a temporary hack because opacity isn't
// exposed through the HTML API yet. work-in-progress...
setTimeout(() => {
    Array.from( document.querySelectorAll('i-dom-plane') ).forEach(n => {
        n.threeObject3d.material.opacity = 0.3
    })

    scene._needsToBeRendered()
}, 0)

function is( el, selector ) {
    if ( [].includes.call( document.querySelectorAll( selector ), el ) ) return true
    return false
}

推荐答案

在有关pointermove的MDN文档页面上,有以下一行:

On the MDN documentation page about pointermove, there's this line:

当指针更改坐标且未通过浏览器触摸操作取消指针时,将触发pointermove事件.

,重点是我的 >

source, emphasis mine

短时间后,(移动)浏览器将声明pointermove事件用于自然"行为,例如平移页面.

After a short period of time, the (mobile) browser will claim the pointermove event for "native" behavior like panning the page.

设计简单的解决方案是使用css属性 touch-action ,并在具有事件处理程序的容器上将其设置为none.

The designed, simple solution is to use the css property touch-action and set it to none on the container that has the event handler.

这是添加到您的代码笔中的css属性: https://codepen.io/anon/pen/XVBMvL

Here's the css property added to your codepen: https://codepen.io/anon/pen/XVBMvL

或者在一个简化的示例中:

Or in a simplified example:

  • 将浏览器设置为模拟触摸(在Chrome浏览器中,开发工具>传感器>触摸)
  • 在左侧开始互动,点将跟随您的手指
  • 在右侧开始互动,您会发现它会迅速失败,就像在提供的示例中一样

var dot = document.querySelector(".dot")
document.body.addEventListener("pointermove", function(ev) {
  dot.style.transform = `translate3d(${ev.clientX}px, ${ev.clientY}px, 0)`;

}, false);

* { margin: 0; padding: 0 }

.wrapper { 
  display: flex; 
  height: 100vh;
}

.hasTouchAction, 
.noTouchAction {
  flex-grow: 1;
  text-align: center;
  background: #efefef;
}

.hasTouchAction {
  touch-action: none;
}

.noTouchAction {
  background: #ccc;
}

.dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: red;
  position: absolute;
  top: -8px;
  left: -8px;
}

<div class="wrapper">
  <div class="hasTouchAction">
    With <code>touch-action: none</code>
  </div>

  <div class="noTouchAction">
    Without <code>touch-action</code>
  </div>
</div>

<div class="dot"></div>

请确保您不会破坏重要的事情并不会损害可访问性.还花一些时间调查浏览器支持.这对我来说适用于Chrome中的触摸模拟事件,但可能不适用于所有浏览器...

Make sure you don't break important things and hurt accessibility. Also spend some time to investigate browser support. This worked for me with touch emulated events in Chrome, but might not work in every browser...

这篇关于"pointermove"事件无法与触摸配合使用.为什么不?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆