JS实现图片剪裁并预览效果


Posted in Javascript onAugust 12, 2016

今天又疯狂学习了web前端的图片剪裁效果,可以有个区域来框住图片的某一部分,并可以预览框住的部分 

效果图如下:

JS实现图片剪裁并预览效果

看着是不是很炫呢

简单介绍下实现方法吧

1.布局就是左右两块div,右边的好说,主要是左边的,左边的用绝对布局的方式分了3层,最下面一层是一个半透明的图片,中间一层是原图,但被剪切成只有一块,也只显示这一块,可以用clip:rect方法实现,然后最上面一层就是自己写的一个边框,在边框上加了8个点,分别给这8个点定义位置。 

2.然后JS代码用了鼠标的点击事件来实现。 

下面贴上自己的代码:

index.html (这里要引用两个js文件,分别是jquery和jquery-ui,其中jquery可以引用网上的,jquery-ui我是自己下在本地引用的,大家可以自己去官网下载,不引用则不能实现拖动剪切框) 

<!DOCTYPE HTML>
<html>
<head lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>图片剪切</title>
<script src="http://cdn.bootcss.com/jquery/2.2.0/jquery.min.js" type="text/javascript"></script>
<script src="js/jquery-ui-1.12.0/jquery-ui.min.js"></script>
<link href="img.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="img.js"></script>
</head>
<body>
 <div id="box">
 <img src="images/1.jpg" id="img1">
 <img src="images/1.jpg" id="img2">
 <div id="main">
 <div id="left-up" class="minDiv left-up"></div>
 <div id="up" class="minDiv up"></div>
 <div id="right-up" class="minDiv right-up"></div>
 <div id="right" class="minDiv right"></div>
 <div id="right-down" class="minDiv right-down"></div>
 <div id="down" class="minDiv down"></div>
 <div id="left-down" class="minDiv left-down"></div>
 <div id="left" class="minDiv left"></div>
 </div>
 </div>
 <div id="preview">
 <img src="images/1.jpg" id="img3">
 </div>

</body>
</html>
 img.css
 

body {
 background-color: #333;
}

#box {
 position: absolute;
 top: 200px;
 left: 100px;
 width: 600px;
 height: 319px;
}

#img1 {
 /*不透明度*/
 opacity: 0.3;
 position:absolute;
 top: 0;
 left: 0;

}

#img2 {
 position: absolute;
 top: 0;
 left: 0;

 /*用于剪切图像的函数
 clip: rect(top,right,bottom,left);
 top表示剪切区域顶部离图片顶部的距离
 right表示剪切区域右边离图片左边的距离,即长+left
 bottom表示剪切区域底部离图片顶部的距离,即宽+top
 left表示剪切区域左边离图片左边的距离
 */
 clip: rect(0, 200px, 200px, 0);
}

#main {
 position: absolute;
 border: 1px solid #fff;
 width:200px;
 height: 200px;
}

#preview {
 position: absolute;
 width: 600px;
 height: 319px;
 top:200px;
 left: 720px;
}
#preview img{
 /*要让函数setPreview里的clip函数达到作用,要给img增加绝对定位或者相对定位
 但由于父元素是绝对定位,所以这里是绝对定位*/
 position: absolute;
}

.minDiv {
 position: absolute;
 width: 8px;
 height: 8px;
 background-color: #fff;
}

.left-up {
 top:-4px;
 left: -4px;

 /*鼠标变化 n-北 w-西 s-南 e-东*/
 cursor: nw-resize;
}

.up {
 /*距最近的一个position属性为absolute或者relative的父级元素左边50%的距离
 除此之外 top right bottom也是距最近的一个position属性为absolute或者relative的父级元素
 的距离
 */
 left: 50%;
 /*距离左边-4px即向左边移动4px*/
 margin-left: -4px;
 top:-4px;
 cursor: n-resize;
}

.right-up {
 right: -4px;
 top: -4px;
 cursor: ne-resize;
}

.right {
 top: 50%;
 margin-top:-4px;
 right: -4px;
 cursor: e-resize;
}

.right-down {
 bottom: -4px;
 right: -4px;
 cursor: se-resize;
}

.down {
 left: 50%;
 margin-left: -4px;
 bottom: -4px;
 cursor: s-resize;
}

.left-down {
 left: -4px;
 bottom: -4px;
 cursor: sw-resize;
}

.left {
 bottom: 50%;
 margin-bottom: -4px;
 left: -4px;
 cursor: w-resize;
}
 img.js
 

