原生 JavaScript 圖片裁剪效果

圖片裁剪程序效果以下,可鼠標操做。 javascript

 

storm.jpg
 

拖動左邊小方框時在右側實時顯示對應的裁剪圖片,同時左側的拖動框裏圖片徹底顯示,拖動框外部圖片模糊顯示。8個控制點能夠對顯示區域大小進行控制。css

HTML 和 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;}   

JS控制總體拖拽

首先完成鼠標拖拽控制區時對應的區域圖片徹底顯示,其餘部分隱藏。 
計算鼠標從一個地方拖動到另外一個地方時拖拽區的移動數據,要使用到一些 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 };           

 

JS 控制八個點的拖動

拖拽有八個點控制點,實際只須要寫上下左右四個方法就可實現,四個角落的拖拽分別同時對應左上,右上,左下,右下。以上方中間控制點爲例,當拖拽此點時,拖拽顯示區水平位置並無變化,只是自己的高度和距離父元素頂部距離發生改變。獲取到拖拽區距離瀏覽器上邊界距離 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 };
相關文章
相關標籤/搜索