圖片裁剪程序效果以下,可鼠標操做。 javascript
拖動左邊小方框時在右側實時顯示對應的裁剪圖片,同時左側的拖動框裏圖片徹底顯示,拖動框外部圖片模糊顯示。8個控制點能夠對顯示區域大小進行控制。css
左側的裁剪操做區域能夠分爲三層。 最底層的圖片半透明效果;中間層的圖片只顯示制定區域,其餘部分隱藏;最上層爲拖拽控制層。最低層和中間層使用同一張圖片,利用CSS屬性clip
控制中間層只顯示一部分。 三個層都使用 absolute 絕對定位。下面是 HTML 和 CSS 代碼。html
1 <div id="cArea"> 2 <img src="./storm.jpg" alt="storm.jpg" class="baseImg"> <!-- 最底層半透明圖片 --> 3 <img src="./storm.jpg" alt="storm.jpg" id="clipImg" class="clipImg"> <!--中間層圖片--> 4 <div id="drag"> <!--拖拽控制層--> 5 <div id="cRightDown" class="dragDot"></div> 6 <div id="cLeftDown" class="dragDot"></div> 7 <div id="cRightUp" class="dragDot"></div> 8 <div id="cLeftUp" class="dragDot"></div> 9 <div id="cRight" class="dragDot"></div> 10 <div id="cDown" class="dragDot"></div> 11 <div id="cLeft" class="dragDot"></div> 12 <div id="cUp" class="dragDot"></div> 13 </div> 14 </div>
涉及到技巧有:元素居中顯示,clip裁剪,除此外都是很簡單的東西。java
1 #cArea{position: relative;overflow: hidden;width: 600px;height: 390px;} 2 .baseImg{position: absolute;top: 0;left: 0;opacity: .3;} 3 .clipImg{position: absolute;top: 0;left: 0;clip: rect(0 200px 200px 0);} 4 #drag{width: 200px;height: 200px;position: absolute;border: 1px dashed #eee;cursor: move;box-sizing: border-box;z-index: 999;} 5 .dragDot{width: 6px;height: 6px;background: #fff;border: 1px solid #888;position: absolute;opacity: 0.8;} 6 #cLeftUp{top: -4px;left: -4px;cursor: nw-resize;} 7 #cUp{top: -4px;left: 50%;margin-left: -4px;cursor: n-resize;} 8 #cRightUp{top: -4px;right: -4px;cursor: ne-resize;} 9 #cRight{right: -4px;top: 50%;margin-top: -4px;cursor: e-resize;} 10 #cRightDown{bottom: -4px;right: -4px;cursor: nw-resize;} 11 #cDown{bottom: -4px;left: 50%;margin-left: -4px;cursor: n-resize;} 12 #cLeftDown{bottom: -4px;left: -4px;cursor: ne-resize;} 13 #cLeft{left: -4px;top: 50%;margin-top: -4px;cursor: e-resize;}
首先完成鼠標拖拽控制區時對應的區域圖片徹底顯示,其餘部分隱藏。
計算鼠標從一個地方拖動到另外一個地方時拖拽區的移動數據,要使用到一些 html 元素屬性和鼠標事件。瀏覽器
屬性 | 說明 |
---|---|
MouseEvent.clientX | 鼠標相對瀏覽器窗口的水平座標 |
MouseEvent.clientY | 鼠標相對瀏覽器窗口的垂直座標 |
HTMLElement.offsetHeight | 元素的像素高度 |
HTMLElement.offsetWidth | 元素的像素寬度 |
HTMLElement.offsetLeft | 元素左邊界相對於父元素的左邊界偏移的像素值 |
HTMLElement.offsetHeight | 元素上邊界相對於父元素的上邊界偏移的像素值 |
在鼠標按下拖拽區域後(mousedown事件),當即記錄此時鼠標的 X1 Y1 座標位置,以及此時拖拽區域相對圖片層的左邊界距離L,上邊界距離T。在鼠標進行移動時記錄移動過程當中的 X2 Y2 座標位置。拖拽區域的left和top屬性值分別爲:X2-X1+L
和 Y2-Y1+T
。 原理如圖spa
代碼以下code
1 function $(id){ 2 return document.getElementById(id) 3 }; 4 var cArea = $('cArea'); // 圖片容器 5 var clipImg = $('clipImg'); // 裁剪層 6 var drag = $('drag'); // 拖拽區域 7 var previewImg = $('previewImg'); //預覽圖 8 var cAreaH = cArea.offsetHeight; // 圖片顯示區的高度 9 var cAreaW = cArea.offsetWidth; // 圖片顯示區的寬度 10 var cAreaTop = getPosition(cArea).Y; //圖片容器距離瀏覽器上邊界距離 11 var cAreaLeft = getPosition(cArea).X; //圖片容器距離瀏覽器左邊界距離 12 var mousePosition,mouseStartX,mouseStartY,dragLeft,dragTop,dragMaxH,dragMaxW // 定義按下鼠標時產生的變量 13 14 drag.addEventListener('mousedown', startDrag, false); // 給拖拽區添加鼠標按下事件 15 16 function startDrag(e) { 17 e.preventDefault(); 18 mouseStartX = e.clientX; // 剛按下鼠標時 鼠標相對瀏覽器邊界的 X 座標 19 mouseStartY = e.clientY; // 剛按下鼠標時 鼠標相對瀏覽器邊界的 Y 座標 20 dragLeft = drag.offsetLeft; // 剛按下鼠標時 裁剪區的距離圖片顯示區 左 邊界距離 21 dragTop = drag.offsetTop; // 剛按下鼠標時 裁剪區的距離圖片顯示區 上 邊界距離 22 dragMaxH = cAreaH - drag.offsetHeight; // 垂直最大範圍 23 dragMaxW = cAreaW - drag.offsetWidth; // 水平最大範圍 24 mousePosition = e.target.id; // 判斷按下位置 25 document.addEventListener('mousemove', dragging, false); 26 document.addEventListener('mouseup', clearDragEvent, false); 27 }; 28 29 // 鼠標鬆開時釋放事件 30 function clearDragEvent(e) { 31 document.removeEventListener('mousemove', dragging, false); 32 document.removeEventListener('mouseup', clearDragEvent, false) 33 }; 34 35 // 總體拖拽 36 function dragMove(e) { 37 var moveX = e.clientX - mouseStartX; // 拖拽中 鼠標座標變化值 38 var moveY = e.clientY - mouseStartY; // 拖拽中 鼠標座標變化值 39 var destinationX = Math.min((moveX + dragLeft), dragMaxW); // 限制拖動的最大範圍,避免超出右和下邊界 40 var destinationY = Math.min((moveY + dragTop), dragMaxH); // 限制拖動的最大範圍,避免超出右和下邊界 41 drag.style.left = destinationX < 0 ? 0 : destinationX + 'px'; // 限制最小範圍,避免超出上和左邊界 42 drag.style.top = destinationY < 0 ? 0 : destinationY + 'px'; // 限制最小範圍,避免超出上和左邊界 43 setClip(); 44 };
拖拽有八個點控制點,實際只須要寫上下左右四個方法就可實現,四個角落的拖拽分別同時對應左上,右上,左下,右下。以上方中間控制點爲例,當拖拽此點時,拖拽顯示區水平位置並無變化,只是自己的高度和距離父元素頂部距離發生改變。獲取到拖拽區距離瀏覽器上邊界距離 dragY,再獲取到鼠標上下拖拽時鼠標的垂直座標 mouseY。拖拽區的高度變化就等於dragY-mouseY
。也很容易看出拖拽區top屬性值變化就等於他原來距離父元素的距離減去自身高度變化。效果以下圖:orm
代碼以下:htm
1 // 上方邊框拖動 2 function upMove(e) { 3 var draggingY = e.clientY; // 鼠標Y座標 4 if(draggingY < cAreaTop) draggingY = cAreaTop; //防止跑出圖片上邊界 5 var dragY = getPosition(drag).Y; // 拖拽區距離父元素邊界 6 var changeHeight = dragY - draggingY; //改變高度 7 drag.style.top = drag.offsetTop - dragY + draggingY + 'px'; 8 drag.style.height = drag.offsetHeight + changeHeight + 'px'; 9 };
下面中間點與此相似,左右也是一樣計算到方法。固然還能夠將上下何在一塊兒,左右合在一塊兒。blog
1 // 上下方向的邊框拖動 2 function upDownMove(e, str) { 3 var draggingY = e.clientY; 4 if(draggingY < cAreaTop) draggingY = cAreaTop; 5 if(draggingY > cAreaTop + cAreaH) draggingY = cAreaTop + cAreaH; 6 var dragY = getPosition(drag).Y; 7 if(str === 'up'){ 8 var changeHeight = dragY - draggingY; 9 drag.style.top = drag.offsetTop - dragY + draggingY + 'px'; 10 } else if(str === 'down') { 11 var changeHeight = draggingY - drag.offsetHeight - dragY; 12 } 13 drag.style.height = drag.offsetHeight + changeHeight + 'px'; 14 setClip(); 15 }; 16 17 // 水平方向的邊框拖動 18 function leftRightMove(e, str) { 19 var draggingX = e.clientX; 20 if(draggingX < cAreaLeft) draggingX = cAreaLeft; 21 if(draggingX > cAreaLeft + cAreaW) draggingX = cAreaLeft + cAreaW; 22 var dragX = getPosition(drag).X; 23 if(str === 'left') { 24 var changeWidth = dragX - draggingX; 25 drag.style.left = drag.offsetLeft - changeWidth + 'px'; 26 } else if(str === 'right') { 27 var changeWidth = draggingX - drag.offsetWidth - dragX; 28 } 29 drag.style.width = drag.offsetWidth + changeWidth + 'px'; 30 setClip(); 31 };
這個很是簡單,知道了拖拽區的座標和尺寸,就很容易計算出中間層clip屬性值。
1 function setClip() { // 顯示層 2 var clipTop = drag.offsetTop; 3 var clipLeft = drag.offsetLeft; 4 var clipRight = drag.offsetWidth + drag.offsetLeft; 5 var clipBottom = drag.offsetHeight + drag.offsetTop; 6 clipImg.style.clip = 'rect(' + clipTop + 'px ' + clipRight + 'px ' + clipBottom + 'px ' + clipLeft + 'px)'; 7 setPreview({top: clipTop, right: clipRight, bottom: clipBottom, left: clipLeft}) 8 }; 9 function setPreview(clip){ // 預覽圖 10 previewImg.style.top = -clip.top + 'px'; 11 previewImg.style.left = -clip.left + 'px'; 12 previewImg.style.clip = 'rect(' + clip.top + 'px ' + clip.right + 'px ' + clip.bottom + 'px '+ clip.left + 'px)'; 13 };