原生js實現React拖拽效果(resize)附帶完整的demo
阿新 • • 發佈:2019-01-07
想找一個可以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;
}
效果: