如何流畅地进行拖动或移动滑动?时间选择器 rect next js 13 应用目录

How do I smoothly do drags or mobile swipe? Time Picker Rect Next Js 13 App Dir

提问人:Inzen 提问时间:10/17/2023 更新时间:10/17/2023 访问量:38

问:

因此,我决定尝试制作自己的时间选择器组件。为什么?好吧,没有一个单一的 UI 库,用户可以向上或向下滑动以选择小时或分钟或下午 / 上午。我不需要用户选择日期,我只想要他们想要的时间。

到目前为止,我可以滚动并让用户选择向上/向下滑动的数字。问题是我正在尝试用户可以在刷卡器上移动多个数字,而不必滑动并且只能向上或向下移动 1 个数字。我还想看到数字随着用户滑动而移动。

如果我做不到这一点,我将简单地使用带有选项的选择标签,但我想避免这种情况,因为我不喜欢移动设备的外观,因为它们使用本机选择。

这是第一次尝试这样的事情,所以我也尝试使用 chatGPT 来做这件事,所以不要以为我是从头开始做的,哈哈。我以前从来没有做过这样的定制。

"use client";
import React, { useState } from "react";
import TimeSection from "./TimeSection";
export default function TimePickerModal() {
  const [isOpen, setIsOpen] = useState(false);
  const [selectedHour, setSelectedHour] = useState(12);
  const [selectedMinute, setSelectedMinute] = useState(30);

  const hours = Array.from({ length: 24 }, (_, i) => i); 
  const minutes = Array.from({ length: 60 }, (_, i) => i); 

  const handleSwipe = (
    setter: React.Dispatch<React.SetStateAction<number>>,
    values: number[],
    currentValue: number
  ) => {
    let startY: number | null = null;
    let initialValue: number | null = null; 

    return (e: React.TouchEvent<HTMLDivElement>) => {
      if (e.type === "touchstart" && e.touches.length > 0) {
        startY = e.touches[0].clientY;
        initialValue = currentValue; 
      } else if (
        e.type === "touchmove" &&
        startY !== null &&
        initialValue !== null
      ) {
        const currentY = e.touches[0].clientY;
        const diff = currentY - startY;

        const swipeSensitivity = 50;
        const unitsToMove = Math.round(diff / swipeSensitivity);

        const newValue = initialValue - unitsToMove; 

        if (newValue >= 0 && newValue < values.length) {
          setter(newValue);
        } else if (newValue < 0) {
          setter(0);
        } else if (newValue >= values.length) {
          setter(values.length - 1);
        }
      }
    };
  };
  return (
    <div>
      <button onClick={() => setIsOpen(true)}>Open Time Picker</button>

      {isOpen && (
        <div
          style={{
            position: "fixed",
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
            backgroundColor: "rgba(0,0,0,0.5)",
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <div
            style={{
              backgroundColor: "white",
              padding: "20px",
              borderRadius: "5px",
              display: "flex",
              flexDirection: "row",
              color: "black",
            }}
          >
            <TimeSection
              values={hours}
              currentValue={selectedHour}
              handleSwipe={handleSwipe(setSelectedHour, hours, selectedHour)}
            />
            <TimeSection
              values={minutes}
              currentValue={selectedMinute}
              handleSwipe={handleSwipe(
                setSelectedMinute,
                minutes,
                selectedMinute
              )}
            />
            <button
              onClick={() => {
                console.log(
                  `Selected Time: ${String(selectedHour).padStart(
                    2,
                    "0"
                  )}:${String(selectedMinute).padStart(2, "0")}`
                );
                setIsOpen(false);
              }}
            >
              Enter
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

TimeSection.tsx

import React from "react";

interface TimeSectionProps {
  values: number[];
  currentValue: number;
  handleSwipe: (e: React.TouchEvent<HTMLDivElement>) => void;
}
export default function TimeSection({
  values,
  currentValue,
  handleSwipe,
}: TimeSectionProps) {
  return (
    <div
      style={{
        height: "250px",
        width: "50px",
        overflow: "hidden",
        position: "relative",
      }}
    >
      <div
        onTouchStart={handleSwipe}
        onTouchMove={handleSwipe}
        style={{
          position: "absolute",
          top: `calc(50% - ${currentValue * 24}px)`, 
          width: "100%",
          textAlign: "center",
        }}
      >
        {values.map((value, index) => (
          <div
            key={index}
            style={{
              color: "black",
              height: "24px",
              lineHeight: "24px",
              visibility:
                index >= currentValue - 2 && index <= currentValue + 2
                  ? "visible"
                  : "hidden",
              opacity: index === currentValue ? 1 : 0.5,
              fontSize: index === currentValue ? "24px" : "18px",
            }}
          >
            {String(value).padStart(2, "0")}
          </div>
        ))}
      </div>
    </div>
  );
}

有谁知道我该如何修复,或者是否有隐藏的 npm 包 idk?希望不是,但是如果我找不到解决方案,那么我将坚持使用选择和选项标签。

reactjs next.js 触摸事件

评论


答:

1赞 HighDevWizards 10/17/2023 #1

AntD 组件支持许多组件,包括 timepicker。https://ant.design/components/time-picker

如果选中此项,则可以找到时间选择器,您只能选择时间。

评论

0赞 Inzen 10/17/2023
不要我找不到这个,但这可能就行了!多谢。
0赞 Inzen 10/18/2023
按照我想要的方式工作,一路上不得不解决一些警告,但它有效。