原生 JavaScript 图片裁剪效果
2016-05-26 20:49
579 查看
图片裁剪程序效果如下,可鼠标操作。
![](https://www.denpe.com/example/storm.jpg)
拖动左边小方框时在右侧实时显示对应的裁剪图片,同时左侧的拖动框里图片完全显示,拖动框外部图片模糊显示。8个控制点可以对显示区域大小进行控制。
涉及到技巧有:元素居中显示,clip裁剪,除此外都是很简单的东西。
计算鼠标从一个地方拖动到另一个地方时拖拽区的移动数据,要使用到一些 html 元素属性和鼠标事件。
在鼠标按下拖拽区域后(mousedown事件),立即记录此时鼠标的 X1 Y1 坐标位置,以及此时拖拽区域相对图片层的左边界距离L,上边界距离T。在鼠标进行移动时记录移动过程中的 X2 Y2 坐标位置。拖拽区域的left和top属性值分别为:
![](https://www.denpe.com/content/images/2016/04/clip-x.jpg)
代码如下
![](https://www.denpe.com/content/images/2016/04/mousey.JPG)
代码如下:
下面中间点与此类似,左右也是同样计算到方法。当然还可以将上下何在一起,左右合在一起。
![](https://www.denpe.com/example/storm.jpg)
拖动左边小方框时在右侧实时显示对应的裁剪图片,同时左侧的拖动框里图片完全显示,拖动框外部图片模糊显示。8个控制点可以对显示区域大小进行控制。
HTML 和 CSS 部分
左侧的裁剪操作区域可以分为三层。 最底层的图片半透明效果;中间层的图片只显示制定区域,其他部分隐藏;最上层为拖拽控制层。最低层和中间层使用同一张图片,利用CSS属性clip控制中间层只显示一部分。 三个层都使用 absolute 绝对定位。下面是 HTML 和 CSS 代码。
<div id="cArea"> <img src="./storm.jpg" alt="storm.jpg" class="baseImg"> <!-- 最底层半透明图片 --> <img src="./storm.jpg" alt="storm.jpg" id="clipImg" class="clipImg"> <!--中间层图片--> <div id="drag"> <!--拖拽控制层--> <div id="cRightDown" class="dragDot"></div> <div id="cLeftDown" class="dragDot"></div> <div id="cRightUp" class="dragDot"></div> <div id="cLeftUp" class="dragDot"></div> <div id="cRight" class="dragDot"></div> <div id="cDown" class="dragDot"></div> <div id="cLeft" class="dragDot"></div> <div id="cUp" class="dragDot"></div> </div> </div>
涉及到技巧有:元素居中显示,clip裁剪,除此外都是很简单的东西。
#cArea{position: relative;overflow: hidden;width: 600px;height: 390px;} .baseImg{position: absolute;top: 0;left: 0;opacity: .3;} .clipImg{position: absolute;top: 0;left: 0;clip: rect(0 200px 200px 0);} #drag{width: 200px;height: 200px;position: absolute;border: 1px dashed #eee;cursor: move;box-sizing: border-box;z-index: 999;} .dragDot{width: 6px;height: 6px;background: #fff;border: 1px solid #888;position: absolute;opacity: 0.8;} #cLeftUp{top: -4px;left: -4px;cursor: nw-resize;} #cUp{top: -4px;left: 50%;margin-left: -4px;cursor: n-resize;} #cRightUp{top: -4px;right: -4px;cursor: ne-resize;} #cRight{right: -4px;top: 50%;margin-top: -4px;cursor: e-resize;} #cRightDown{bottom: -4px;right: -4px;cursor: nw-resize;} #cDown{bottom: -4px;left: 50%;margin-left: -4px;cursor: n-resize;} #cLeftDown{bottom: -4px;left: -4px;cursor: ne-resize;} #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 | 元素上边界相对于父元素的上边界偏移的像素值 |
X2-X1+L和
Y2-Y1+T。 原理如图
![](https://www.denpe.com/content/images/2016/04/clip-x.jpg)
代码如下
function $(id){ return document.getElementById(id) }; var cArea = $('cArea'); // 图片容器 var clipImg = $('clipImg'); // 裁剪层 var drag = $('drag'); // 拖拽区域 var previewImg = $('previewImg'); //预览图 var cAreaH = cArea.offsetHeight; // 图片显示区的高度 var cAreaW = cArea.offsetWidth; // 图片显示区的宽度 var cAreaTop = getPosition(cArea).Y; //图片容器距离浏览器上边界距离 var cAreaLeft = getPosition(cArea).X; //图片容器距离浏览器左边界距离 var mousePosition,mouseStartX,mouseStartY,dragLeft,dragTop,dragMaxH,dragMaxW // 定义按下鼠标时产生的变量 drag.addEventListener('mousedown', startDrag, false); // 给拖拽区添加鼠标按下事件 function startDrag(e) { e.preventDefault(); mouseStartX = e.clientX; // 刚按下鼠标时 鼠标相对浏览器边界的 X 坐标 mouseStartY = e.clientY; // 刚按下鼠标时 鼠标相对浏览器边界的 Y 坐标 dragLeft = drag.offsetLeft; // 刚按下鼠标时 裁剪区的距离图片显示区 左 边界距离 dragTop = drag.offsetTop; // 刚按下鼠标时 裁剪区的距离图片显示区 上 边界距离 dragMaxH = cAreaH - drag.offsetHeight; // 垂直最大范围 dragMaxW = cAreaW - drag.offsetWidth; // 水平最大范围 mousePosition = e.target.id; // 判断按下位置 document.addEventListener('mousemove', dragging, false); document.addEventListener('mouseup', clearDragEvent, false); }; // 鼠标松开时释放事件 function clearDragEvent(e) { document.removeEventListener('mousemove', dragging, false); document.removeEventListener('mouseup', clearDragEvent, false) }; // 整体拖拽 function dragMove(e) { var moveX = e.clientX - mouseStartX; // 拖拽中 鼠标坐标变化值 var moveY = e.clientY - mouseStartY; // 拖拽中 鼠标坐标变化值 var destinationX = Math.min((moveX + dragLeft), dragMaxW); // 限制拖动的最大范围,避免超出右和下边界 var destinationY = Math.min((moveY + dragTop), dragMaxH); // 限制拖动的最大范围,避免超出右和下边界 drag.style.left = destinationX < 0 ? 0 : destinationX + 'px'; // 限制最小范围,避免超出上和左边界 drag.style.top = destinationY < 0 ? 0 : destinationY + 'px'; // 限制最小范围,避免超出上和左边界 setClip(); };
JS 控制八个点的拖动
拖拽有八个点控制点,实际只需要写上下左右四个方法就可实现,四个角落的拖拽分别同时对应左上,右上,左下,右下。以上方中间控制点为例,当拖拽此点时,拖拽显示区水平位置并没有变化,只是本身的高度和距离父元素顶部距离发生改变。获取到拖拽区距离浏览器上边界距离 dragY,再获取到鼠标上下拖拽时鼠标的垂直坐标 mouseY。拖拽区的高度变化就等于dragY-mouseY。也很容易看出拖拽区top属性值变化就等于他原来距离父元素的距离减去自身高度变化。效果如下图:
代码如下:
// 上方边框拖动 function upMove(e) { var draggingY = e.clientY; // 鼠标Y坐标 if(draggingY < cAreaTop) draggingY = cAreaTop; //防止跑出图片上边界 var dragY = getPosition(drag).Y; // 拖拽区距离父元素边界 var changeHeight = dragY - draggingY; //改变高度 drag.style.top = drag.offsetTop - dragY + draggingY + 'px'; drag.style.height = drag.offsetHeight + changeHeight + 'px'; };
下面中间点与此类似,左右也是同样计算到方法。当然还可以将上下何在一起,左右合在一起。
// 上下方向的边框拖动 function upDownMove(e, str) { var draggingY = e.clientY; if(draggingY < cAreaTop) draggingY = cAreaTop; if(draggingY > cAreaTop + cAreaH) draggingY = cAreaTop + cAreaH; var dragY = getPosition(drag).Y; if(str === 'up'){ var changeHeight = dragY - draggingY; drag.style.top = drag.offsetTop - dragY + draggingY + 'px'; } else if(str === 'down') { var changeHeight = draggingY - drag.offsetHeight - dragY; } drag.style.height = drag.offsetHeight + changeHeight + 'px'; setClip(); }; // 水平方向的边框拖动 function leftRightMove(e, str) { var draggingX = e.clientX; if(draggingX < cAreaLeft) draggingX = cAreaLeft; if(draggingX > cAreaLeft + cAreaW) draggingX = cAreaLeft + cAreaW; var dragX = getPosition(drag).X; if(str === 'left') { var changeWidth = dragX - draggingX; drag.style.left = drag.offsetLeft - changeWidth + 'px'; } else if(str === 'right') { var changeWidth = draggingX - drag.offsetWidth - dragX; } drag.style.width = drag.offsetWidth + changeWidth + 'px'; setClip(); };
中间层和拖拽区以及预览区的同步显示
这个非常简单,知道了拖拽区的坐标和尺寸,就很容易计算出中间层clip属性值。function setClip() { // 显示层 var clipTop = drag.offsetTop; var clipLeft = drag.offsetLeft; var clipRight = drag.offsetWidth + drag.offsetLeft; var clipBottom = drag.offsetHeight + drag.offsetTop; clipImg.style.clip = 'rect(' + clipTop + 'px ' + clipRight + 'px ' + clipBottom + 'px ' + clipLeft + 'px)'; setPreview({top: clipTop, right: clipRight, bottom: clipBottom, left: clipLeft}) }; function setPreview(clip){ // 预览图 previewImg.style.top = -clip.top + 'px'; previewImg.style.left = -clip.left + 'px'; previewImg.style.clip = 'rect(' + clip.top + 'px ' + clip.right + 'px ' + clip.bottom + 'px '+ clip.left + 'px)'; };
相关文章推荐
- 解决jsCookie 页面跳转失效问题
- [JSOI2016]反质数序列
- 2016年5月26日晚上(妙味课堂js基础-2笔记四(BOM))
- 2016年5月26日晚上(妙味课堂js基础-2笔记三(DOM))
- 实习入职第六天---快速查看JSON格式化工具
- 便签4-js数组
- Extjs框架html5中input、textarea的placeholder,元素内容为空时,颜色为灰色
- JSON.parse解析json数据及取值的几种方式
- 玩转js--炫酷抽奖轮盘
- js 去掉字符串前后空格
- IntelliJ IDEA中js代码报如下警告的解决方法
- high performence javascript(高性能JavaScript)
- 在JSP中添加图片
- [RxJS] Combination operator: withLatestFrom
- JSP和Servlet之间跳转总结
- js模版引擎介绍
- 网页进度条实现
- [RxJS] Combination operator: zip
- Javascript 读取浏览器名及版本号
- 主流web界面播放器的页面引用以及浏览器的支持情况分析(VLC)