基于JavaScript实现图片剪切效果


Posted in Javascript onMarch 07, 2017

学会如何获取鼠标的坐标位置以及监听鼠标的按下、拖动、松开等动作事件,从而实现拖动鼠标来改变图片大小。

还可以学习css中的clip属性。

一、CSS实现图片不透明及裁剪效果。

图片剪切三层结构

1、第一层opacity,给图层设置透明度

2、第二层clip,clip属性:对图片进行裁剪,实现图像的一部分显示,其他部分进行隐藏

3、第三层选取框absolute(与第二层重叠的),包括八个触点的效果

基于JavaScript实现图片剪切效果

html代码:

<div id="box">
 <img src="img/1.jpg" id="img1" />
 <img src="img/1.jpg" id="img2" />
 <div id="main">
  <div class="Divmin up-left"></div>
  <div class="Divmin up"></div>
  <div class="Divmin up-right"></div>
  <div class="Divmin right"></div>
  <div class="Divmin right-down"></div>
  <div class="Divmin down"></div>
  <div class="Divmin left-down"></div>
  <div class="Divmin left"></div>
 </div>
</div>

css代码:

body{
  background: #333;
 }
 #box{
  width: 500px;
  height: 380px;
  position: absolute;
  top: 100px;
  left: 200px;
 }
 #img1,#img2{
  position: absolute;
  top: 0;
  left: 0;
 }
 #img1{
  opacity: 0.3;
 }
 #img2{
  clip: rect(0,200px,200px,0);
 }
 #main{
  position: absolute;/*第三层需用绝对定位浮在上面*/
  width: 200px;
  height: 200px;
  border: 1px solid #fff;
 }
 .Divmin{
  position: absolute;
  width: 8px;
  height: 8px;
  background: #fff;
 }
 .up-left{margin-top: -4px;margin-left: -4px;cursor: nw-resize;}
 .up{
  left: 50%;/*父元素盒子main宽度的一半,注意要有绝对定位*/
  margin-left:-4px;
  top: -4px;
  cursor: n-resize;
 }
 .up-right{top: -4px;right: -4px;cursor: ne-resize;}
 .right{top: 50%;margin-top: -4px;right: -4px;cursor: e-resize;}
 .right-down{right: -4px;bottom: -4px;cursor: se-resize;}
 .down{bottom: -4px;left: 50%;margin-left: -4px;cursor: s-resize;}
 .left-down{left: -4px;bottom: -4px;cursor: sw-resize;}
 .left{left: -4px;top: 50%;margin-top: -4px;cursor: w-resize;}

二、javascript获取选择框偏移量

选择框鼠标拖动位置详解:

offsetLeft:元素相对于其父元素左边界的距离;

clientX:鼠标位置的横坐标;

clientWidth:元素的宽度;

offsetXY:是该事件发生的盒子模型里的坐标,与滚动条无关。

clientXY:是整个浏览器可用部分里的坐标,与滚动条无关,即需要拖动滚动条才能看到的区域不考虑。

pageXY:是整个网页里的坐标,与滚动条有关。

基于JavaScript实现图片剪切效果

构造一个getPosition()函数,用于获取元素相对于屏幕左边及上边的距离

js代码如下:

//获取元素相对于屏幕左边及上边的距离,利用offsetLeft
 function getPosition(el){
  var left = el.offsetLeft;
  var top = el.offsetTop;
  var parent = el.offsetParent;
  while(parent != null){
   left += parent.offsetLeft;
   top += parent.offsetTop;
   parent = parent.offsetParent;
  }
  return {"left":left,"top":top};
 }

三、javascript实现控制触点

监听鼠标的按下、拖动、松开的事件控制选取框的大小。

注意区别:

Element.clientWidth 属性表示元素的内部宽度,以像素计。该属性包括内边距,但不包括垂直滚动条(如果有的话)、边框和外边距。

即clientWidth不包括边框,offsetWidth包括边框

1)点击右面的触点

js代码:

