Javascript 如何创建具有约束和过度标记的可拖动文件?
我正在尝试创建一个在定义的约束内(例如:在一个300*200px的容器内)的draggable。然而,除此之外,我还想创建一些橡皮筋效果,用于对可拖动设备进行过度包装。直到现在,我还没有找到用(纯)JavaScript实现这一点的方法 期望输出: 我当前的代码:Javascript 如何创建具有约束和过度标记的可拖动文件?,javascript,reactjs,rubber-band,Javascript,Reactjs,Rubber Band,我正在尝试创建一个在定义的约束内(例如:在一个300*200px的容器内)的draggable。然而,除此之外,我还想创建一些橡皮筋效果,用于对可拖动设备进行过度包装。直到现在,我还没有找到用(纯)JavaScript实现这一点的方法 期望输出: 我当前的代码: import React,{Component,Fragment}来自“React”; 常数外径=400; 常数outerHeight=300; 导出默认类ImagePreview扩展组件{ DragableContainerRef
import React,{Component,Fragment}来自“React”;
常数外径=400;
常数outerHeight=300;
导出默认类ImagePreview扩展组件{
DragableContainerRef=null;
状态={
拖动:false,
posX:0,
波西:0
};
组件将装入=()=>{
document.addEventListener(“mousedown”,this.onMouseDown);
document.addEventListener(“mouseup”,this.onMouseUp);
};
组件将卸载=()=>{
document.removeEventListener(“mousedown”,this.onMouseDown);
document.removeEventListener(“mouseup”,this.onMouseUp);
};
calculateCenter=r=>{
常数{clientWidth,clientHeight}=r;
log({clientHeight,clientWidth});
//const centerX=innerWidth/2-clientWidth/2;
//const centerY=内部高度/2-客户端高度/2;
const centerX=外径/2-客户端宽度/2;
常数中心=外部高度/2-客户端高度/2;
log({centerX,centerY});
这是我的国家({
posX:centerX,
波西:森蒂
});
};
lastMousePos={
x:0,,
y:0
};
/**
*查看mouseEvent中的鼠标是否位于所需目标(.draggable)上
*@返回{boolean}真/假
*@memberofimagepreview
*/
checkTarget=e=>{
如果(
e、 目标&&
(e.target.classList.contains(“可拖动”)| | e.target.tagName==“SPAN”)
)
返回true;
返回false;
};
TotalTranslationy=null;
检查边界=(位置、维度、窗口维度)=>{
const posBoundBefore=0;
const posBoundAfter=窗口维度-维度;
if(posPOSBOUNDEAFTER){
返回后返回;
}
返回pos;
};
/**
*.draggable的Mousedown事件侦听器
*如果放大,则启动拖动过程。
*@memberofimagepreview
*/
onMouseDown=e=>{
如果(本检查目标(e)){
this.lastMousePos={
x:e.clientX,
y:e.clientY
};
document.addEventListener(“mousemove”,this.onMouseMove);
}
};
/**
*.draggable的Mousemove事件侦听器
*移动
*@memberofimagepreview
*/
onMouseMove=e=>{
常数{clientX,clientY}=e;
常量{x:initialX,y:initialY}=this.lastMousePos;
const{posX:lastStateX,posY:lastStateY}=this.state;
设posX=this.checkBounds(
lastStateX+(clientX-initialX),
this.draggableContainerRef.clientWidth,
外层宽度
);
设posY=this.checkBounds(
lastStateY+(客户端-首字母缩写),
此.DragableContainerRef.clientHeight,
户外照明
);
this.lastMousePos={
x:clientX,
y:clientY
};
这是我的国家({
姿势:“Zoomedindamped”,
是的,
posX,
波西
});
};
/**
*.draggable的Mouseup事件侦听器
*检查图像是否已被拖动。否则,它将切换放大/缩小的姿势和默认位置。
*@memberofimagepreview
*/
onMouseUp=e=>{
document.removeEventListener(“mousemove”,this.onMouseMove);
this.setState({drawing:false});
};
ref=r=>{
this.draggableContainerRef=r;
如果(r!==null)此.calculateCenter(r);
};
render(){
const{posX,posY}=this.state;
返回(
拖我!
);
}
}
您有代码吗?这是一个非常广泛的问题。。有许多库可以帮助您实现这一点。与此类似,“react-dnd”react-dnd使用HTML5的拖放API,它不能提供像上面显示的GIF那样多的视觉反馈。我目前的原型太混乱了,不过如果需要的话,我会尽量简化它,并将其添加到问题中
import React, { Component, Fragment } from "react";
const outerWidth = 400;
const outerHeight = 300;
export default class ImagePreview extends Component {
draggableContainerRef = null;
state = {
dragging: false,
posX: 0,
posY: 0
};
componentWillMount = () => {
document.addEventListener("mousedown", this.onMouseDown);
document.addEventListener("mouseup", this.onMouseUp);
};
componentWillUnmount = () => {
document.removeEventListener("mousedown", this.onMouseDown);
document.removeEventListener("mouseup", this.onMouseUp);
};
calculateCenter = r => {
const { clientWidth, clientHeight } = r;
console.log({ clientHeight, clientWidth });
//const centerX = innerWidth / 2 - clientWidth / 2;
//const centerY = innerHeight / 2 - clientHeight / 2;
const centerX = outerWidth / 2 - clientWidth / 2;
const centerY = outerHeight / 2 - clientHeight / 2;
console.log({ centerX, centerY });
this.setState({
posX: centerX,
posY: centerY
});
};
lastMousePos = {
x: 0,
y: 0
};
/**
* Looks whether the mouse in a mouseEvent is on the desired target (.draggable)
* @returns {boolean} True / False
* @memberof ImagePreview
*/
checkTarget = e => {
if (
e.target &&
(e.target.classList.contains("draggable") || e.target.tagName === "SPAN")
)
return true;
return false;
};
totalTranlationY = null;
checkBounds = (pos, dimension, windowDimension) => {
const posBoundBefore = 0;
const posBoundAfter = windowDimension - dimension;
if (pos < posBoundBefore) {
return posBoundBefore;
} else if (pos > posBoundAfter) {
return posBoundAfter;
}
return pos;
};
/**
* Mousedown event listener for .draggable
* Initiates dragging process if zoomed in.
* @memberof ImagePreview
*/
onMouseDown = e => {
if (this.checkTarget(e)) {
this.lastMousePos = {
x: e.clientX,
y: e.clientY
};
document.addEventListener("mousemove", this.onMouseMove);
}
};
/**
* Mousemove event listener for .draggable
* Moves
* @memberof ImagePreview
*/
onMouseMove = e => {
const { clientX, clientY } = e;
const { x: initialX, y: initialY } = this.lastMousePos;
const { posX: lastStateX, posY: lastStateY } = this.state;
let posX = this.checkBounds(
lastStateX + (clientX - initialX),
this.draggableContainerRef.clientWidth,
outerWidth
);
let posY = this.checkBounds(
lastStateY + (clientY - initialY),
this.draggableContainerRef.clientHeight,
outerHeight
);
this.lastMousePos = {
x: clientX,
y: clientY
};
this.setState({
pose: "zoomedInDampened",
dragging: true,
posX,
posY
});
};
/**
* Mouseup event listener for .draggable
* Checks whether image has been dragged around. Otherwise it toggles the pose for zooming in/out and defaults position.
* @memberof ImagePreview
*/
onMouseUp = e => {
document.removeEventListener("mousemove", this.onMouseMove);
this.setState({ dragging: false });
};
ref = r => {
this.draggableContainerRef = r;
if (r !== null) this.calculateCenter(r);
};
render() {
const { posX, posY } = this.state;
return (
<Fragment>
<div
className="draggableContainer"
style={{
fontFamily: "sans-serif",
width: outerWidth,
height: outerHeight,
background: "#292929",
position: "absolute",
margin: "auto",
left: 0,
right: 0,
top: 0,
bottom: 0
}}
>
<div
ref={this.ref}
className="draggable"
style={{
padding: "10px 15px",
cursor: "grab",
background: "gray",
position: "absolute",
userSelect: "none",
transform: `translateX(${posX}px) translateY(${posY}px)`
}}
>
<span
draggable={false}
style={{ color: "black", fontWeight: "bold" }}
>
Drag me!
</span>
</div>
</div>
</Fragment>
);
}
}