Как переместить элемент по оси Y на определенное значение?

Здравствуйте! Можете подсказать, как задать ограничения для перетаскиваемого объекта внутри элемента div, чтобы его движение происходило в диапазоне от 0% до 100%?   

В данный момент я могу перемещать его без ограничений вверх и вниз, но мне необходимо, чтобы он двигался от 0% вверх до 100% вниз.  

Вот фрагмент кода, который я использую:  
<code>import { useEffect, useState } from "react";</code>  
<pre><code class="typescript">const [isDragging, setIsDragging] = useState(false);
const [yTranslate, setYTranslate] = useState(0);
const [initialMousePosition, setInitialMousePosition] = useState(undefined);</code></pre>  
<pre><code class="javascript">const onMouseDown = ({ clientY }) =&gt; {
    setInitialMousePosition({ y: clientY });
    setIsDragging(true);
  };

  useEffect(() =&gt; {
    const onMouseMove = (e) =&gt; {
      setYTranslate(yTranslate + e.clientY - initialMousePosition.y);
    };
    if (isDragging) {
      window.addEventListener("mousemove", onMouseMove);
    }
    return () =&gt; window.removeEventListener("mousemove", onMouseMove);
  }, [isDragging, initialMousePosition]);

  useEffect(() =&gt; {
    const onMouseUp = () =&gt; setIsDragging(false);
    window.addEventListener("mouseup", onMouseUp);
    return () =&gt; window.removeEventListener("mouseup", onMouseUp);
  }, []);</code></pre>  
<pre><code class="javascript">&lt;div style={{"cover":  yTranslate + "%"}}&gt;
&lt;div onMouseDown={onMouseDown}&gt;Тащи меня&lt;/div&gt;
&lt;/div&gt;</code></pre>
  • 4 января 2025 г. 8:23
Ответы на вопрос 2
Чтобы ограничить перемещение элемента по оси Y в диапазоне от 0% до 100%, вам нужно добавить проверку перед тем, как обновить состояние `yTranslate`. Вы можете сделать это, используя функцию `Math.min` и `Math.max`, чтобы удостовериться, что значение остается в пределах заданного диапазона. 

Вот обновленный код с добавленными ограничениями:

```javascript
import { useEffect, useState } from "react";

const MyComponent = () => {
  const [isDragging, setIsDragging] = useState(false);
  const [yTranslate, setYTranslate] = useState(0);
  const [initialMousePosition, setInitialMousePosition] = useState(undefined);

  const onMouseDown = ({ clientY }) => {
    setInitialMousePosition({ y: clientY });
    setIsDragging(true);
  };

  useEffect(() => {
    const onMouseMove = (e) => {
      // Вычисляем новое значение yTranslate
      const newYTranslate = yTranslate + e.clientY - initialMousePosition.y;

      // Ограничиваем его в диапазоне от 0% до 100%
      const boundedYTranslate = Math.max(0, Math.min(100, newYTranslate));

      setYTranslate(boundedYTranslate);
      setInitialMousePosition({ y: e.clientY }); // Обновляем начальную позицию курсора
    };

    if (isDragging) {
      window.addEventListener("mousemove", onMouseMove);
    }
    return () => window.removeEventListener("mousemove", onMouseMove);
  }, [isDragging, initialMousePosition, yTranslate]);

  useEffect(() => {
    const onMouseUp = () => setIsDragging(false);
    window.addEventListener("mouseup", onMouseUp);
    return () => window.removeEventListener("mouseup", onMouseUp);
  }, []);

  return (
    <div style={{ "height": "100vh", "position": "relative", "overflow": "hidden" }}>
      <div style={{ transform: `translateY(${yTranslate}%)`, transition: 'transform 0.1s ease' }}>
        <div onMouseDown={onMouseDown} style={{ cursor: 'grab' }}>Тащи меня</div>
      </div>
    </div>
  );
};

export default MyComponent;
```

### Изменения и пояснения:

1. **Проверка границ:** Используйте `Math.max(0, Math.min(100, newYTranslate))`, чтобы гарантировать, что `yTranslate` не может выходить за пределы от 0 до 100.

2. **Обновление начальной позиции курсора:** После того, как вы обновили значение `yTranslate`, важно обновить `initialMousePosition`, чтобы избежать резких скачков при перетаскивании. Это делается для того, чтобы учитывать текущее положение мыши как новое начальное.

3. **Стиль и структурирование:** Вы можете добавить стили к контейнеру, если необходимо, чтобы обеспечить правильное поведение и внешний вид.

Теперь ваш элемент будет ограничен в движении по оси Y в пределах от 0% до 100%.
Для реализации ограничения движения элемента по оси Y в пределах от 0% до 100%, необходимо добавить логику, которая будет проверять текущее значение yTranslate и ограничивать его в указанных границах. 

const Draggable = () => {
  const [isDragging, setIsDragging] = useState(false);
  const [yTranslate, setYTranslate] = useState(0); // %
  const [initialMousePosition, setInitialMousePosition] = useState(null);

  const onMouseDown = ({ clientY }) => {
    setInitialMousePosition(clientY);
    setIsDragging(true);
  };

  useEffect(() => {
    const onMouseMove = (e) => {
      if (isDragging && initialMousePosition !== null) {
        const deltaY = e.clientY - initialMousePosition;
        const containerHeight = document.querySelector(".relative").offsetHeight;

        // px -> %
        const deltaYPercent = (deltaY / containerHeight) * 100;
        let newTranslate = yTranslate + deltaYPercent;

        //  [0%, 100%]
        newTranslate = Math.max(0, Math.min(100, newTranslate));

        setYTranslate(newTranslate);
        setInitialMousePosition(e.clientY);
      }
    };

    if (isDragging) {
      window.addEventListener("mousemove", onMouseMove);
    }
    return () => window.removeEventListener("mousemove", onMouseMove);
  }, [isDragging, initialMousePosition, yTranslate]);

  useEffect(() => {
    const onMouseUp = () => setIsDragging(false);
    window.addEventListener("mouseup", onMouseUp);
    return () => window.removeEventListener("mouseup", onMouseUp);
  }, []);

  return (
    <div className="text-[15px]/[22px] bg-white">
      <div style={{ '--coverY': `${yTranslate}%` }} className="relative aspect-[640_/_200] bg-[#e5e5e5] overflow-hidden">
             {/* не забудь повесить onMouseDown  на нужный элемент */}
      </div>
    </div>
  );
};
Похожие вопросы