图片裁剪

概述

在项目中,我们常常遇到图片裁剪的问题。不论是某个博文封面或者头像,都会用到裁剪。今天我们就来说说大致的思路。

图片准备

如果是写在项目中的裁剪,我们最好将它封成组件,这样在需要的地方方便调用。巧妇难为无米之炊,所以我们的第一步便是准备图片。

<input type="file" id="myfile" class="coverpic" accept="image/*" onchange="handleOnchange(this)"/>
<label for="myfile" class='btn'>Choose a file</label> 

ps: input标签上传文件的样式不是很好看,故 lable 标签,在这里的作用便是将input与其关联,将input标签display:none;之后,自定义上传button样式。

在input的onChange事件回调中获取图片。

将图片转换为url

function fileToUrl() {
   const imgFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i
   if (url && typeof url === 'string') {
     setSrc(url)
   } else if (file && URL.createObjectURL && imgFilter.test(file[0].type)) {
     setSrc(URL.createObjectURL(file[0]))
   } else if (file && imgFilter.test(file[0].type)) {
     const reader = new FileReader()
     file && reader.readAsDataURL(file[0])
     reader.onload = function(e: ProgressEvent) {
       setSrc(get(e, 'target.result', ''))
     }
   }
 }

图片转为url之后,变可以填入裁剪区域的img标签内。在这里有一个问题,就是假若裁剪区域为400*400,我们上传的照片大小不一,长宽比也不一致,那么填入img标签的宽高怎么设?

方案:比较长宽,哪个大,就把哪个缩小至400,另一个则根据大的缩小比例进行缩小。

裁剪框的移动及判断

在这里插入图片描述
在这里就拿左右移动作为例子,进行说明。

左右移动,即x轴上的移动,我们计算movx,即移动后e.clientX减去初始e.clientX再加上移动前裁剪框的左边距,也就是说,我们算的movx总是最新的左边距。同理,movy即是最新的上边距。

  • 如果movy小于0 ,并且movx小于0,那说明现在在左上角,边界情况,不能再移动,故此我们设置裁剪框移动参数如下
setCropper({ top: 0,left: 0,})
  • 边界情况2,movy小于0,并且movx>裁剪区域宽减去裁剪框的宽,这时说明,移动到最右
setCropper({ top: 0,left: 裁剪区域宽-裁剪框的宽-裁剪框的两个黑边})
  • movy小于0,在除去上面两种情况的前提下,movx算是在正常区域移动,故设置如下
setCropper({ top: 0,left: moveX})

之后再对movy不能再向下移动的情况下,对x进行讨论。以及movx两种边界情况,进行讨论。

裁剪框拉伸处理

同样,画个图,对各种边界情况进行处理,改变裁剪框的大小信息。

结合裁剪信息和 cavans 进行图片导出

  • canvas 宽高设置。
  • drawImage传参
    • imgge: 要处理的图片、视频
    • sx: 开始剪切的x坐标位置
    • sy: 开始剪切的y坐标位置
    • swidth: 被剪切的图像的宽度
    • sheight: 被剪切的图像的高度
    • x:在画布上放置图像的x坐标位置
    • y:在画布上放置的图像的y坐标位置
    • width: 要使用的图像的宽度
    • height: 要使用的图像的高度
function handleData() {
    const image = new Image()
    image.setAttribute('crossorigin', 'anonymous')
    image.src = src
    image.onload = function() {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      canvas.width = 122
      shape === 'rectangle' ? (canvas.height = 91.5) : (canvas.height = 122)
      ctx &&
        ctx.drawImage(
          image,
          (left * originalW) / tailorWidth,
          (top * originalH) / height,
          (size * originalW) / tailorWidth,
          (size * originalH) / height,
          0,
          0,
          122,
          122
        )
      setImgUrl(canvas.toDataURL('image/jpeg', 0.92))
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值