var mainDiv = $('main');
 var rightDiv = $('right');
 var isDraging = false;
 var contact = "";//表示被按下的触点
 //鼠标按下时
 rightDiv.onmousedown = function(){
  isDraging = true;
  contact = "right";
 }
 //鼠标松开时
 window.onmouseup = function(){
  isDraging = false;
 }
 //鼠标移动时
 window.onmousemove = function(e){
  if(isDraging == true){
   if(contact == "right"){
    var e = e||window.event;
    var x = e.clientX;//鼠标位置的横坐标
    var widthBefore = mainDiv.offsetWidth - 2;//选取框变化前的宽度
    //var widthBefore = mainDiv.clientWidth;
    var addWidth = x - getPosition(mainDiv).left - widthBefore;//鼠标移动后选取框增加的宽度
    mainDiv.style.width = widthBefore + addWidth + 'px';//选取框变化后的宽度
   }
  }
 }
//获取id的函数
function $(id){
 return document.getElementById(id);
}

2)点击上面触点

点击上面中间的触点移动时,选取框的高度和左上角的位置都需要变化。

增加的高度=选取框相对于屏幕上面的距离 - 鼠标位置的纵坐标

选取框左上角的top值要减去增加的高度,因为鼠标向上移动时高度增加,top值减小,下移时高度减小,top增大。

变化示意图:

基于JavaScript实现图片剪切效果

js代码:

else if(contact == "up"){
    var y = e.clientY;//鼠标位置的纵坐标
    var heightBefore = mainDiv.offsetHeight - 2;//选取框变化前的高度
    var addHeight = getPosition(mainDiv).top - y;//增加的高度
    mainDiv.style.height = heightBefore + addHeight + 'px';//选取框变化后的宽度
    mainDiv.style.top = mainDiv.offsetTop - addHeight + 'px';//相当于变化后左上角的纵坐标,鼠标向上移纵坐标减小,下移增大
   }

 3)点击左边触点

原理同点击上面触点,宽度和左边的位置都会变化

变化示意图:

基于JavaScript实现图片剪切效果

js代码:

else if(contact == "left"){
     var widthBefore = mainDiv.offsetWidth - 2;
      var addWidth = getPosition(mainDiv).left - e.clientX;//增加的宽度等于距离屏幕左边的距离减去鼠标位置横坐标
      mainDiv.style.width = widthBefore + addWidth + 'px';
     mainDiv.style.left = mainDiv.offsetLeft - addWidth + 'px';//左边的距离(相当于左边位置横坐标)等于选取框距父级元素的距离减去增加的宽度
   }

 4)点击下面触点

增加的宽度 = 鼠标位置纵坐标 - 距屏幕上边的距离 - 原先的宽度

左上角的位置不需改变

js代码:

else if(contact = "down"){
     var heightBefore = mainDiv.offsetHeight - 2;
     var addHeight = e.clientY - getPosition(mainDiv).top - mainDiv.offsetHeight;
     mainDiv.style.height = heightBefore + addHeight + 'px';
    }

 5)点四个角时的变化是高度和宽度变化的叠加,所以最好将上面四个变化的过程封装成函数,便于维护和代码复用。

      如果用if else 需要判断8次,所以改为switch语句来简化代码

      修改后的js代码如下:

window.onmousemove = function(e){
  var e = e||window.event;
  if(isDraging == true){
   switch (contact){
    case "up" : upMove(e);break;
    case "right" : rightMove(e);break;
    case "down" : downMove(e);break;
    case "left" : leftMove(e);break;
    case "up-right" : upMove(e);rightMove(e);break;
    case "down-right" : downMove(e);rightMove(e);break;
    case "down-left" : downMove(e);leftMove(e);break;
    case "up-left" : upMove(e);leftMove(e);break;
   }
  }
 }
