Здравствуйте! Можете подсказать, как задать ограничения для перетаскиваемого объекта внутри элемента 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 }) => {
setInitialMousePosition({ y: clientY });
setIsDragging(true);
};
useEffect(() => {
const onMouseMove = (e) => {
setYTranslate(yTranslate + e.clientY - initialMousePosition.y);
};
if (isDragging) {
window.addEventListener("mousemove", onMouseMove);
}
return () => window.removeEventListener("mousemove", onMouseMove);
}, [isDragging, initialMousePosition]);
useEffect(() => {
const onMouseUp = () => setIsDragging(false);
window.addEventListener("mouseup", onMouseUp);
return () => window.removeEventListener("mouseup", onMouseUp);
}, []);</code></pre>
<pre><code class="javascript"><div style={{"cover": yTranslate + "%"}}>
<div onMouseDown={onMouseDown}>Тащи меня</div>
</div></code></pre>
Чтобы ограничить перемещение элемента по оси 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 и ограничивать его в указанных границах. <br/> <br/> <pre><code class="javascript">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>
);
};</code></pre>