原生js实现React拖拽效果(resize)附带完整的demo
程序员文章站
2022-07-03 14:12:23
...
想找一个可以resize块的组件,找了好几天都没找到合适的。
尝试过的开源组件:
“react-rnd”:被拖拽的块采用的布局方式是“position:absolute”,更改布局的话拖拽的事件会失效,没有仔细去研究原理。但是我是在不知道这个布局怎么去比较好的兼容页面的flex布局,所以放弃了这个组件
网上查到的大多数拖拽组件是Draggable拖拽,多用于块的拖拽排序等,而我需要的是resize块的大小,两者截然不同。
看了有人用原生js写的html文件,上面的效果还是不错的,所以读懂了代码,在此代码的结构上进行了改动,运用到了react中。
核心代码:
var theobject = null;
var dir;
//拖拽的时候初始化了一个object
resizeObject = () => {
this.el = null; //pointer to the object
this.dir = ""; //type of current resize (n, s, e, w, ne, nw, se, sw)
this.grabx = null; //Some useful values
this.graby = null;
this.width = null;
this.height = null;
this.left = null;
this.top = null;
};
//获取鼠标点击的X坐标
getPositionX = (e) => {
return e.clientX;
};
//获取鼠标点击的Y坐标
getPositionY = (e) => {
return e.clientY;
};
//获取拖拽的方向,从而确定鼠标的状态
getDirection = (el, e) => {
var xPos, yPos, offset, dir;
dir = "";
xPos = this.getPositionX(e);
yPos = this.getPositionY(e);
offset = 80; //The distance from the edge in pixels
if (yPos < offset) dir += "n";
else if (yPos > el.offsetHeight - offset) dir += "s";
if (xPos < offset) dir += "w";
else if (xPos > el.offsetWidth - offset) dir += "e";
return dir;
};
//鼠标按下触发函数
doDown = (e) => {
var el = this.leftDiv;
if (el == null) {
theobject = null;
return;
}
dir = this.getDirection(el, e);
if (dir == "") return;
theobject = new this.resizeObject();
theobject.el = el;
theobject.dir = dir;
theobject.grabx = e.clientX;
theobject.graby = e.clientY;
theobject.width = el.offsetWidth;
theobject.height = el.offsetHeight;
theobject.left = el.offsetLeft;
theobject.top = el.offsetTop;
e.returnValue = false;
e.cancelBubble = true;
};
//鼠标抬起触发函数
doUp = () => {
if (theobject != null) {
theobject = null;
}
};
//鼠标移动触发函数
doMove = (e) => {
var el, str, xMin, yMin;
xMin = 8; //The smallest width possible
yMin = 8; // height
el = this.leftDiv;
if (el.className == "resizeMe") {
str = this.getDirection(el, e);
if (str == "") str = "default";
else str += "-resize";
el.style.cursor = str;
}
if (theobject != null) {
if (dir.indexOf("e") != -1) {
theobject.el.style.width = Math.max(xMin, theobject.width + e.clientX - theobject.grabx) + "px";
}
if (dir.indexOf("s") != -1){
theobject.el.style.height = Math.max(yMin, theobject.height + e.clientY - theobject.graby) + "px";
}
if (dir.indexOf("w") != -1) {
theobject.el.style.left = Math.min(theobject.left + e.clientX - theobject.grabx, theobject.left + theobject.width - xMin) + "px";
theobject.el.style.width = Math.max(xMin, theobject.width - e.clientX + theobject.grabx) + "px";
}
if (dir.indexOf("n") != -1) {
theobject.el.style.top = Math.min(theobject.top + e.clientY - theobject.graby, theobject.top + theobject.height - yMin) + "px";
theobject.el.style.height = Math.max(yMin, theobject.height - e.clientY + theobject.graby) + "px";
}
}
e.returnValue = false;
e.cancelBubble = true;
}
效果:
完整的demo地址点击获取
上一篇: Nginx 虚拟主机