//获取id的函数
function $(id){
 return document.getElementById(id);
}
//获取元素相对于屏幕左边及上边的距离,利用offsetLeft
 function getPosition(el){
  var left = el.offsetLeft;
  var top = el.offsetTop;
  var parent = el.offsetParent;
  while(parent != null){
   left += parent.offsetLeft;
   top += parent.offsetTop;
   parent = parent.offsetParent;
  }
  return {"left":left,"top":top};
 }
 //up移动
 function upMove(e){
  var y = e.clientY;//鼠标位置的纵坐标
  var heightBefore = mainDiv.offsetHeight - 2;//选取框变化前的高度
  var addHeight = getPosition(mainDiv).top - y;//增加的高度
  mainDiv.style.height = heightBefore + addHeight + 'px';//选取框变化后的宽度
  mainDiv.style.top = mainDiv.offsetTop - addHeight + 'px';//相当于变化后左上角的纵坐标,鼠标向上移纵坐标减小,下移增大
 }
 //right移动
 function rightMove(e){
  var x = e.clientX;//鼠标位置的横坐标
  var widthBefore = mainDiv.offsetWidth - 2;//选取框变化前的宽度
  //var widthBefore = mainDiv.clientWidth;
  var addWidth = x - getPosition(mainDiv).left - widthBefore;//鼠标移动后选取框增加的宽度
  mainDiv.style.width = widthBefore + addWidth + 'px';//选取框变化后的宽度
 }
 //down移动
 function downMove(e){
  var heightBefore = mainDiv.offsetHeight - 2;
  var addHeight = e.clientY - getPosition(mainDiv).top - mainDiv.offsetHeight;
  mainDiv.style.height = heightBefore + addHeight + 'px';
 }
 //left移动
 function leftMove(e){
  var widthBefore = mainDiv.offsetWidth - 2;
  var addWidth = getPosition(mainDiv).left - e.clientX;//增加的宽度等于距离屏幕左边的距离减去鼠标位置横坐标
  mainDiv.style.width = widthBefore + addWidth + 'px';
  mainDiv.style.left = mainDiv.offsetLeft - addWidth + 'px';//左边的距离(相当于左边位置横坐标)等于选取框距父级元素的距离减去增加的宽度
 }

四、实现选取框区域明亮显示

1)选取框内的第二层图片需重新设置其clip属性

四个方面图示:

基于JavaScript实现图片剪切效果

js代码:

//设置选取框图片区域明亮显示
 function setChoice(){
  var top = mainDiv.offsetTop;
  var right = mainDiv.offsetLeft + mainDiv.offsetWidth;
  var bottom = mainDiv.offsetTop + mainDiv.offsetHeight;
  var left = mainDiv.offsetLeft;
  img2.style.clip = "rect("+top+"px,"+right+"px,"+bottom+"px,"+left+"px)";
 }

2)鼠标移动时会导致图片被选中,可在js代码中添加一行代码使其禁止图片被选中

//禁止图片被选中
 document.onselectstart = new Function('event.returnValue = false;');

也可以在css样式里添加 *{user-select:none}

意思是文本不可选中,对图片跟div有一样的效果。

五、实现选取框位置可拖动

首先要阻止事件冒泡

js代码如下: 

//鼠标按下触点时
 rightDiv.onmousedown = function(e){
  e.stopPropagation();
  isDraging = true;
  contact = "right";
 }

鼠标拖拽效果的实现可见另一篇随笔http://www.cnblogs.com/vampire170204/p/6422914.html

六、实现图片剪切区域预览

新增一个图片预览区域的div

html代码:

<div id="preview">
 <img src="img/1.jpg" id="img3" />
</div>

css代码:

#preview{
  position: absolute;
  width: 500px;
  height: 380px;
  top: 100px;
  left:710px ;
 }
 #preview #img3{position: absolute;}

注意:要让clip:rect(top,right,bottom,left) 起作用,必须让作用元素为相对/绝对定位。

js部分同样是利用clip属性,和setChoice()函数同时被调用

同时为了让右边预览区的左上角位置固定,需要设置其top和left的值

//右边图片预览函数
 function setPreview(){
  var top = mainDiv.offsetTop;
  var right = mainDiv.offsetLeft + mainDiv.offsetWidth;
  var bottom = mainDiv.offsetTop + mainDiv.offsetHeight;
  var left = mainDiv.offsetLeft;
  var img3 = $('img3');
  img3.style.top = -top + 'px';
  img3.style.left = -left + 'px';
  img3.style.clip = "rect("+top+"px,"+right+"px,"+bottom+"px,"+left+"px)";
 }

