Touchmove disables several schemes for default scrolling

preface

Share some problems and solutions encountered in the actual development process, if there is any mistake in the article, you are also welcome to point out, mutual encouragement. !

Personal Blog Address🍹 🍰 fe – code

background

From a recent mobile terminal need to use the TouchMove event to trigger the animation of the lantern. However, in actual operation, it is found that it is easy to trigger the vertical scrolling of the page itself when sliding the revolving light, as shown in the figure below

Note: here use Overflow: Auto to simulate a revolving lamp, only do the touchmove test.

It can be seen that in the sliding process, once the sliding direction deviates to the vertical direction, it will trigger the vertical scrolling of the page.

plan

Passive event listeners

Since vertical scrolling is triggered by the TouchMove event, it was easy to think of disabling the event’s default behavior with e.preventDefault(), and easy to change the code.

function Touch() {
    const startTouchRef = useRef({x: 0.y: 0});
    // Save the initial location
    function onTouchStart(e) {
        startTouchRef.current = { x: e.touches[0].pageX, y: e.touches[0].pageY };
    }
    // Restrict vertical scrolling
    function onTouchMove(e) {
        const y = Math.abs(e.touches[0].pageY - startTouchRef.current.y);
        const x = Math.abs(e.touches[0].pageX - startTouchRef.current.x);
        // Simply determine whether the sliding direction is inclined to y or x
        // Disable x scrolling by default, because x scrolling is done via Touchmove or CSS animation
        if(y < x) { e.preventDefault(); }}return (
        <div onTouchStart={onTouchStart}
             onTouchMove={onTouchMove}>
            // ...
        </div>)}Copy the code

It’s easy to get an error in the end.

Is human error, let’s go to see www.chromestatus.com/features/50… This url.

Passive listener is false by default, but Chrome 56 has changed the touchStart and touchMove parameters to passive: true. This way, the TouchMove event does not block the scrolling of the page. In passive: false, no matter whether e.preventDefault() needs to be called to prevent scrolling, the page will not react until the touchmove function is completed.

Take a simple test.

// Does not prevent the page from scrolling, only increases the event processing time
function Touch() {
    const ref = useRef(null);
    function onTouchMove(e) {
        console.time();
        let index = 0;
        for (let i = 0; i< 1000000000; i++) {
            index++;
        }
        console.timeEnd();
    }
    useEffect(() = > {
        ref.current.addEventListener('touchmove', onTouchMove, { passive: false });
        return () = > {
            ref.current.removeEventListener('touchmove', onTouchMove, { passive: false}); }; } []);return (
        <div >
            // ...
        </div>)}Copy the code

The response to each swipe is noticeably slow because the browser doesn’t know whether to disable default scrolling until the TouchMove is complete. With passive set to true, the browser will disregard the possibility of disabling the default behavior and immediately trigger the page behavior.

Of course, if you really want to prevent the default behavior, as I did with my previous requirement, you need to manually set Passive to false and otherwise use preventDefault. Either way, however, we need to optimize our executing code to minimize the time code runs. Otherwise, you will also see the following warnings:

With regard to passive event listening, more optimization is done on the mobile side, and there seems to be less processing on the PC side. Here I only tested mouseWheel in Chrome 74 on PC. Although passive: True was set, the scrolling behavior of the page was not triggered preferentially. However, in mobile mode, yes. If you’re interested, you can test it yourself.

Chrome 56 supports passive, so you may need to do a compatibility test when using it. The code comes from MDN.

// If options is set to passive, passive is supported
var passiveSupported = false;

try {
  var options = Object.defineProperty({}, "passive", {
    get: function() {
      passiveSupported = true; }});window.addEventListener("test".null, options);
} catch(err) {}

someElement.addEventListener("mouseup", handleMouseUp, passiveSupported
                               ? { passive: true } : false);
Copy the code

touch-action

An area that sets up how the touch screen user manipulates elements (for example, the browser’s built-in zoom function). – MDN

This is a CSS property, which simply means that you can specify the gestures that the user is allowed to use.

  • Pan-x enables the one-finger horizontal panning gesture
  • Pan-y enables the one-finger vertical panning gesture
  • None Disallows operations

Other attributes, you can go to MDN to check. For our needs, a similar effect can be achieved by using pan-Y to open only the vertical direction. Please note that the touch-action function is the same as the passive: false function and preventDefault function. It will not be optimized for sliding in the allowed direction.

In addition, this property has compatibility issues and does not work well in Safari. See Can I Use for details.

overflow

To disable scrolling for an element, add overflow: Hidden to its parent element to achieve the desired effect. For the entire page, add overflow: Hidden to the HTML tag. However, based on the current requirements scenario, you need to decide when to set the properties and when to remove them, since you only want to scroll horizontally without triggering vertical scrolling.

I’m not doing this test here, but just to give you an idea.

Communication group

Qq front-end communication group: 960807765, welcome all kinds of technical exchanges, looking forward to your joining;

Wechat group: Students in need can add my wechat (Q1324210213), I will pull you into the group.

Afterword.

If you see here, and this article is a little help to you, I hope you can move a small hand to support the author, thank 🍻. If there is something wrong in the article, we are welcome to point out and encourage each other. Thanks for reading. See you next time!

  • The article warehouse 🍹 🍰 fe – code
  • Social chat system (vue + Node + mongodb) – 💘🍦🙈Vchat

Interested students can pay attention to my public number front-end engine, fun and material.