zoukankan      html  css  js  c++  java
  • react实现自定义hooks(移动端拖拽)

    实现思路

    通过touchstart、touchmove、touchend组合,实现过程中需要注意以下几个问题

    1. touchmove、touchend事件需要绑定在window上,并且这两个事件需要包在touchstart中
    2. touchstart事件需要阻止冒泡和禁止默认事件,开始监听touchmove和touchmove。组件销毁前要记得移除事件监听
    3. touchend事件里要移除事件监听
    4. touchmove计算位置值,弄清楚event.clientX和element.offsetTop等关系
    5. 定位不要使用position,应该使用transform的translate

    在线预览

    react移动端拖拽hooks

    核心代码

    import { useEffect, useState, useRef } from "react";
    import "./styles.css";
    /***
     * 请在移动端查看
     */
    const docWidth = document.documentElement.clientWidth;
    const docHeight = document.documentElement.clientHeight;
    
    export default function useMobileDrag(props) {
      const touchStartX = useRef(0);
      const touchStartY = useRef(0);
      const [x, setX] = useState(0);
      const [y, setY] = useState(0);
    
      const { targetDomRef } = props;
    
      useEffect(() => {
        if (!targetDomRef?.current) {
          return;
        }
    
        const target = targetDomRef.current;
        const { width, height } = target.getBoundingClientRect();
        const touchmove = (e) => {
          const { clientX, clientY } = e.targetTouches[0];
          if (clientX - touchStartX.current >= docWidth - width) {
            setX(docWidth - width);
          } else if (clientX - touchStartX.current <= 0) {
            setX(0);
          } else {
            setX(clientX - touchStartX.current);
          }
          if (clientY - touchStartY.current >= docHeight - height) {
            setY(docHeight - height);
          } else if (clientY - touchStartY.current <= 0) {
            setY(0);
          } else {
            setY(clientY - touchStartY.current);
          }
        };
        const touchend = () => {
          window.removeEventListener("touchmove", touchmove);
          window.removeEventListener("touchend", touchend);
        };
        const touchstart = (e) => {
          e.stopPropagation();
          e.preventDefault();
          const { top, left } = target?.getBoundingClientRect();
          const { clientX, clientY } = e.targetTouches[0];
          touchStartX.current = clientX - left;
          touchStartY.current = clientY - top;
    
          window.addEventListener("touchmove", touchmove);
          window.addEventListener("touchend", touchend);
        };
        target.addEventListener("touchstart", touchstart);
        return () => {
          target.removeEventListener("touchstart", touchstart);
        };
      }, [targetDomRef]);
      return { x, y };
    }
    
    
  • 相关阅读:
    SpringMVC,3种不同的URL路由配置方法(这根本不是一个小问题)
    PHP在Windows下安装配置第一步
    跟我一起学extjs5(18--模块的新增、改动、删除操作)
    html image -- data:image/png;base64
    oc66--代理模式应用2
    oc65--协议应用1,接口.做数据类型限定
    oc64--协议2@protocol
    oc63--协议@protocol1
    oc62--block1
    oc61--block
  • 原文地址:https://www.cnblogs.com/xingguozhiming/p/15777906.html
Copyright © 2011-2022 走看看