// 在元素加载完之后执行,确保元素可以成功获取
window.onload =function(){

 document.onselectstart = new Function('event.returnValue=false;');
 $("#main").draggable({containment:'parent', drag:setChoice});
 var img = document.getElementById("img2");

 var rightDiv = document.getElementById("right");
 var upDiv = document.getElementById("up");
 var leftDiv = document.getElementById("left");
 var downDiv = document.getElementById("down");
 var leftupDiv = document.getElementById("left-up");
 var rightupDiv = document.getElementById("right-up");
 var rightdownDiv = document.getElementById("right-down");
 var leftdownDiv = document.getElementById("left-down");

 var mainDiv = document.getElementById("main");
 var ifKeyDown = false; 

 var contact = "";// 表示被按下的触点

 //鼠标按下状态
 rightDiv.onmousedown = function(e) {
 /*拖动效果引入的jquery 和 jquery-ui也会去触发鼠标点击事件,
 所以为了防止自己定义的点击事件和引入的点击事件冲突,传入e并加入以下
 这条语句,防止冒泡。冒泡是指鼠标点击里面的元素时也会触发父元素的一些事件*/
 e.stopPropagation();
 ifKeyDown = true;
 contact = "right";
 }
 upDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "up";
 }
 leftDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "left";
 }
 downDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "down";
 }
 leftupDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "left-up";
 }
 rightupDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "right-up";
 }
 rightdownDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "right-down";
 }
 leftdownDiv.onmousedown = function(e) {
 e.stopPropagation();
 ifKeyDown = true;
 contact = "left-down";
 }

 //鼠标松开状态
 window.onmouseup = function() {
 ifKeyDown = false;
 }

 //鼠标移动事件
 window.onmousemove = function(e) {
 if(ifKeyDown == true){

 switch(contact){
 case "right": rightMove(e); break;
 case "up": upMove(e); break;
 case "left": leftMove(e); break;
 case "down": downMove(e); break;
 case "left-up": leftMove(e); upMove(e); break;
 case "right-up": rightMove(e); upMove(e); break;
 case "right-down": rightMove(e); downMove(e); break;
 case "left-down": leftMove(e); downMove(e); break;
 }

 }
 setChoice();
 setPreview();
 
 }
 //右边移动
 function rightMove(e) {
 var x = e.clientX; //鼠标x坐标
 var addWidth = ""; //鼠标移动后选取框增加的宽度
 var widthBefore = mainDiv.offsetWidth - 2; //选取框变化前的宽度,减2是为了减去边框border的宽,左右两边各为1px,所以是2
 addWidth = x - getPosition(mainDiv).left //鼠标移动后增加的宽度
 if(widthBefore <= img.width){
 mainDiv.style.width = addWidth + "px"; //选取框变化后的宽度
 } else {
 mainDiv.style.width = img.width + "px";
 }
 }

 //上边移动
 function upMove(e) {
 var topBefore = mainDiv.offsetTop;
 var y = e.clientY;//鼠标纵坐标
 var addHeight = 0;
 var mainY = getPosition(mainDiv).top;//选取框相对于屏幕上边的距离
 addHeight = y - mainY; //增加的高度
 var heightBefore = mainDiv.offsetHeight - 2;
 var bottom = topBefore + heightBefore;

 var heightAfter = heightBefore - addHeight;
 var topAfter = mainDiv.offsetTop + addHeight;

 if(topAfter < bottom && topAfter > -2){
 mainDiv.style.height = heightAfter + "px";
 mainDiv.style.top = topAfter + "px";
 }

 }

 //左边移动
 function leftMove(e) {
 // 左边框变化前距离父元素左边的距离
 var leftBefore = mainDiv.offsetLeft;
 // 鼠标按下停止后鼠标距离浏览器左边界的距离
 var x = e.clientX;
 // 定义增加的宽度
 var addWidth = 0;
 // 变化之前剪辑框的宽度
 var widthBefore = mainDiv.offsetWidth - 2;
 // 变化之前左边框距离浏览器左边界的距离
 var mainDivLeft = getPosition(mainDiv).left;
 // 右边框距离父元素的左边的距离
 var right = leftBefore + widthBefore;
 // 增加的宽度
 addWidth = x - mainDivLeft;
 // 变化之后剪辑框的宽度
 var widthAfter = widthBefore - addWidth;
 // 变化之后剪辑框离左边的距离
 var leftAfter = mainDiv.offsetLeft + addWidth;
 // 防止左边框移到右边框以外区域
 if(leftAfter < right && leftAfter > -2) {
 // 定义变化后的宽度
 mainDiv.style.width = widthAfter + "px";
 // 定义变化后距离左边父元素的距离
 mainDiv.style.left = leftAfter + "px";
 }
 
 }

 //下边移动
 function downMove(e) {
 var y = e.clientY;
 var addHeight = 0;
 var heightBefore = mainDiv.offsetHeight - 2;
 addHeight = y - getPosition(mainDiv).top;
 if(heightBefore <= img.height) {
 mainDiv.style.height = addHeight + "px";
 } else {
 mainDiv.style.height = img.height + "px";
 }
 
 }


 // 获取元素相对于屏幕左边的距离,利用offsetLeft
 // node为传入的元素
 function getPosition(node) {
 /*获取元素相对于父元素的左边距*/
 var left = node.offsetLeft;
 /*获取元素相对于父元素的上边距*/
 var top = node.offsetTop;
 /*获取元素的父元素*/
 var parent = node.offsetParent;
 /*判断是否存在父元素,存在则一直加上左边距,一直算出元素相对于浏览器
 左边界的距离*/
 while(parent != null) {
 /*循环累加子元素相对于父元素的左边距*/
 left += parent.offsetLeft;
 /*循环累加子元素相对于父元素的上边距*/
 top += parent.offsetTop;
 /*循环获取父元素的父元素,直至没有父元素为止*/
 parent = parent.offsetParent;
 }
 return {"left":left,"top":top};
 }


 //设置选取区域高亮可见
 function setChoice() {
 var top = mainDiv.offsetTop;
 var right = mainDiv.offsetLeft + mainDiv.offsetWidth;
 var bottom = mainDiv.offsetTop + mainDiv.offsetHeight;
 var left = mainDiv.offsetLeft;
 img.style.clip = "rect("+ top+"px,"+ right+"px,"+ bottom +"px,"+ left+"px"+")"
 }

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
分享精心挑选的12款优秀jQuery Ajax分页插件和教程
Aug 09 Javascript
JS运动基础框架实例分析
Mar 03 Javascript
AngularJS进行性能调优的7个建议
Dec 28 Javascript
D3.js实现直方图的方法详解
Sep 25 Javascript
jQuery插件fullPage.js实现全屏滚动效果
Dec 02 Javascript
前端JS面试中常见的算法问题总结
Dec 23 Javascript
js实现数组内数据的上移和下移的实例
Nov 14 Javascript
基于 Vue 实现一个酷炫的 menu插件
Nov 14 Javascript
JavaScript实现无限级递归树的示例代码
Mar 29 Javascript
vue微信分享的实现(在当前页面分享其他页面)
Apr 16 Javascript
vue3.0实现插件封装
Dec 14 Vue.js
如何在vue中使用kindeditor富文本编辑器
Dec 19 Vue.js
JS数组去掉重复数据只保留一条的实现代码
Aug 11 #Javascript
分享JS数组求和与求最大值的方法
Aug 11 #Javascript
利用JavaScript阻止表单提交的两种方法
Aug 11 #Javascript
防止Node.js中错误导致进程阻塞的办法
Aug 11 #Javascript
JavaScript中 ES6 generator数据类型详解
Aug 11 #Javascript
基于MVC5和Bootstrap的jQuery TreeView树形控件(二)之数据支持json字符串、list集合
Aug 11 #Javascript
基于MVC5和Bootstrap的jQuery TreeView树形控件(一)之数据支持json字符串、list集合
Aug 11 #Javascript
You might like
PHP flush()与ob_flush()的区别详解
2013/06/03 PHP
DWZ+ThinkPHP开发时遇到的问题分析
2016/12/12 PHP
laravel框架模型中非静态方法也能静态调用的原理分析
2019/11/23 PHP
深入理解PHP+Mysql分布式事务与解决方案
2020/12/03 PHP
XMLHTTPRequest的属性和方法简介
2010/11/23 Javascript
HTML DOM的nodeType值介绍
2011/03/31 Javascript
javascript白色简洁计算器
2015/05/04 Javascript
最全面的百度地图JavaScript离线版开发
2016/09/10 Javascript
Node.js的基本知识简单汇总
2016/09/19 Javascript
Vue 固定头 固定列 点击表头可排序的表格组件
2016/11/25 Javascript
数组Array的排序sort方法
2017/02/17 Javascript
js实现移动端导航点击自动滑动效果
2017/07/18 Javascript
BootStrap点击保存后实现模态框自动关闭的思路(模态框)
2017/09/26 Javascript
js构建二叉树进行数值数组的去重与优化详解
2018/03/26 Javascript
JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】
2020/02/24 Javascript
[48:48]VGJ.T vs Liquid 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
在IIS服务器上以CGI方式运行Python脚本的教程
2015/04/25 Python
Python检测字符串中是否包含某字符集合中的字符
2015/05/21 Python
Python yield 使用浅析
2015/05/28 Python
Python的Asyncore异步Socket模块及实现端口转发的例子
2016/06/14 Python
Python常用的内置序列结构(列表、元组、字典)学习笔记
2016/07/08 Python
关于Python元祖,列表,字典,集合的比较
2017/01/06 Python
Python解决八皇后问题示例
2018/04/22 Python
Python爬虫之正则表达式的使用教程详解
2018/10/25 Python
Flask模板引擎之Jinja2语法介绍
2019/06/26 Python
opencv resize图片为正方形尺寸的实现方法
2019/12/26 Python
美国家用电器和电子产品商店:Abt
2016/09/06 全球购物
纯净、自信、100%的羊绒服装:360Cashmere
2021/02/20 全球购物
化学相关工作求职信
2013/10/02 职场文书
高中的职业生涯规划书
2013/12/28 职场文书
搞笑创意广告语
2014/03/17 职场文书
常务副总经理任命书
2014/06/05 职场文书
亲子阅读的活动方案
2014/08/15 职场文书
农村党支部书记司法四风问题对照检查材料
2014/09/26 职场文书
2016会计专业自荐信范文
2016/01/28 职场文书
数据设计之权限的实现
2022/08/05 MySQL