React Draggable Component All In One
React Draggable Component All In One
HTML5 DnD / Drag and Drop / draggable
Draggable API
document.elementFromPoint(x, y)
The elementFromPoint()
method, available on the Document object, returns the topmost
Element at the specified coordinates
(relative to the viewport
).
Document 对象上可用的 elementFromPoint() 方法返回指定坐标
(相对于视口
)处最顶层
的 Element。
function changeColor(newColor) {
// x,y
elem = document.elementFromPoint(2, 50);
elem.style.color = newColor;
}
<p id="para1">Some text here</p>
<button onclick="changeColor('blue');">Blue</button>
<button onclick="changeColor('red');">Red</button>
https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint
document.elementsFromPoint(x, y)
The elementsFromPoint()
method of the Document interface returns an array
of all elements at the specified coordinates
(relative to the viewport). The elements are ordered
from the topmost
to the bottommost
box of the viewport.
Document 接口的 elementsFromPoint() 方法返回指定坐标
(相对于视口)处的所有元素的数组
。元素从视口的最顶部
到最底部
的框排序
。
https://developer.mozilla.org/en-US/docs/Web/API/Document/elementsFromPoint
vanilla js / pure js
// dragstart
// dragover
// dragend
// drop
https://www.youtube.com/watch?v=jfYWwQrtzzY
react-draggable
https://www.npmjs.com/package/react-draggable
https://github.com/react-grid-layout/react-draggable
demos
https://react-grid-layout.github.io/react-draggable/example/
https://github.com/react-grid-layout/react-draggable/blob/master/example/example.js
import React from 'react';
import ReactDOM from 'react-dom';
import Draggable from 'react-draggable';
class App extends React.Component {
eventLogger = (e: MouseEvent, data: Object) => {
console.log('Event: ', e);
console.log('Data: ', data);
};
render() {
return (
<Draggable
axis="x"
handle=".handle"
defaultPosition={{x: 0, y: 0}}
position={null}
grid={[25, 25]}
scale={1}
onStart={this.handleStart}
onDrag={this.handleDrag}
onStop={this.handleStop}>
<div>
<div className="handle">Drag from here</div>
<div>This readme is really dragging on...</div>
</div>
</Draggable>
);
}
}
ReactDOM.render(<App/>, document.body);
const {ReactDraggable: Draggable, React, ReactDOM} = window;
class App extends React.Component {
state = {
activeDrags: 0,
deltaPosition: {
x: 0, y: 0
},
controlledPosition: {
x: -400, y: 200
}
};
handleDrag = (e, ui) => {
const {x, y} = this.state.deltaPosition;
this.setState({
deltaPosition: {
x: x + ui.deltaX,
y: y + ui.deltaY,
}
});
};
onStart = () => {
this.setState({activeDrags: ++this.state.activeDrags});
};
onStop = () => {
this.setState({activeDrags: --this.state.activeDrags});
};
onDrop = (e) => {
this.setState({activeDrags: --this.state.activeDrags});
if (e.target.classList.contains("drop-target")) {
alert("Dropped!");
e.target.classList.remove('hovered');
}
};
onDropAreaMouseEnter = (e) => {
if (this.state.activeDrags) {
e.target.classList.add('hovered');
}
}
onDropAreaMouseLeave = (e) => {
e.target.classList.remove('hovered');
}
// For controlled component
adjustXPos = (e) => {
e.preventDefault();
e.stopPropagation();
const {x, y} = this.state.controlledPosition;
this.setState({controlledPosition: {x: x - 10, y}});
};
adjustYPos = (e) => {
e.preventDefault();
e.stopPropagation();
const {controlledPosition} = this.state;
const {x, y} = controlledPosition;
this.setState({controlledPosition: {x, y: y - 10}});
};
onControlledDrag = (e, position) => {
const {x, y} = position;
this.setState({controlledPosition: {x, y}});
};
onControlledDragStop = (e, position) => {
this.onControlledDrag(e, position);
this.onStop();
};
render() {
const dragHandlers = {onStart: this.onStart, onStop: this.onStop};
const {deltaPosition, controlledPosition} = this.state;
return (
<div>
<h1>React Draggable</h1>
<p>Active DragHandlers: {this.state.activeDrags}</p>
<p>
<a href="https://github.com/STRML/react-draggable/blob/master/example/example.js">Demo Source</a>
</p>
<Draggable {...dragHandlers}>
<div className="box">I can be dragged anywhere</div>
</Draggable>
<Draggable axis="x" {...dragHandlers}>
<div className="box cursor-x">I can only be dragged horizonally (x axis)</div>
</Draggable>
<Draggable axis="y" {...dragHandlers}>
<div className="box cursor-y">I can only be dragged vertically (y axis)</div>
</Draggable>
<Draggable onStart={() => false}>
<div className="box">I don't want to be dragged</div>
</Draggable>
<Draggable onDrag={this.handleDrag} {...dragHandlers}>
<div className="box">
<div>I track my deltas</div>
<div>x: {deltaPosition.x.toFixed(0)}, y: {deltaPosition.y.toFixed(0)}</div>
</div>
</Draggable>
<Draggable handle="strong" {...dragHandlers}>
<div className="box no-cursor">
<strong className="cursor"><div>Drag here</div></strong>
<div>You must click my handle to drag me</div>
</div>
</Draggable>
<Draggable handle="strong">
<div className="box no-cursor" style={{display: 'flex', flexDirection: 'column'}}>
<strong className="cursor"><div>Drag here</div></strong>
<div style={{overflow: 'scroll'}}>
<div style={{background: 'yellow', whiteSpace: 'pre-wrap'}}>
I have long scrollable content with a handle
{'\n' + Array(40).fill('x').join('\n')}
</div>
</div>
</div>
</Draggable>
<Draggable cancel="strong" {...dragHandlers}>
<div className="box">
<strong className="no-cursor">Can't drag here</strong>
<div>Dragging here works</div>
</div>
</Draggable>
<Draggable grid={[25, 25]} {...dragHandlers}>
<div className="box">I snap to a 25 x 25 grid</div>
</Draggable>
<Draggable grid={[50, 50]} {...dragHandlers}>
<div className="box">I snap to a 50 x 50 grid</div>
</Draggable>
<Draggable bounds={{top: -100, left: -100, right: 100, bottom: 100}} {...dragHandlers}>
<div className="box">I can only be moved 100px in any direction.</div>
</Draggable>
<Draggable {...dragHandlers}>
<div className="box drop-target" onMouseEnter={this.onDropAreaMouseEnter} onMouseLeave={this.onDropAreaMouseLeave}>I can detect drops from the next box.</div>
</Draggable>
<Draggable {...dragHandlers} onStop={this.onDrop}>
<div className={`box ${this.state.activeDrags ? "no-pointer-events" : ""}`}>I can be dropped onto another box.</div>
</Draggable>
<div className="box" style={{height: '500px', width: '500px', position: 'relative', overflow: 'auto', padding: '0'}}>
<div style={{height: '1000px', width: '1000px', padding: '10px'}}>
<Draggable bounds="parent" {...dragHandlers}>
<div className="box">
I can only be moved within my offsetParent.<br /><br />
Both parent padding and child margin work properly.
</div>
</Draggable>
<Draggable bounds="parent" {...dragHandlers}>
<div className="box">
I also can only be moved within my offsetParent.<br /><br />
Both parent padding and child margin work properly.
</div>
</Draggable>
</div>
</div>
<Draggable bounds="body" {...dragHandlers}>
<div className="box">
I can only be moved within the confines of the body element.
</div>
</Draggable>
<Draggable {...dragHandlers}>
<div className="box" style={{position: 'absolute', bottom: '100px', right: '100px'}}>
I already have an absolute position.
</div>
</Draggable>
<Draggable {...dragHandlers}>
<RemWrapper>
<div className="box rem-position-fix" style={{position: 'absolute', bottom: '6.25rem', right: '18rem'}}>
I use <span style={{ fontWeight: 700 }}>rem</span> instead of <span style={{ fontWeight: 700 }}>px</span> for my transforms. I also have absolute positioning.
<br /><br />
I depend on a CSS hack to avoid double absolute positioning.
</div>
</RemWrapper>
</Draggable>
<Draggable defaultPosition={{x: 25, y: 25}} {...dragHandlers}>
<div className="box">
{"I have a default position of {x: 25, y: 25}, so I'm slightly offset."}
</div>
</Draggable>
<Draggable positionOffset={{x: '-10%', y: '-10%'}} {...dragHandlers}>
<div className="box">
{'I have a default position based on percents {x: \'-10%\', y: \'-10%\'}, so I\'m slightly offset.'}
</div>
</Draggable>
<Draggable position={controlledPosition} {...dragHandlers} onDrag={this.onControlledDrag}>
<div className="box">
My position can be changed programmatically. <br />
I have a drag handler to sync state.
<div>
<a href="#" onClick={this.adjustXPos}>Adjust x ({controlledPosition.x})</a>
</div>
<div>
<a href="#" onClick={this.adjustYPos}>Adjust y ({controlledPosition.y})</a>
</div>
</div>
</Draggable>
<Draggable position={controlledPosition} {...dragHandlers} onStop={this.onControlledDragStop}>
<div className="box">
My position can be changed programmatically. <br />
I have a dragStop handler to sync state.
<div>
<a href="#" onClick={this.adjustXPos}>Adjust x ({controlledPosition.x})</a>
</div>
<div>
<a href="#" onClick={this.adjustYPos}>Adjust y ({controlledPosition.y})</a>
</div>
</div>
</Draggable>
</div>
);
}
}
class RemWrapper extends React.Component {
// PropTypes is not available in this environment, but here they are.
// static propTypes = {
// style: PropTypes.shape({
// transform: PropTypes.string.isRequired
// }),
// children: PropTypes.node.isRequired,
// remBaseline: PropTypes.number,
// }
translateTransformToRem(transform, remBaseline = 16) {
const convertedValues = transform.replace('translate(', '').replace(')', '')
.split(',')
.map(px => px.replace('px', ''))
.map(px => parseInt(px, 10) / remBaseline)
.map(x => `${x}rem`)
const [x, y] = convertedValues
return `translate(${x}, ${y})`
}
render() {
const { children, remBaseline = 16, style } = this.props
const child = React.Children.only(children)
const editedStyle = {
...child.props.style,
...style,
transform: this.translateTransformToRem(style.transform, remBaseline),
}
return React.cloneElement(child, {
...child.props,
...this.props,
style: editedStyle
})
}
}
ReactDOM.render(<App/>, document.getElementById('container'));
refs
©xgqfrms 2012-2025
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/17947257
未经授权禁止转载,违者必究!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
2023-01-05 中国国内航班燃油附加费是如何按照航段计算的 All In One
2023-01-05 LeetCode Badge 2022 All In One
2023-01-05 Docker Desktop bugs All In One
2022-01-05 WebGL & CG All In One
2022-01-05 TestFlight All In One
2021-01-05 Zero Width Space bug All In One
2021-01-05 zsh & for loop bug