惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Register - Security
The Register - Security
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
LangChain Blog
N
Netflix TechBlog - Medium
量子位
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
H
Help Net Security
D
Docker
D
DataBreaches.Net
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
B
Blog
博客园 - 聂微东
Apple Machine Learning Research
Apple Machine Learning Research
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
F
Full Disclosure
GbyAI
GbyAI
F
Fortinet All Blogs
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
博客园 - Franky
MongoDB | Blog
MongoDB | Blog
有赞技术团队
有赞技术团队
博客园 - 叶小钗
小众软件
小众软件
V
Visual Studio Blog
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
The GitHub Blog
The GitHub Blog
Recorded Future
Recorded Future
J
Java Code Geeks
雷峰网
雷峰网
P
Privacy & Cybersecurity Law Blog
C
Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
AWS News Blog
AWS News Blog
Webroot Blog
Webroot Blog
美团技术团队
N
News | PayPal Newsroom
G
Google Developers Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园_首页
V
Vulnerabilities – Threatpost

博客园 - 【当耐特】

苹果 icloud 把我 ipad min 所有照片丢失 Wechart 饼图 - 【当耐特】 - 博客园 【开源】Skatch 正式发布 - 极速渲染抽象派草图 - 【当耐特】 【开源】小程序、小游戏和Web运动引擎 to2to 发布 - 【当耐特】 【开源】微信小程序、小游戏以及 Web 通用 Canvas 渲染引擎 - Cax - 【当耐特】 【开源】Qone 正式发布,使 javascript 支持 .NET LINQ - 【当耐特】 你不容错过的 腾讯 AlloyTeam Web 前端大会 看点完全剖析 50行代码实现的高性能动画定时器 raf-interval - 【当耐特】 - 博客园 QQ日迹Omi实战开发,从0到1 - 【当耐特】 - 博客园 腾讯AlloyTeam正式发布pasition - 制作酷炫Path过渡动画 - 【当耐特】 腾讯AlloyTeam正式发布omi-cli脚手架 - 创建网站无需任何配置 - 【当耐特】 Omi树组件omi-tree编写指南 - 【当耐特】 - 博客园 腾讯AlloyTeam正式发布Canvas魔幻线条 - curvejs - 【当耐特】 Omi官方插件系列 - omi-transform介绍 - 【当耐特】 Omi新成员omi-router正式发布 - 【当耐特】 - 博客园 Omi架构与React Fiber - 【当耐特】 - 博客园 Omi框架Store体系的前世今生 - 【当耐特】 - 博客园 omi-cli新版发布-升级webpack2和支持sass生成组件局部CSS - 【当耐特】 - 博客园 Omi应用md2site-0.5.0发布-支持动态markdown拉取解析 - 【当耐特】 - 博客园
腾讯 AlloyCrop 1.0 发布 - 【当耐特】
【当耐特】 · 2017-08-02 · via 博客园 - 【当耐特】

2017-08-02 11:10  【当耐特】  阅读(2920)  评论()    收藏  举报

写在前面

AlloyCrop 这个项目是8个月前发布的,作为AlloyFinger 的典型案例,发布之后被BAT等其他公司广泛使用。但是发布之后,有两个问题一直没有抽出时间去解决:

  • 裁剪图像的分辨率太小,是否可配?
  • pinch双指放大的时候,放大的中心不是双指中心,是否可以优化?

现在很高兴地告诉大家,AlloyCrop 已经完全搞定了上面两个问题,本文将解释新版本的变化和AlloyCrop背后的原理。当然AlloyFinger的原理这里就不再阐述,以前有分享过 超小Web手势库AlloyFinger原理

先看全新的API变化。

API

new AlloyCrop({
    image_src: "img src",
    circle: true, // optional parameters , the default value is false
    width: 200, // crop width
    height: 100, // crop height
    output: 2, // output resolution --> 400*200
    ok: function (base64, canvas) { },
    cancel: function () { },
    ok_text: "yes", // optional parameters , the default value is ok
    cancel_text: "no" // optional parameters , the default value is cancel
});
参数 是否必填 意义
image_src 必须 需要裁剪图片的src地址
circle 不必须,默认是false 代表选取的是否是圆形还是矩形,默认是矩形,注意:圆形选取裁剪出来的也是正方形图片
width 必须 选区的宽
height 必须 选区的高
output 必须 输出的倍率。比如如果output为2,选区的宽300,选区的高100,输出的图像的分辨率为 (2×300,2×100)
ok 必须 点击ok按钮的回调
cancel 必须 点击cancel按钮的回调
ok_text 不必须,默认是ok ok按钮的文本
cancel_text 不必须,默认是cancel cancel按钮的文本

