原生 JavaScript 图片裁剪效果
图片裁剪程序效果如下,可鼠标操作。

拖动左边小方框时在右侧实时显示对应的裁剪图片,同时左侧的拖动框里图片完全显示,拖动框外部图片模糊显示。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 | 元素上边界相对于父元素的上边界偏移的像素值 |
在鼠标按下拖拽区域后(mousedown事件),立即记录此时鼠标的 X1 Y1 坐标位置,以及此时拖拽区域相对图片层的左边界距离L,上边界距离T。在鼠标进行移动时记录移动过程中的 X2 Y2 坐标位置。拖拽区域的left和top属性值分别为:X2-X1+L
和 Y2-Y1+T
。 原理如图
代码如下
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)';
};
原生 JavaScript 图片裁剪效果的更多相关文章
- javascript图片放大镜效果展示
javascript图片放大镜效果展示 <!DOCTYPE html> <html> <head lang="en"> <meta cha ...
- JavaScript图片裁剪
1.jquery 图片裁剪库选择 Jcrop:http://deepliquid.com/content/Jcrop.html imgareaselect:http://odyniec.net/pro ...
- 纯原生javascript实现分页效果
随着近几年前端行业的迅猛发展,各种层出不穷的新框架,新方法让我们有点眼花缭乱. 最近刚好比较清闲,所以没事准备撸撸前端的根基javascript,纯属练练手,写个分页,顺便跟大家分享一下 functi ...
- JAVASCRIPT——图片滑动效果
点击按钮开始整体右移,移动至蓝色区域全部显示出来停止. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu ...
- 原生JavaScript实现新手引导效果(第二个玩具)
慕课地址https://www.imooc.com/video/169 预览效果: <!DOCTYPE html> <html> <head> <meta c ...
- 原生JavaScript实现评分效果
一.实现原理: 1.要设置一个“大总管变量”,用于记录点击时的星星下标,只声明不赋值. 2.移入每个星星时,先把所有的星星恢复到默认状态:再把当前星星及在它之前的星星设为选中状态. 3.移出每个星星时 ...
- 原生javascript实现分页效果+搜索功能
一.概述 首先,我们要明确为何需要分页技术,主要原因有以下: 1.分页可以提高客户体验度,适当地选择合适的数据条数,让页面显得更有条理,使得用户体验感良好,避免过多数据的冗余. 2.提高性能的需要. ...
- 原生javascript写的侧栏跟随效果
浏览网站时经常看到有的网站上,当一个页面很长的时候,设定侧栏内容会跟随滚动条滚动,我们把这种效果叫做“侧栏跟随滚动”.这种特效对提高网站浏览量.文章点击率.广告点击量都有一定效果. 侧栏跟随滚动的实现 ...
- 原生javascript实现图片放大镜效果
当我们在电商网站上购买商品时,经常会看到这样一种效果,当我们把鼠标放到我们浏览的商品图片上时,会出现类似放大镜一样的一定区域的放大效果,方便消费者观察商品.今天我对这一技术,进行简单实现,实现图片放大 ...
随机推荐
- 3D Touch的简单使用
6s发布以后新增了一个3D touch功能,我个人觉得这个功能点在某些时候还是挺方便的,比如说微信的扫码功能. 直接长按图标就可以进入这个功能里面,不用再打开app.一层层查找了,比较方便. 其实这个 ...
- Enter password: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
1.kill掉列出的进程: [root@localhost mysql]# ps -a | grep -i mysql pts/ :: mysqld_safe pts/ :: mysqld <d ...
- ADS的使用
ADS是一款强大的软件,应用程序不能直接操作硬件,而ADS程序是无操作系统支持的,可以直接操作硬件,下面来介绍一下ADS的基本使用方法. 编辑本段基本简介: ADS(ARM Developer Sui ...
- json解析日期方法 问题的解决方案
之前在做项目的时候发现,用json格式传输日期数据的时候,发现从数据库中传回到页面的数据出现错误,查阅相关资料才知道,原来json不支持日期解析,要自己解决,解决方案也很简单,写一段js代码就OK了- ...
- sql server 2008 r2 清除数据库日志
USE [master] GO ALTER DATABASE [数据库名] SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE [数据库名] SET ...
- 整理:sql语句优化之SQL Server
. 增加服务器CPU个数;但是必须明白并行处理串行处理更需要资源例如内存.使用并行还是串行程是MsSQL自动评估选择的.单个任务分解成多个任务,就可 以在处理器上运行.例如耽搁查询的排序.连接.扫描和 ...
- Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行
Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候 ...
- Appium 提高脚本复用、可配置性
- article元素设计网络新闻展示
article元素用来表示文档.页面中独立的.完整的.可以独自被外部引用的内容.它可以是一篇文章博客或者报刊中的文章.一篇论坛帖子.一段用户评论或独立的插件等.除了内容部分,一个article元素通常 ...
- <a>多颜色标签点击之后保持原色的一次实践, Ext Panel下解决及通用方案思路
代码为片段, 需要自行设置全部环境方可全部运行. 案例背景 使用Ext开发了一个表格,需要根据一列值来动态设置颜色. 效果如下: 说明: 不同行显示不同的内容, 作为标题行, 可以点击链接到其他地方. ...