有了上一篇图片放大镜的铺垫,今天的这个例子是缩小镜,因为裁剪的原图往往很大,不能在工作区域看到全部图片,所以,要有缩小镜来显示,当前裁剪的区域是原图的哪个部分.按照惯例首先看下效果图:
功能一:载入默认图片
功能二:选择本地图片
功能三:拖拽(鼠标直接拖动工作区视窗)
功能四:放大,缩小(点击按钮放大/缩小0.5倍,鼠标滚轮图片缩放)
功能五:利用canvas绘图裁剪图片
以下是源码,分享下,防止忘记:
html
<div id="workplace"> <div id="workplacewrap"> <div id="operateplace"> <div class="showinfo"> <span class="mouseposition"> 坐标(px): x:<span class="mouseposition-x">0</span> y:<span class="mouseposition-y">0</span> </span> </div> <div id="sourceImage"> <img src="./images/show-window/timgjpg" alt="" draggable="false"> </div> <div id="clipregion"></div> <div class="operation"> <input id="fileselector" type="file" hidden style=""> <label class="btn" for="fileselector">选择文件</label> <span id="btn-ResizeUp" class="btn">放大</span> <span id="btn-ResizeDown" class="btn">缩小</span> <span id="btn-Clip" class="btn">裁剪</span> </div> </div> <div id="showwindow"> <div class="showinfo"> <span class="mouseposition"> 坐标(px): x: <span class="mouseposition-x">0</span> y:<span class="mouseposition-y">0</span> </span> </div> <div style="position: absolute;"> <div id="pologen"></div> </div> <div id="previewwindow"> <img src="" alt="" draggable="false"> </div> <div class="operation"> <span class="btn">保存</span> </div> </div> </div> </div>
css
* { font-size: 14px; letter-spacing: 1px; color: #000; -ms-text-justify: auto; text-justify: auto; font-size: 12px; } #workplace { width: 100%; height: auto; background: #f4f4f4; } #workplacewrap { margin: 0px auto; width: 1200px; display: flex; flex-direction: row; align-items: flex-start; justify-content: flex-start; border-right: 1px solid #f0f0f0; border-left: 1px solid #f0f0f0; background: #f4f4f4; font-family: "微软雅黑 Light"; padding: 5px; } #operateplace { padding: 4px; border: 1px solid #bababa; } #sourceImage { width: 500px; height: 300px; border: 1px solid #bababa; background: none; margin-bottom: -1px; overflow: hidden; } #sourceImage img { position: relative; top: 0; left: 0; } .btn { background: #aa0000; border: #F8F8F8; color: white; padding: 5px; } .btn:hover { cursor: pointer; background: #cc1234; } .operation { display: flex; flex-direction: row; align-items: center; justify-content: space-around; height: 50px; } .showinfo { margin-bottom: -1px; font-size: 12px; } #showwindow { justify-self: flex-end; align-items: flex-end; width: 500px; height: auto; border: #baabba 1px solid; margin-left: 5px; padding: 5px; overflow: hidden; position:relative; } #previewwindow { border: 1px solid #bababa; width: 500px; height: 300px; } #pologen { border:1px solid red; position:relative; display:none; }
javascript:
class ClipTools { constructor() { this.workview = $('#sourceImage'); this.showview = $('#previewwindow'); this.workviewimg=$('#sourceImage>img'); this.showviewimg = $('#previewwindow>img'); this.workvwidth = 0; this.workvheight = 0; this.showvwidth = $('#sourceImage').width(); this.showvheight = $('#sourceImage').height(); //右侧显示区图片缩放后的高度 this.showvimgheight=0; //右侧显示区图片缩放后的宽度 this.showvimgwidth=0; this.resizeRate = 0.5; this.isScrollMouseResize = false; this.isClip=false; this.isMouseDown=false; this.workpos_x = 0; this.workpos_y = 0; //图片顶点位置 this.sourceimg_l=0; this.sourceimg_t=0; this.lastMouse_x=0; this.lastMouse_y=0; this.sourceimg_w = 0; this.sourceimg_h = 0; this.enlargeratio = 1.0; //显示区图片和显示区域的比例 this.showToSourceWidthRatio=0.1; this.showToSouceHeightRatio=0.1; this.Init = this.Init.bind(this); this.ImgInputFileChanged = this.ImgInputFileChanged.bind(this); this.ResizeUp = this.ResizeUp.bind(this); this.ResizeDown = this.ResizeDown.bind(this); this.ShowWorkPos = this.ShowWorkPos.bind(this); this.DrawClipRegionTosShow=this.DrawClipRegionTosShow.bind(this); } ShowWorkPos(x, y) { $('.mouseposition-x').text(this.workpos_x); $('.mouseposition-y').text(this.workpos_y); //console.log(`asdfa:${this.workpos_x}`); this.DrawClipRegionTosShow(); } Init() { //如果工作区域有默认图片 this.sourceimg_h = this.workviewimg.height(); this.sourceimg_w = this.workviewimg.width(); this.workvwidth = this.sourceimg_w; this.workvheight = this.sourceimg_h; this.showToSouceHeightRatio=this.showvheight/this.sourceimg_h; this.showToSourceWidthRatio=this.showvwidth/this.sourceimg_w; //右侧展示区域,展示当前工作区处于图片的区域 //按照最小比例对图片进行缩放 if (this.showToSouceHeightRatio<this.showToSourceWidthRatio) { this.showvimgheight=this.showvheight; this.showvimgwidth=this.showToSouceHeightRatio*this.sourceimg_w; } else { this.showvimgheight=this.sourceimg_h*this.showToSourceWidthRatio; this.showvimgwidth=this.showvwidth; } this.showviewimg.attr('src',this.workviewimg.attr('src')).width(this.showvimgwidth).height(this.showvimgheight); $('#btn-Clip').click(()=>{ //if (!avatorImg.src) return; let _cropCanvas = document.createElement('canvas'); // 计算边长 //let _side = (showSide / avatorImg.offsetWidth) * primitiveLength.width; // 计算截取时从原图片的原始长度的坐标 // 因为图片有可能会被放大/缩小,这时候,初始化时记录下来的primitiveLength信息就有用处了 let _sy =-this.sourceimg_t/ (this.workvheight/this.sourceimg_h); let _sx=-this.sourceimg_l/(this.workvwidth/this.sourceimg_w); let _swidth=this.workview.width()/(this.workvwidth/this.sourceimg_w); let _sheight=this.workview.height()/(this.workvheight/this.sourceimg_h); let width=this.workview.width(); let height=this.workview.height(); //工作区域视窗就是图片的大小 _cropCanvas.width = width; _cropCanvas.height = height; // 绘制图片 _cropCanvas.getContext('2d').drawImage(this.workviewimg[0], _sx, _sy, _swidth, _sheight, 0, 0, width, height); // 保存图片信息 let _lastImageData = _cropCanvas.toDataURL('image/png'); // 将裁剪出来的信息展示 this.showviewimg.attr({"src": _lastImageData,"width":width+"px","height":height+"px"}); // imageShow.style.width = showSide + 'px'; // imageShow.style.height = showSide + 'px'; $('#pologen').css('display',"none"); alert("裁剪成功"); }); $('#fileselector').on("change", this.ImgInputFileChanged); $("#btn-ResizeUp").click(this.ResizeUp); $("#btn-ResizeDown").click(this.ResizeDown); //this.DrawClipRegionTosShow(); this.workviewimg.mousemove((e) => { if(this.isMouseDown) { if (this.workviewimg) var left_s= e.offsetX- this.lastMouse_x; var top_s=e.offsetY-this.lastMouse_y; this.sourceimg_l+=left_s; this.sourceimg_t+=top_s; this.workviewimg.css({"left":this.sourceimg_l+"px","top":this.sourceimg_t+"px"}); } this.workpos_x = e.offsetX+this.sourceimg_l; this.workpos_y = e.offsetY+this.sourceimg_t; this.ShowWorkPos(e.offsetX,e.offsetY); //this.DrawClipRegionTosShow(); return false; }); //工作区滚轮事件,调整图片缩放 this.workviewimg.on("mousewheel DOMMouseScroll",(e)=> { this.isScrollMouseResize=true; var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) || // chrome & ie (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1)); // firefox if(delta>0)//向上滚 { if(this.enlargeratio>=1) { return; } this.workvwidth += 1; this.workvheight +=this.sourceimg_h/this.sourceimg_w; } else if(delta<0) { this.workvwidth -= 1; this.workvheight -=this.sourceimg_h/this.sourceimg_w; } this.workviewimg.width(this.workvwidth); this.workviewimg.height(this.workvheight); //this.DrawClipRegionTosShow(); }); //工作区图片拖拽 this.workviewimg.mousedown((e)=>{ this.isMouseDown=true; if(!this.isClip) { this.workviewimg.css({"cursor":"move"}); } this.lastMouse_x=e.offsetX; this.lastMouse_y=e.offsetY; }); this.workviewimg.mouseleave((e)=>{ this.isMouseDown=false; if(!this.isClip) { this.workviewimg.css({"cursor":"default"}); } }); $('body').mouseup((e)=>{ this.isMouseDown=false; if(!this.isClip) { this.workviewimg.css({"cursor":"default"}); } }); } //在展示区域,标识出被截图的范围 DrawClipRegionTosShow() { //1.首先将工作区左上角的位置还原到原图的位置,因为有滚轮的放大和缩小,所以原本定义在放大或者缩小按钮上的缩放比例不能再使用,要重新计算 //不管是放大缩小按钮,还是滚轮缩放的比例在工作区都是一样的 let rate= this.workvheight/this.sourceimg_h; let sourceLeft=this.sourceimg_l/rate; let sourceTop=this.sourceimg_t/rate; //计算在右侧展示区,缩放后投影裁剪区域的位置 this.showToSouceHeightRatio=this.showvheight/this.workvheight; this.showToSourceWidthRatio=this.showvwidth/this.workvwidth; let showLeft=0; let showTop=0; let showWidth=0; let showHeight=0; if (this.showToSouceHeightRatio<this.showToSourceWidthRatio) { showWidth=this.workview.width()*this.showToSouceHeightRatio; showHeight=this.workview.height()*this.showToSouceHeightRatio; showLeft=-sourceLeft*this.showToSouceHeightRatio; showTop=-sourceTop*this.showToSouceHeightRatio; } else { showWidth=this.workview.width()*this.showToSourceWidthRatio; showHeight=this.workview.height()*this.showToSourceWidthRatio; showLeft=-sourceLeft*this.showToSourceWidthRatio; showTop=-sourceTop*this.showToSourceWidthRatio; } $('#pologen').css({"display":"block","top":showTop+"px","left":showLeft+"px","width":showWidth+"px","height":showHeight+"px"}); } ResizeDown(e) { this.sourceimg_t=0; this.sourceimg_l=0; this.workviewimg.css({"left":this.sourceimg_l+"px","top":this.sourceimg_t+"px"}); //鼠标滑轮调整过尺寸,则将图复原 if (this.isScrollMouseResize) { this.enlargeratio = 1.0; this.workvwidth=this.sourceimg_w; this.workvheight=this.sourceimg_h; this.workviewimg.width(this.sourceimg_w); this.workviewimg.height(this.sourceimg_h); } this.isScrollMouseResize = false; if (this.workvheight < this.showvheight && this.workvwidth < this.showvwidth) { return; } else { this.enlargeratio *= this.resizeRate; this.workvwidth = this.sourceimg_w * this.enlargeratio; this.workvheight = this.sourceimg_h * this.enlargeratio; this.workviewimg.width(this.workvwidth); this.workviewimg.height(this.workvheight); this.DrawClipRegionTosShow(); } } ResizeUp(e) { this.sourceimg_t=0; this.sourceimg_l=0; this.workviewimg.css({"left":this.sourceimg_l+"px","top":this.sourceimg_t+"px"}); //鼠标滑轮调整过尺寸,则将图复原 if (this.isScrollMouseResize) { this.enlargeratio = 1.0; this.workvwidth=this.sourceimg_w; this.workvheight=this.sourceimg_h; this.workviewimg.width(this.sourceimg_w); this.workviewimg.height(this.sourceimg_h); } this.isScrollMouseResize = false; if (this.enlargeratio >= 1) { return; } else { this.enlargeratio /= this.resizeRate; this.workvwidth = this.sourceimg_w * this.enlargeratio; this.workvheight = this.sourceimg_h * this.enlargeratio; this.workviewimg.width(this.workvwidth); this.workviewimg.height(this.workvheight); } this.DrawClipRegionTosShow(); } ImgInputFileChanged(e) { let file = e.target.files[0]; let reader = new FileReader(); reader.onload = (e) => { this.workviewimg.attr('src', e.target.result); } reader.readAsDataURL(file); this.sourceimg_h = this.workviewimg.height(); this.sourceimg_w = this.workviewimg.width(); this.showToSouceHeightRatio=this.showvheight/this.sourceimg_h; this.showToSourceWidthRatio=this.showvwidth/this.sourceimg_w; //右侧展示区域,展示当前工作区处于图片的区域 //按照短边的比例对图片进行缩放 if (this.showToSouceHeightRatio<this.showToSourceWidthRatio) { this.showvimgheight=this.showvheight; this.showvimgwidth=this.showToSouceHeightRatio*this.sourceimg_w; } else { this.showvimgheight=this.sourceimg_h*this.showToSourceWidthRatio; this.showvimgwidth=this.showvwidth; } this.showviewimg.attr('src',this.workviewimg.attr('src')).width(this.showvimgwidth).height(this.showvimgheight); this.DrawClipRegionTosShow(); } } $(function () { let clip = new ClipTools(); clip.Init(); })
有问题,希望指正,本人刚接触前端不久,谢谢!