基于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 相关文章推荐
在textarea中屏蔽js的某个function的javascript代码
Apr 20 Javascript
基于jquery的兼容各种浏览器的iframe自适应高度的脚本
Aug 13 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
Aug 02 Javascript
javascript中的self和this用法小结
Feb 08 Javascript
Javascript 数组排序详解
Oct 22 Javascript
javascript实现在线客服效果
Jul 15 Javascript
js中的关联数组与普通数组详解
Jul 27 Javascript
Bootstrap组合上、下拉框简单实现代码
Mar 06 Javascript
Javascript中字符串相关常用的使用方法总结
Mar 13 Javascript
JS图片预加载插件详解
Jun 21 Javascript
javascript实现打砖块小游戏(附完整源码)
Sep 18 Javascript
小程序自定义圆形进度条
Nov 17 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
用Flash图形化数据(一)
2006/10/09 PHP
PHP strncasecmp字符串比较的小技巧
2011/01/04 PHP
关于php 接口问题(php接口主要也就是运用curl,curl函数)
2013/07/01 PHP
jquery+php+ajax显示上传进度的多图片上传并生成缩略图代码
2014/10/15 PHP
php获取Google机器人访问足迹的方法
2015/04/15 PHP
Gambit vs CL BO3 第二场 2.13
2021/03/10 DOTA
jQuery的三种$()
2009/12/30 Javascript
JQUERY设置IFRAME的SRC值的代码
2010/11/30 Javascript
基于jquery的loading 加载提示效果实现代码
2011/09/01 Javascript
javascript 判断中文字符长度的函数代码
2012/08/27 Javascript
javascript实例分享---具有立体效果的图片特效
2014/06/08 Javascript
Jquery中Event对象属性小结
2015/02/27 Javascript
JS实现简易图片轮播效果的方法
2015/03/25 Javascript
jQuery选择器源码解读(四):tokenize方法的Expr.preFilter
2015/03/31 Javascript
浅谈JavaScript中setInterval和setTimeout的使用问题
2015/08/01 Javascript
原生js和jQuery实现淡入淡出轮播效果
2015/12/25 Javascript
jQuery对table表格进行增删改查
2020/12/22 Javascript
javaScript+turn.js实现图书翻页效果实例代码
2017/02/16 Javascript
阿里大于短信验证码node koa2的实现代码(最新)
2017/09/07 Javascript
JS实现textarea通过换行或者回车把多行数字分割成数组并且去掉数组中空的值
2018/10/29 Javascript
JavaScript提升机制Hoisting详解
2019/10/23 Javascript
Nuxt 项目性能优化调研分析
2020/11/07 Javascript
python中实现php的var_dump函数功能
2015/01/21 Python
使用Python求解最大公约数的实现方法
2015/08/20 Python
python中安装Scrapy模块依赖包汇总
2017/07/02 Python
python2.7无法使用pip的解决方法(安装easy_install)
2018/04/03 Python
Python正则匹配判断手机号是否合法的方法
2020/12/09 Python
Python3 解决读取中文文件txt编码的问题
2019/12/20 Python
python-sys.stdout作为默认函数参数的实现
2020/02/21 Python
python中的selenium安装的步骤(浏览器自动化测试框架)
2020/03/17 Python
基于Tensorflow读取MNIST数据集时网络超时的解决方式
2020/06/22 Python
最耐用行李箱,一箱永流传:Briggs & Riley(全球终身保修)
2017/12/07 全球购物
给女儿的表扬信
2014/01/18 职场文书
优秀通讯员事迹材料
2014/01/28 职场文书
音乐会主持人开场白
2015/05/28 职场文书
军训后的感想
2015/08/07 职场文书