使用JS制作一个鼠标可拖的DIV(四)——缩放
原理与鼠标拖动 DIV 相同。
下面就先实现一个在DIV的右上角显示一个小正方形(类似)。
当鼠标按下并拖动时,DIV会以要拖动的元素的左下角的坐标点定位,根据鼠标的拖动,按比例的扩大或缩小。
一、思路
1、鼠标按时事件。
这里要初始化数据。
同移动一样,给小正方形绑定鼠标按时事件。
(1)获得并保存要移动的元素(parent)的宽(parentWidth)与高(parentHeight)。
即:元素缩放前的宽与高。
(2)由于是要按比例缩放,所以,要在这时计算出宽与高的比例(scale),得到的结果保留一位小数。
(3)获得鼠标的 X 坐标(mouseX),用于计算鼠标移动前与移动后的位置。
2、鼠标拖动事件。
同移动一样,给 document 帮绑定移动事件。
由于小正方形是放在元素(parent)中的,为了避免绑定的鼠标按下事件与元素(parent)中相同的事件有冲突。
所以,在绑定document.onmousemove前,要先清空元素(parent)的onmousedown事件。
parent.onmousedown = function () { } document.onmousemove = function (doc) {
}
(1)计算出:鼠标移动的差值(moveWidth) = 移动后的鼠标坐标(currentMouseX) - 移动前的鼠标坐标(mouseX)。
(2)元素(parent)缩放后的宽度(width) = 元素(parent)当前的宽度 + 鼠标移动的差值(moveWidth)
(3)元素(parent)缩放后的高度(height) = 元素(parent)缩放的后的宽度(width)X (1 / 宽与高的比例(scale))
即:height = width X (1 / scale)
注意,这里要使用四舍五入来取整。
(4)由于是要以元素(parent)左下角的坐标为定点,所以需要计算出元素(parent)左上角的 Y 坐标(top)的偏移量。
元素(parent)左上角的 Y 坐标(top) = 元素(parent)当前左上角的 Y 坐标 - (元素(parent)缩放后的高度(height) - 元素(parent)缩放前的高度(parentHeight))
即:
top = parent.offsetTop - (height - parentHeight);
设置元素(parent)左上角的 Y 坐标。
设置元素(parent)缩放后的宽度。
设置元素(parent)缩放后的高度。
parent.style.top = top + "px"; parent.style.width = width + "px"; parent.style.height = height + "px";
更新当前鼠标的 X 坐标(mouseX)。
更新当前元素的宽度(parentWidth)。
更新当前元素的高度(parentHeight)。
mouseX = currentMouseX; parentWidth = parent.offsetWidth; parentHeight = parent.offsetHeight;
3.鼠标放开事件
当鼠标放开时:
清除 document.onmousemove 事件。
重新绑定(parent)的 onmousedown 事件到 moveBind 函数。
二、实现
续上篇
首先,在元素(parent)里增加一个子DIV并绑定onmousedown事件到zoomBind函数,做为右上角的小正方形。
在 addElement 函数里增加:
var rightSize = "<div class='resize' onmousedown='zoomBind(this, event)'></div>";
CSS样式是:
.resize { width: 7px; height: 7px; background-color: #ddd; border: 1px solid #000; top: -5px; right: -5px; position: absolute; cursor: ne-resize; }
为了避免事件冲突,在 moveBind 函数的最开始增加一个 bool 类型的变量,当鼠标按下时,设置为 true, 放开时,设置为 false。
function moveBind(obj, evnt) { isMouseMove = true; /*...*/ }
moveBind 函数里绑定的onmouseup 事件:
document.onmouseup = function () { isMouseMove = false; document.onmousemove = function () { } };
现在创建zoomBind函数:
//是否元素缩放。 var isMouseZoom = false; function zoomBind(obj, evnt) { isMouseZoom = true; //设置最小宽度。 var minWidth = 50; //获得元素对象。 var parent = obj.parentNode; //获得当前鼠标位置。 var mouseX = evnt.clientX; //获得元素的宽与高。 var parentSize = findPosition(parent); var parentWidth = parentSize[4]; var parentHeight = parentSize[5]; //计算出宽与高的比例。 var scale = (parentWidth / parentHeight).toFixed(1); parent.onmousedown = function () { } document.onmousemove = function (doc) { if (isMouseZoom) { //设置成绝对定位,让元素可以移动。 parent.style.position = "absolute"; //获得鼠标移动后的坐标。 var currentMouseX = doc.clientX; //计算出移动后的坐标。 var moveWidth = currentMouseX - mouseX; //计算宽度增加或减少的值,增加的量等于鼠标移位的量。 var width = parent.offsetWidth + moveWidth; if (width > minWidth) { //高度参数是:当前宽度的值 * (1 / 宽与高的比例) var height = Math.round(width * (1 / scale)); //以元素左下角为定点,则左下角的 Y 坐标 = 当前元素的左上角的 Y 坐标 - (改变后的高度 - 改变前的高度) var top = parent.offsetTop - (height - parentHeight); parent.style.top = top + "px"; parent.style.width = width + "px"; parent.style.height = height + "px"; mouseX = currentMouseX; parentWidth = parent.offsetWidth; parentHeight = parent.offsetHeight; } } } document.onmouseup = function () { isMouseZoom = false; document.onmousemove = function () { } parent.onmousedown = function (e) { moveBind(parent, e); } }; }
以下是完整源码:
这里使用的是 jquery-1.10.2.min.js
/*要引入 jquery */ //禁止鼠标选中。 document.onselectstart = new Function("event.returnValue=false;"); var containerId = "innerContainer"; var showId = "idShow"; var moveElement = "div"; //是否元素移动。 var isMouseMove = false; //是否元素缩放。 var isMouseZoom = false; var productLists = $("#products"); //获得容器坐标。 var setContainer = findPosition(document.getElementById(containerId)); $("#ContainerWidth").attr("value", setContainer[4]); $("#ContainerHeight").attr("value", setContainer[5]); function addElement(obj) { var container = findPosition(document.getElementById(containerId)); var containerLeft = container[0]; var containerTop = container[1]; var containerWidth = container[4]; var containerHeight = container[5]; //设置默认宽度与高度。 var width = 50; var height = width * (1 / (obj.offsetWidth / obj.offsetHeight)); var left = containerLeft + containerWidth / 2 - width / 2; var top = containerTop + containerHeight / 2 - height / 2; var style = "width:" + width + "px;height:" + height + "px; left:" + left + "px;top:" + top + "px; position:absolute;background: #ff0000;"; var rightSize = "<div class='resize' onmousedown='zoomBind(this, event)'></div>"; $("#" + containerId).append("<div onmousedown='moveBind(this, event)' onmousemove=\"this.style.cursor='move'\" style='" + style + "'>" + rightSize + "</div>"); } /****************************以下是元素缩放*******************************/ function zoomBind(obj, evnt) { isMouseZoom = true; //设置最小宽度。 var minWidth = 50; //获得元素对象。 var parent = obj.parentNode; //获得当前鼠标位置。 var mouseX = evnt.clientX; //获得元素的宽与高。 var parentSize = findPosition(parent); var parentWidth = parentSize[4]; var parentHeight = parentSize[5]; //计算出宽与高的比例。 var scale = (parentWidth / parentHeight).toFixed(1); parent.onmousedown = function () { } document.onmousemove = function (doc) { if (isMouseZoom) { //设置成绝对定位,让元素可以移动。 parent.style.position = "absolute"; //获得鼠标移动后的坐标。 var currentMouseX = doc.clientX; //计算出移动后的坐标。 var moveWidth = currentMouseX - mouseX; //计算宽度增加或减少的值,增加的量等于鼠标移位的量。 var width = parent.offsetWidth + moveWidth; if (width > minWidth) { //高度参数是:当前宽度的值 * (1 / 宽与高的比例) var height = Math.round(width * (1 / scale)); //以元素左下角为定点,则左下角的 Y 坐标 = 当前元素的左上角的 Y 坐标 - (改变后的高度 - 改变前的高度) var top = parent.offsetTop - (height - parentHeight); parent.style.top = top + "px"; parent.style.width = width + "px"; parent.style.height = height + "px"; mouseX = currentMouseX; parentWidth = parent.offsetWidth; parentHeight = parent.offsetHeight; } } } document.onmouseup = function () { isMouseZoom = false; document.onmousemove = function () { } parent.onmousedown = function (e) { moveBind(parent, e); } }; } /****************************以上是元素缩放*******************************/ /****************************以下是元素拖动*******************************/ //绑定移动事件。 function moveBind(obj, evnt) { isMouseMove = true; //获得元素坐标。 var left = obj.offsetLeft; var top = obj.offsetTop; var width = obj.offsetWidth; var height = obj.offsetHeight; //计算出鼠标的位置与元素位置的差值。 var cleft = evnt.clientX - left; var ctop = evnt.clientY - top; //获得容器坐标。 var container = findPosition(document.getElementById(containerId)); var containerLeft = container[0]; var containerTop = container[1]; var containerWidth = container[4]; var containerHeight = container[5]; /*计算出容器的范围坐标。*/ //开始 X 坐标。 var startX = containerLeft; //开始 Y 坐标。 var startY = containerTop; //结束 X 坐标。 var maxX = startX + containerWidth - width; //结束 Y 坐标。 var maxY = startY + containerHeight - height; //鼠标选中的元素设置成顶层。 obj.style.zIndex = getMaxIndex() + 1; //输出显示。 //show("idShow", startX, startY); document.onmousemove = function () { } document.onmousemove = function (doc) { if (isMouseMove) { //计算出移动后的坐标。 var moveLeft = doc.clientX - cleft; var moveTop = doc.clientY - ctop; //设置成绝对定位,让元素可以移动。 obj.style.position = "absolute"; //不可以超出指定的范围。 if (moveLeft >= startX && moveTop >= startY && moveLeft <= maxX && moveTop <= maxY) { //当移动位置在范围内时,元素跟随鼠标移动。 obj.style.left = moveLeft + "px"; obj.style.top = moveTop + "px"; } else { /****************以下为处理当鼠标的位置不在范围内里,鼠标的移动,里面的元素也要跟着移动*****************/ //向右移动时,如果移动坐标没有大于最大 X 坐标,则移动,否则设置成最大 X 坐标的值。 if (moveLeft >= startX && moveLeft <= maxX) { obj.style.left = moveLeft + "px"; } else if (moveLeft > maxX) { obj.style.left = maxX + "px"; } else if (moveLeft < startX) { obj.style.left = startX + "px"; } //向下移动时,如果移动坐标没有大于最大 Y 坐标,则移动,否则设置成最大 Y 坐标的值。 if (moveTop >= startY && moveTop <= maxY) { obj.style.top = moveTop + "px"; } else if (moveTop > maxY) { obj.style.top = maxY + "px"; } else if (moveTop < startY) { obj.style.top = startY + "px"; } } var objX = obj.offsetLeft - startX; var objY = obj.offsetTop - startY; var inputValue = obj.getElementsByTagName("input")[0]; inputValue.value = objX + "," + objY + "," + width + "," + height; show(showId, moveLeft, moveTop); } } document.onmouseup = function () { isMouseMove = false; document.onmousemove = function () { } }; } //获得元素的坐标与大小。 function findPosition(oElement) { var x2 = 0; var y2 = 0; var width = oElement.clientWidth; var height = oElement.clientHeight; //alert(width + "=" + height); if (typeof (oElement.offsetParent) != 'undefined') { for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) { posX += oElement.offsetLeft; posY += oElement.offsetTop; } x2 = posX + width; y2 = posY + height; return [posX, posY, x2, y2, width, height]; } else { x2 = oElement.x + width; y2 = oElement.y + height; return [oElement.x, oElement.y, x2, y2, width, height]; } } //获得最大 Z 坐标。 function getMaxIndex() { var index = 0; var ds = document.getElementById(containerId).getElementsByTagName(moveElement); var length = document.getElementById(containerId).getElementsByTagName(moveElement).length; for (var loop = 0; loop < length; loop++) { if (ds[loop].style.zIndex > index) index = ds[loop].style.zIndex; } return parseInt(index); } //显示坐标信息。 function show(id, x, y) { document.getElementById(id).innerHTML = "left:" + x + ";top:" + y; } /*****************************以上是元素拖动*******************************/
完整CSS:
.resize { width: 7px; height: 7px; background-color: #ddd; border: 1px solid #000; top: -5px; right: -5px; position: absolute; cursor: ne-resize; } #mainContainer { border: 10px solid #990000; width: 600px; height: 300px; } #innerContainer { width: 100%; height: 100%; } #Drag { /*border: 5px solid #C4E3FD;*/ background: #C4E3FD; width: 50px; height: 50px; top: 50px; left: 50px; z-index: 2; } #Drag2 { /*border: 5px solid #C4E3FD;*/ background: #ff0000; width: 80px; height: 80px; top: 50px; left: 50px; z-index: 3; /*background: url(http://pic.cnitblog.com/face/614265/20140725231849.png) no-repeat;*/ }
完整 HTML:
<div id="mainContainer"> <div id="innerContainer"> </div> </div> <br />拖放状态:<span id="idShow">未开始</span> <br /><span id="testShow"></span> <div> <img src="http://pic.cnitblog.com/face/614265/20140725231849.png" onclick="addElement(this)" /> </div>