以上所述是小编给大家介绍的基于JavaScript实现图片剪切效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用javascript实现点击链接弹出&quot;图片另存为&quot;而不是直接打开
Aug 15 Javascript
超级24小时弹窗代码 24小时退出弹窗代码 100%弹窗代码(IE only)
Jun 11 Javascript
jQuery写fadeTo示例代码
Feb 21 Javascript
JavaScript学习心得之概述
Jan 20 Javascript
JavaScript创建一个object对象并操作对象属性的用法
Mar 23 Javascript
浅谈JavaScript 数据属性和访问器属性
Sep 01 Javascript
js实现tab选项卡切换功能
Jan 13 Javascript
jQuery弹出窗口简单实现代码
Mar 09 Javascript
jquery实现的table排序功能示例
Mar 10 Javascript
vue.js 实现图片本地预览 裁剪 压缩 上传功能
Mar 01 Javascript
layui-tree实现Ajax异步请求后动态添加节点的方法
Sep 23 Javascript
实例讲解React 组件生命周期
Jul 08 Javascript
详解Vue2 无限级分类(添加,删除,修改)
Mar 07 #Javascript
js放到head中失效的原因与解决方法
Mar 07 #Javascript
Bootstrap媒体对象学习使用
Mar 07 #Javascript
angular十大常见问题
Mar 07 #Javascript
Bootstrap表单控件学习使用
Mar 07 #Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
Mar 07 #Javascript
Bootstrap进度条实现代码解析
Mar 07 #Javascript
You might like
vBulletin HACK----关于排版的两个HACK
2006/10/09 PHP
zf框架的zend_cache缓存使用方法(zend框架)
2014/03/14 PHP
Yii2使用小技巧之通过 Composer 添加 FontAwesome 字体资源
2014/06/22 PHP
用js实现键盘方向键翻页功能的代码
2007/06/03 Javascript
jQuery弹出层插件简化版代码下载
2008/10/16 Javascript
为jquery.ui.dialog 增加“自动记住关闭时的位置”的功能
2009/11/24 Javascript
javascript 全等号运算符使用说明
2010/05/31 Javascript
jQuery Autocomplete自动完成插件
2010/07/17 Javascript
用js来解决ajax读取页面乱码
2010/11/28 Javascript
js中通过父级进行查找定位元素
2014/06/15 Javascript
jQuery中toggleClass()方法用法实例
2015/01/05 Javascript
jQuery源码分析之jQuery.fn.each与jQuery.each用法
2015/01/23 Javascript
JS插件overlib用法实例详解
2015/12/26 Javascript
JS组件Form表单验证神器BootstrapValidator
2016/01/26 Javascript
Bootstrap开发实战之第一次接触Bootstrap
2016/06/02 Javascript
jQuery事件委托之Safari
2016/07/05 Javascript
JS触摸屏网页版仿app弹窗型滚动列表选择器/日期选择器
2016/10/30 Javascript
Vue 父子组件的数据传递、修改和更新方法
2018/03/01 Javascript
简单了解TypeScript中如何继承 Error 类
2019/06/21 Javascript
刷新页面后让控制台的js代码继续执行
2019/09/20 Javascript
[04:49]2014DOTA2国际邀请赛 Newbee顺利挺进总决赛 ImbaTV独家专访
2014/07/19 DOTA
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
python使用多线程不断刷新网页的方法
2015/03/31 Python
Python使用MYSQLDB实现从数据库中导出XML文件的方法
2015/05/11 Python
matlab中实现矩阵删除一行或一列的方法
2018/04/04 Python
解决PySide+Python子线程更新UI线程的问题
2019/01/11 Python
python实现可逆简单的加密算法
2019/03/22 Python
基于python cut和qcut的用法及区别详解
2019/11/22 Python
Pytorch Tensor基本数学运算详解
2019/12/30 Python
台湾前三大B2C购物网站:MOMO购物网
2017/04/27 全球购物
Deux par Deux官方网站:设计师童装
2020/01/03 全球购物
给民警的表扬信
2014/01/08 职场文书
2014最新毕业证代领委托书
2014/09/26 职场文书
法制主题班会教案
2015/08/13 职场文书
jQuery实现影院选座订座效果
2021/04/13 jQuery
mybatis 获取无数据的字段不显示的问题
2021/07/15 Java/Android