برنامه نویسی

نحوه ردیابی حرکت ماوس و لمس در حالت فشرده با React

در یوتیوب تماشا کنید | 🐙 گیت هاب | 🎮 نسخه ی نمایشی

وقتی رابط‌های کاربری تعاملی پیچیده‌ای مانند لغزنده، ویرایشگر یا انتخابگر رنگ می‌سازیم، اغلب نیاز داریم که حرکت ماوس یا لمس را در حالت فشرده ردیابی کنیم. اجازه دهید یک جزء انتزاعی با کاربرد آسان را که دقیقاً برای این منظور طراحی شده است به اشتراک بگذارم.

نسخه ی نمایشی از ReactKit

جزء PressTracker

مؤلفه دو ویژگی دریافت می کند:

  • render – تابعی که جزء مصرف کننده باید از آن برای ارائه محتوا استفاده کند. یک شی را با props و position خواص این props فیلد حاوی ref و دسته‌های شروع موس و لمسی، باید به عنصر ظرف منتقل شود. این position یک نقطه با x و y مختصات در محدوده 0 تا 1. نشان دهنده موقعیت نسبی مکان نما در داخل ظرف است. در تمام موارد عملی من، نیاز به دانستن موقعیت نسبی داشتم، بنابراین تصمیم گرفتم از آن به عنوان پیش فرض استفاده کنم.
  • onChange – تابعی که با تغییر موقعیت فراخوانی می شود. یک شی را با همان دریافت می کند position بحث و جدل. توجه داشته باشید زمانی که منشاء پرس خارج از ظرف باشد، موقعیت آن خواهد بود null.
import { Point } from "lib/entities/Point"
import { useBoundingBox } from "lib/shared/hooks/useBoundingBox"
import { enforceRange } from "lib/shared/utils/enforceRange"
import {
  MouseEvent,
  MouseEventHandler,
  ReactNode,
  TouchEvent,
  TouchEventHandler,
  useCallback,
  useEffect,
  useState,
} from "react"
import { useEvent } from "react-use"

interface ContainerProps {
  onMouseDown: MouseEventHandler<HTMLElement>
  onTouchStart: TouchEventHandler<HTMLElement>
  ref: (node: HTMLElement | null) => void
}

interface ChangeParams {
  position: Point | null
}

interface RenderParams extends ChangeParams {
  props: ContainerProps
}

interface PressTrackerProps {
  render: (props: RenderParams) => ReactNode
  onChange?: (params: ChangeParams) => void
}

export const PressTracker = ({ render, onChange }: PressTrackerProps) => {
  const [container, setContainer] = useState<HTMLElement | null>(null)
  const box = useBoundingBox(container)

  const [position, setPosition] = useState<Point | null>(null)

  const handleMove = useCallback(
    ({ x, y }: Point) => {
      if (!box) return

      const { left, top, width, height } = box

      setPosition({
        x: enforceRange((x - left) / width, 0, 1),
        y: enforceRange((y - top) / height, 0, 1),
      })
    },
    [box]
  )

  const handleMouse = useCallback(
    (event: MouseEvent) => {
      handleMove({ x: event.clientX, y: event.clientY })
    },
    [handleMove]
  )

  const handleTouch = useCallback(
    (event: TouchEvent) => {
      const touch = event.touches[0]
      if (touch) {
        handleMove({ x: touch.clientX, y: touch.clientY })
      }
    },
    [handleMove]
  )

  useEffect(() => {
    if (onChange) {
      onChange({ position })
    }
  }, [onChange, position])

  const clearPosition = useCallback(() => {
    setPosition(null)
  }, [])
  useEvent("mouseup", position ? clearPosition : undefined)
  useEvent("touchend", position ? clearPosition : undefined)
  useEvent("mousemove", position ? handleMouse : undefined)
  useEvent("touchmove", position ? handleTouch : undefined)

  return (
    <>
      {render({
        props: {
          ref: setContainer,
          onMouseDown: handleMouse,
          onTouchStart: handleTouch,
        },
        position: position,
      })}
    </>
  )
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این PressTracker جزء عنصر ظرف را در useState و از useBoundingBox قلاب را برای به دست آوردن موقعیت و اندازه آن. برای شروع فرآیند ردیابی، جزء مصرف کننده باید رندر شود PressTracker جزء و پروپ های لازم را به عنصر ظرف منتقل کنید.

<PressTracker
  render={({ props, position }) => (
    <Container {...props}>
      {position && (
        <Highlight
          style={{
            width: toPercents(position.x),
            height: toPercents(position.y),
          }}
        />
      )}
    </Container>
  )}
/>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما موقعیت را روی هر یک از ماوس به پایین در رویدادهای شروع لمسی تنظیم می کنیم. بنابراین هنگامی که کاربر با کانتینر تعامل کرد، ما شروع به ردیابی موقعیت مکان نما می کنیم useEvent قلاب از react-use کتابخانه گوش می دهد برای mouseup و touchend رویدادها برای توقف ردیابی، و همچنین mousemove و touchmove رویدادها برای به روز رسانی موقعیت مکان نما. این handleMove تابع، مختصات مطلق را از رویدادهای لمسی و ماوس تبدیل می کند، و اطمینان می دهد که مختصات در محدوده باقی می مانند 0 به 1، حتی زمانی که مکان نما خارج از ظرف است.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا