有了上一篇图片放大镜的铺垫,今天的这个例子是缩小镜,因为裁剪的原图往往很大,不能在工作区域看到全部图片,所以,要有缩小镜来显示,当前裁剪的区域是原图的个部分.按照惯例首先看下效果图:

        功能一:载入默认图片

         功能二:选择本地图片

        功能三:拖拽(鼠标直接拖动工作区视窗)     

            功能四:放大,缩小(点击按钮放大/缩小0.5倍,鼠标滚轮图片缩放)

 

             功能五:利用canvas绘图裁剪图片

             以下是源码,分享下,防止忘记:

            html:

 1 <script src="./javascript/jquery.min.js"></script>
 2 <div id="workplace">
 3     <div id="workplacewrap">
 4         <div id="operateplace">
 5             <div class="showinfo">
 6             <span class="mouseposition">
 7                 坐标(px):
 8                 x:<span class="mouseposition-x">0</span>
 9                 y:<span class="mouseposition-y">0</span>
10             </span>
11             </div>
12             <div id="sourceImage">
13                 <img src="./images/show-window/1-1.jpg" alt="" draggable="false">
14             </div>
15             <div id="clipregion"></div>
16             <div class="operation">
17                 <input id="fileselector" type="file" hidden style="">
18                 <label class="btn" for="fileselector">选择文件</label>
19                 <span id="btn-ResizeUp" class="btn">放大</span>
20                 <span id="btn-ResizeDown" class="btn">缩小</span>
21                 <span id="btn-Clip" class="btn">裁剪</span>
22             </div>
23         </div>
24         <div id="showwindow">
25             <div class="showinfo">
26             <span class="mouseposition">
27                 缩放比例:
28                 <span class="enlargeratio"></span>%
29             </span>
30             </div>
31             <div style="position: absolute;">
32                 <div id="pologen"></div>
33             </div>
34             <div id="previewwindow">
35                 <img src="" alt="" draggable="false">
36             </div>
37             <div class="operation">
38                 <span class="btn">保存</span>
39             </div>
40 
41         </div>
42     </div>

          css:

  1       * {
  2             font-size: 14px;
  3             letter-spacing: 1px;
  4             color: #000;
  5             -ms-text-justify: auto;
  6             text-justify: auto;
  7             font-size: 12px;
  8         }
  9 
 10         #workplace {
 11             width: 100%;
 12             height: auto;
 13             background: #f4f4f4;
 14 
 15         }
 16 
 17         #workplacewrap {
 18             margin: 0px auto;
 19             width: 1200px;
 20             display: flex;
 21             flex-direction: row;
 22             align-items: flex-start;
 23             justify-content: flex-start;
 24             border-right: 1px solid #f0f0f0;
 25             border-left: 1px solid #f0f0f0;
 26             background: #f4f4f4;
 27             font-family: "微软雅黑 Light";
 28             padding: 5px;
 29         }
 30 
 31         #operateplace {
 32             padding: 4px;
 33             border: 1px solid #bababa;
 34 
 35         }
 36 
 37         #sourceImage {
 38             width: 500px;
 39             height: 300px;
 40             border: 1px solid #bababa;
 41             background: none;
 42             margin-bottom: -1px;
 43             overflow: hidden;
 44         }
 45 
 46         #sourceImage img {
 47             position: relative;
 48             top: 0;
 49             left: 0;
 50         }
 51 
 52         .btn {
 53             background: #aa0000;
 54             border: #F8F8F8;
 55             color: white;
 56             padding: 5px;
 57         }
 58 
 59         .btn:hover {
 60             cursor: pointer;
 61             background: #cc1234;
 62         }
 63 
 64         .operation {
 65             display: flex;
 66             flex-direction: row;
 67             align-items: center;
 68             justify-content: space-around;
 69             height: 50px;
 70         }
 71 
 72         .showinfo {
 73 
 74             margin-bottom: -1px;
 75             font-size: 12px;
 76         }
 77 
 78         #showwindow {
 79             justify-self: flex-end;
 80             align-items: flex-end;
 81             width: 500px;
 82             height: auto;
 83             border: #baabba 1px solid;
 84             margin-left: 5px;
 85             padding: 5px;
 86             overflow: hidden;
 87             position:relative;
 88         }
 89 
 90         #previewwindow {
 91             border: 1px solid #bababa;
 92             width: 500px;
 93             height: 300px;
 94         }
 95         #pologen
 96         {
 97             border:1px solid red;
 98             position:relative;
 99             display:none;
100         }

                javascript:

  1 //代码重新修订
  2 class ClipTools {
  3         constructor() {
  4             this.workview = $('#sourceImage');
  5             this.showview = $('#previewwindow');
  6 
  7             this.workviewimg=$('#sourceImage>img');
  8             this.showviewimg = $('#previewwindow>img');
  9             //工作区实际尺寸,由于图片有缩放,工作区尺寸实际是有workvimg尺寸决定的,而工作区视窗的是尺寸是固定的,本例中是500*300,这个尺寸默认就是最终截图的尺寸
 10             //后面扩展,可以对工作视图的尺寸进行调整,截出不同尺寸的图片
 11             this.workvwidth = 0;
 12             this.workvheight = 0;
 13             //同样展示框的尺寸,实际是右侧展示框图片缩放后的尺寸,本例中图片一定要全部放入展示视窗,所以,这个尺寸是小于等于展示视窗的尺寸的
 14             this.showvwidth = $('#sourceImage').width();
 15             this.showvheight = $('#sourceImage').height();
 16 
 17             //右侧显示区图片缩放后的高度
 18             this.showvimgheight=0;
 19             //右侧显示区图片缩放后的宽度
 20             this.showvimgwidth=0;
 21             this.resizeRate = 0.5;
 22             this.isScrollMouseResize = false;
 23             //后面扩展,比如绘制裁剪区域时用,本例中没有实际意义
 24             this.isClip=false;
 25 
 26             this.isMouseDown=false;
 27             //标识鼠标在工作区的坐标,offsetX 和offsetY(相对于视窗)
 28             this.workpos_x = 0;
 29             this.workpos_y = 0;
 30 
 31             //图片顶点位置
 32             this.sourceimg_l=0;
 33             this.sourceimg_t=0;
 34             //图片在计算拖动距离的时候,需要记录鼠标的起始位置,在鼠标的down->move中,起始位置以鼠标的down点为基准
 35             this.lastMouse_x=0;
 36             this.lastMouse_y=0;
 37             //记录图片的原始尺寸
 38             this.sourceimg_w = 0;
 39             this.sourceimg_h = 0;
 40             //记录图片缩放的比例
 41             this.enlargeratio = 1.0;
 42 
 43             //显示区图片和显示区域的比例
 44             this.showToSourceWidthRatio=0.1;
 45             this.showToSouceHeightRatio=0.1;
 46 
 47 
 48             this.Init = this.Init.bind(this);
 49             this.ImgInputFileChanged = this.ImgInputFileChanged.bind(this);
 50             this.ResizeUp = this.ResizeUp.bind(this);
 51             this.ResizeDown = this.ResizeDown.bind(this);
 52             this.ShowWorkPos = this.ShowWorkPos.bind(this);
 53             this.DrawClipRegionTosShow=this.DrawClipRegionTosShow.bind(this);
 54         }
 55         ShowWorkPos(x, y) {
 56             $('.mouseposition-x').text(this.workpos_x);
 57             $('.mouseposition-y').text(this.workpos_y);
 58             $(".enlargeratio").text(($("#pologen").height()/this.showvimgwidth)*100);
 59 
 60             this.DrawClipRegionTosShow();
 61         }
 62 
 63         Init() {
 64             //如果工作区域有默认图片
 65             this.sourceimg_h = this.workviewimg.height();
 66             this.sourceimg_w = this.workviewimg.width();
 67 
 68             this.workvwidth = this.sourceimg_w;
 69             this.workvheight = this.sourceimg_h;
 70 
 71             this.showToSouceHeightRatio=this.showvheight/this.sourceimg_h;
 72             this.showToSourceWidthRatio=this.showvwidth/this.sourceimg_w;
 73 
 74             //右侧展示区域,展示当前工作区处于图片的区域
 75             //按照最小比例对图片进行缩放
 76 
 77             if (this.showToSouceHeightRatio<this.showToSourceWidthRatio)
 78             {
 79                 this.showvimgheight=this.showvheight;
 80                 this.showvimgwidth=this.showToSouceHeightRatio*this.sourceimg_w;
 81             }
 82             else
 83             {
 84                 this.showvimgheight=this.sourceimg_h*this.showToSourceWidthRatio;
 85                 this.showvimgwidth=this.showvwidth;
 86             }
 87             this.showviewimg.attr('src',this.workviewimg.attr('src')).width(this.showvimgwidth).height(this.showvimgheight);
 88 
 89             $('#btn-Clip').click(()=>{
 90                 let _cropCanvas = document.createElement('canvas');
 91                 // 计算截取时从原图片的原始长度的坐标
 92                //图片有缩放等,所以要利用原始数据进行计算
 93                 let _sy =-this.sourceimg_t/ (this.workvheight/this.sourceimg_h);
 94                 let _sx=-this.sourceimg_l/(this.workvwidth/this.sourceimg_w);
 95                 let _swidth=this.workview.width()/(this.workvwidth/this.sourceimg_w);
 96                 let _sheight=this.workview.height()/(this.workvheight/this.sourceimg_h);
 97                 let width=this.workview.width();
 98                 let height=this.workview.height();
 99                 //工作区域视窗就是图片的大小
100                 _cropCanvas.width = width;
101                 _cropCanvas.height = height;
102                 // 绘制图片
103                 _cropCanvas.getContext('2d').drawImage(this.workviewimg[0], _sx, _sy, _swidth, _sheight, 0, 0, width, height);
104                 // 保存图片信息
105                 let _lastImageData = _cropCanvas.toDataURL('image/png');
106                 // 将裁剪出来的信息展示
107                 this.showviewimg.attr({"src": _lastImageData}).css({"width":width+"px","height":height+"px"});
108                 $('#pologen').css('display',"none");
109                 alert("裁剪成功");
110             });
111             $('#fileselector').on("change", this.ImgInputFileChanged);
112             $("#btn-ResizeUp").click(this.ResizeUp);
113             $("#btn-ResizeDown").click(this.ResizeDown);
114             //this.DrawClipRegionTosShow();
115             this.workviewimg.mousemove((e) => {
116 
117                 if(this.isMouseDown)
118                 {
119                     if (this.workviewimg)
120                     var left_s= e.offsetX- this.lastMouse_x;
121                     var top_s=e.offsetY-this.lastMouse_y;
122 
123                     this.sourceimg_l+=left_s;
124                     this.sourceimg_t+=top_s;
125                     this.workviewimg.css({"left":this.sourceimg_l+"px","top":this.sourceimg_t+"px"});
126                 }
127                 this.workpos_x = e.offsetX+this.sourceimg_l;
128                 this.workpos_y = e.offsetY+this.sourceimg_t;
129                 this.ShowWorkPos(e.offsetX,e.offsetY);
130                 return false;
131             });
132             //工作区滚轮事件,调整图片缩放,相当于是微调
133             this.workviewimg.on("mousewheel DOMMouseScroll",(e)=> {
134                 this.isScrollMouseResize=true;
135                 var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) ||  // chrome & ie
136                     (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1));              // firefox
137 
138                 if(delta>0)//向上滚
139                 {
140                     if(this.enlargeratio>=1)
141                     {
142                         return;
143                     }
144                     this.workvwidth += 1;
145                     this.workvheight +=this.sourceimg_h/this.sourceimg_w;
146                 }
147                 else if(delta<0)
148                 {
149                     this.workvwidth -= 1;
150                     this.workvheight -=this.sourceimg_h/this.sourceimg_w;
151                 }
152                 this.workviewimg.css({"width":this.workvwidth+"px","height":this.workvheight+"px"});
153                 this.workviewimg.height(this.workvheight);
154                 //this.DrawClipRegionTosShow();
155             });
156 
157             //工作区图片拖拽
158             this.workviewimg.mousedown((e)=>{
159                 this.isMouseDown=true;
160                  if(!this.isClip)
161                  {
162                      this.workviewimg.css({"cursor":"move"});
163                  }
164                  this.lastMouse_x=e.offsetX;
165                  this.lastMouse_y=e.offsetY;
166             });
167             //鼠标未松开,移出工作区
168             this.workviewimg.mouseleave((e)=>{
169                 this.isMouseDown=false;
170                 if(!this.isClip)
171                 {
172                     this.workviewimg.css({"cursor":"default"});
173                 }
174             });
175             //防止鼠标松开的事件,遗漏,所以拖拽的终事件,放在body中监听
176             $('body').mouseup((e)=>{
177                 this.isMouseDown=false;
178                 if(!this.isClip)
179                 {
180                     this.workviewimg.css({"cursor":"default"});
181                 }
182             });
183         }
184         //在展示区域,标识出被截图的范围
185         DrawClipRegionTosShow()
186         {
187             //1.首先将工作区左上角的位置还原到原图的位置,因为有滚轮的放大和缩小,所以原本定义在放大或者缩小按钮上的缩放比例不能再使用,要重新计算
188             //不管是放大缩小按钮,还是滚轮缩放的比例在工作区都是一样的
189                //计算在右侧展示区,缩放后投影裁剪区域的位置
190             this.showToSouceHeightRatio=this.showvheight/this.workvheight;
191             this.showToSourceWidthRatio=this.showvwidth/this.workvwidth;
192             let showLeft=0;
193             let showTop=0;
194             let showWidth=0;
195             let showHeight=0;
196             if (this.showToSouceHeightRatio<this.showToSourceWidthRatio)
197             {
198                 showWidth=this.workview.width()*this.showToSouceHeightRatio;
199                 showHeight=this.workview.height()*this.showToSouceHeightRatio;
200                 showLeft=-this.sourceimg_l*this.showToSouceHeightRatio;
201                 showTop=-this.sourceimg_t*this.showToSouceHeightRatio;
202             }
203             else
204             {
205                 showWidth=this.workview.width()*this.showToSourceWidthRatio;
206                 showHeight=this.workview.height()*this.showToSourceWidthRatio;
207                 showLeft=-this.sourceimg_l*this.showToSourceWidthRatio;
208                 showTop=-this.sourceimg_t*this.showToSourceWidthRatio;
209             }
210             $('#pologen').css({"display":"block","top":showTop+"px","left":showLeft+"px","width":showWidth+"px","height":showHeight+"px"});
211 
212         }
213         ResizeDown(e) {
214             this.sourceimg_t=0;
215             this.sourceimg_l=0;
216             this.workviewimg.css({"left":this.sourceimg_l+"px","top":this.sourceimg_t+"px"});
217             //鼠标滑轮调整过尺寸,则将图复原
218             if (this.isScrollMouseResize) {
219                 this.enlargeratio = 1.0;
220                 this.workvwidth=this.sourceimg_w;
221                 this.workvheight=this.sourceimg_h;
222                 this.workviewimg.css({"width":this.sourceimg_w+"px","height":this.sourceimg_h+"px"});
223             }
224             this.isScrollMouseResize = false;
225             //不允许对完全在工作区展示的图片,再缩小
226             if (this.workvheight < this.showvheight && this.workvwidth < this.showvwidth) {
227                 return;
228             }
229             else {
230                 this.enlargeratio *= this.resizeRate;
231                 this.workvwidth = this.sourceimg_w * this.enlargeratio;
232                 this.workvheight = this.sourceimg_h * this.enlargeratio;
233                 this.workviewimg.css({"width":this.workvwidth+"px","height":this.workvheight+"px"});
234                 this.DrawClipRegionTosShow();
235             }
236         }
237 
238         ResizeUp(e) {
239             this.sourceimg_t=0;
240             this.sourceimg_l=0;
241             this.workviewimg.css({"left":this.sourceimg_l+"px","top":this.sourceimg_t+"px"});
242             //鼠标滑轮调整过尺寸,则将图复原
243             if (this.isScrollMouseResize) {
244                 this.enlargeratio = 1.0;
245                 this.workvwidth=this.sourceimg_w;
246                 this.workvheight=this.sourceimg_h;
247                 this.workviewimg.css({"width":this.sourceimg_w+"px","height":this.sourceimg_h+"px"});
248 
249             }
250             this.isScrollMouseResize = false;
251             //不允许,对原样展示的图片再进行放大
252             if (this.enlargeratio >= 1) {
253                 return;
254             }
255             else {
256                 this.enlargeratio /= this.resizeRate;
257                 this.workvwidth = this.sourceimg_w * this.enlargeratio;
258                 this.workvheight = this.sourceimg_h * this.enlargeratio;
259                 this.workviewimg.css({"width":this.workvwidth+"px","height":this.workvheight+"px"});
260             }
261             this.DrawClipRegionTosShow();
262         }
263         ImgInputFileChanged(e) {
264             let file = e.target.files[0];
265             let reader = new FileReader();
266             reader.readAsDataURL(file);
267             //读取完成时
268             reader.onloadend = (e) => {
269                 this.workviewimg.attr('src', e.target.result);
270 
271                 this.sourceimg_h = this.workviewimg.height();
272                 this.sourceimg_w = this.workviewimg.width();
273 
274 
275                 this.showToSouceHeightRatio=this.showvheight/this.sourceimg_h;
276                 this.showToSourceWidthRatio=this.showvwidth/this.sourceimg_w;
277 
278                 //右侧展示区域,展示当前工作区处于图片的区域
279                 //按照短边的比例对图片进行缩放
280                 if (this.showToSouceHeightRatio<this.showToSourceWidthRatio)
281                 {
282                     this.showvimgheight=this.showvheight;
283                     this.showvimgwidth=this.showToSouceHeightRatio*this.sourceimg_w;
284                 }
285                 else
286                 {
287                     this.showvimgheight=this.sourceimg_h*this.showToSourceWidthRatio;
288                     this.showvimgwidth=this.showvwidth;
289                 }
290                 this.showviewimg.attr('src',this.workviewimg.attr('src')).css({"width":this.showvimgwidth+"px","height":this.showvimgheight+"px"});
291 
292                 this.DrawClipRegionTosShow();
293             }
294 
295 
296         }
297     }
298 
299     $(function () {
300         let clip = new ClipTools();
301         clip.Init();
302     })

          还有个文件保存的功能,由于裁剪之后,展示区域的图片路径是base64,所以可以直接发送给服务器,或者用于本地图直接展示

          有问题,希望指正,本人刚接触前端不久,谢谢!