与之前版本最主要的变化就是新增了 output 支持自定义倍率分辨率的图像输出。

output原理

crop: function () {
    this.calculateRect();
    this.ctx.drawImage(this.img, this.crop_rect[0], this.crop_rect[1], this.crop_rect[2], this.crop_rect[3], 0, 0, this.canvas.width, this.canvas.height);

},

其中 this.calculateRect() 是计算选取和图片重叠在一起的矩形区域,drawImage 是把裁剪的区域绘制到 canvas 上。注意 canvas 的宽高是多少?且看:

this.canvas.width = option.width * this.output;
this.canvas.height = option.height * this.output;

所以就达到了自定义倍率分辨率的目的。当然这里图片的失真又或者超分辨,都取决于 drawImage 插值过程。关于插值,以前特意对比过,使用三次卷积插值完爆了其他几个,但是三次卷积插值速度也是最慢,所以浏览器内核要权衡效率和插值结果去实现 drawImage。

img

calculateRect计算裁剪区域

因为我们需要把图片的某个区域绘制到整个canvas上。所以drawImage的后四个参数为(0, 0, this.canvas.width, this.canvas.height),然后我们需要去计算图片裁剪的区域。

pv

大概就分上面两种情况,一种是完全包含,一种部分相交。

因为图片会被放大或者缩小(scale),所以情况会变得稍微复杂一点点。求出相交的矩形区域后,要对图片scale进行校正,校正回到1的比例,才能用于drawImage。具体代码参见 https://github.com/AlloyTeam/AlloyCrop/blob/master/alloy-crop.js#L227-L255

pinch 缩放优化

使用AlloyCrop是可以放大或者缩小再进行裁剪,怎么基于 pinch 的两个手指的中间进行放大呢?所以的秘密都在这个multipointStart里。

  • multipointStart是AlloyFinger抛出的多手指开始碰到屏幕的回调函数,通过evt.touches拿到前两个手指的坐标去计算中心坐标
  • 重置 originX 和 originY 到两手指的中心
  • 再重置 translateX 和 translateY 去抹平 originX和originY变更带来的位移
 new AlloyFinger(this.croppingBox, {
	multipointStart: function (evt) {
	    //reset origin x and y
	    var centerX = (evt.touches[0].pageX + evt.touches[1].pageX) / 2;
	    var centerY = (evt.touches[0].pageY + evt.touches[1].pageY) / 2;
	    var cr = self.img.getBoundingClientRect();
	    var img_centerX = cr.left + cr.width / 2;
	    var img_centerY = cr.top + cr.height / 2;
	    var offX = centerX - img_centerX;
	    var offY = centerY - img_centerY;
	    var preOriginX = self.img.originX
	    var preOriginY = self.img.originY
	    self.img.originX = offX / self.img.scaleX;
	    self.img.originY = offY / self.img.scaleY;
	    //reset translateX and translateY
	    self.img.translateX += offX - preOriginX * self.img.scaleX;
	    self.img.translateY += offY - preOriginY * self.img.scaleX;
	    self.initScale = self.img.scaleX;
	},
	pinch: function (evt) {
	    self.img.scaleX = self.img.scaleY = self.initScale * evt.zoom;
	},
	pressMove: function (evt) {
	    self.img.translateX += evt.deltaX;
	    self.img.translateY += evt.deltaY;
	    evt.preventDefault();
	}
});
  • 注意,translateX, translateY, translateZ, scaleX, scaleY, scaleZ, rotateX, rotateY, rotateZ, skewX, skewY, originX, originY, originZ 都是 css3transform 类库 注入到DOM元素上的属性。

Preview

Preview

Demo

Dependencies

License

This content is released under the MIT License.