SimpleCrop 媲美原生体验的Web图片裁剪组件

SimpleCropgithub.com/newbieYoung… 是一个在功能交互上复刻移动设备原生图片裁剪功能的 Web 图片裁剪组件;css

左侧是 IOS 系统相册中原生的图片裁剪功能,右侧为 SimpleCrop 移动端示例。html

能够扫描二维码体验:git

或者访问如下连接:github

newbieyoung.github.io/Simple-Crop…web

之因此会作这个项目主要是由于已知的图片裁剪组件并不能彻底知足本身的要求,好比:canvas

只支持旋转固定角度。浏览器

彻底不支持旋转。bash

所以和目前流行的 Web 图片裁剪组件相比,其优点在于如下几点:spa

  • 裁剪图片支持任意角度旋转;
  • 移动端缩放以双指中心为基准点;
  • 支持边界判断、当裁剪框里出现空白时,图片自动吸附至彻底填满裁剪框;
  • 操做体验媲美原生客户端。

安装使用教程能够点击连接 github.com/newbieYoung… 查看。3d

关键实现

要实现任意角度旋转双指中心缩放边界判断自动吸附等功能,关键点以下:

1. 判断点和矩形的位置关系

a1 + a2 + a3 + a4 < 360
b1 + b2 + b3 + b4 = 360
复制代码

判断点是否在矩形外能够经过链接矩形四个顶点和判断点,而后计算四条连线之间的夹角,若是夹角之和小于 360 度,那么该判断点在矩形外;反之若是夹角之和等于 360 度,那么该判断点在矩形内。

2. 计算矩形以中心缩放恰好包含矩形外一点的放大倍数

当旋转裁剪图片时须要进行适当的放大才能保证裁剪框不超出,这里就须要计算这个放大倍数。

先让裁剪图片不进行放大旋转,而后判断裁剪框四个顶点有哪些超出了裁剪图片,接着根据超出的顶点计算放大倍数,以下:

须要的注意的是上述方法也能够用来判断点是否在矩形外,并且这种方法比计算夹角和的方法计算量要少。

另外旋转图片除了要进行适当放大,防止裁剪框不超出;在裁剪图片中心点没有变更时还能够进行适当缩小,去掉多余空隙;

适当缩小和适当放大的计算方式相似,辅助图以下:

3. 双指缩放以双指中心为基准点

SimpleCrop 中有大量的位移变换计算,出于方便的考虑我在开发时都默认变换基准点为图片中心点,也就是说transform-origin:50% 50%;可是这样会对双指缩放以双指中心为基准点的实现带来必定的困扰;

就缩放变换而言,相同倍数不一样基准点的区别仅仅在于变换后的位置不同了;所以解决方案也很简单,求出位移差而后进行缩放变换以后再进行位移变换便可。

4. 计算一个矩形恰好包含另一个矩形须要进行的缩放和位移变换

在旋转裁剪图片时咱们能够对其进行适当的放大从而保证裁剪框不会超出裁剪图片;可是在缩小裁剪图片却不能这么作,而应该采用移动裁剪图片的方式保证裁剪框不超出裁剪图片。

移动距离的计算能够先得到点到矩形中心的向量,而后计算该向量在矩形边框上的投影向量,最后能够用投影向量的长度减去边框长度的一半获得。

有些状况只使用位移变换并不能解决问题,以下:

此时先要把裁剪图片放大至能彻底包含裁剪框,而后再进行位移变换。

5. 裁剪图片

获取最终的裁剪图片须要用到 Canvas 的 drawImage 方法,可是其参数支持有限;

void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
复制代码

所以裁剪图片时须要先把图中xy坐标系转换为x1y1坐标系,得到 top、left、width、height 参数后,再执行 drawImage 方法;

这里须要注意两个问题:

  • 其一是当咱们把坐标系转换为 x1y1 时,为了彻底把裁剪图片绘制进去,每每会把容器 Canvas 的宽度和高度设置成超过裁剪图片;可是 Canvas 的尺寸在浏览器中是有最大限制的,超出后浏览器会报警告canvas area exceeds the maximum limit并且绘制的结果为空白;要解决这个问题就要求咱们适当控制容器 Canvas 的宽度和高度,只要保证能彻底包含裁剪框便可;在 SimppleCrop 中会默认等于裁剪图片的宽度和高度;

  • 其二则是裁剪图片方向角的问题,在 IOS 中使用系统相机竖着拍照时获得的照片的方向角元数据是横着的,在网页中使用 img 标签显示不会有问题,可是当使用 Canvas 绘制时若是不处理一下就不能正常绘制;可使用 Exif.js github.com/exif-js/exi… 获取图片元数据,而后借鉴 JavaScript-Load-Image github.com/blueimp/Jav… 中的处理方法便可。

总结

最后上述全部内容都基于须要实时获取裁剪图片进行 CSS3 Transform 变换后的新坐标,有兴趣能够查看CSS3 2D Transform Matrix

相关文章
相关标签/搜索