zoukankan      html  css  js  c++  java
  • html+jquery实现简单图片裁剪

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

            功能一:载入默认图片

             功能二:选择本地图片

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

                功能四:放大,缩小(点击按钮放大/缩小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,所以可以直接发送给服务器,或者用于本地图直接展示

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

  • 相关阅读:
    到底什么是 ROI Pooling Layer ???
    Interacted Action-Driven Visual Tracking Algorithm
    论文笔记:Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments
    论文笔记: Dual Deep Network for Visual Tracking
    (zhuan) Attention in Neural Networks and How to Use It
    深度学习课程笔记(六)Error
    华尔街
    使用makefile
    财商入门 --- 富爸爸,穷爸爸
    分形之拆分三角形(Split Triangle)
  • 原文地址:https://www.cnblogs.com/andayhou/p/9380404.html
Copyright © 2011-2022 走看看