照片合成webapp项目总结

最近做了一个小项目, 在微信里面根据用户选择的模板、用户微信头像、昵称、用户选择上传的照片合成一个图片,用户可以保存到手机上,然后发朋友圈。

说复杂其实不复杂, 总结一下其中踩过的坑。

用Canvas合成照片

最开始是打算自己写Canvas,绘制照片、文字等, 最后调用canvas的toDataURI()方法合成照片的。但是canvas上又不方便响应用户点击等操作,还得用dom写一遍, 感觉就有点重复了。 后来想起以前用过的html2canvas库,果断用之,很方便。顺便还搜到几个其他的库,不过暂时没用过,先mark一下:

这里有几篇blog介绍使用的,可以看看,当然官网文档永远是最权威的,适当的时候还需要看下源码。

Retina屏幕下canvas模糊

马上问题来了, retina屏幕下(mac pro、iphone6+)保存出来的图片是模糊的。这个主要是canvas宽高的单位跟css单位不一致,retina屏幕下用了4倍像素渲染造成的。需要了解CSS像素、物理像素、逻辑像素、PPI、devicePixelRatio等概念,可以参考下面几篇。

弧形文字

设计稿有一个模板里面文字是弧形的,用svg实现了:

结果发现html2canvas没法保存svg。google之后发现html2canvas支持svg有问题:

我用inline svg也是没法绘制出来的, 开启了foreignObject选项,结果svg文字是可以保存了, 但是很多我不想要的内容也出来了。 foreignObject这个不是很了解,以后再看吧。

搜了一下,发现一些把svg转成canvas的库, 大概看了一下觉得没必要引入,还不如直接自己canvas画好了。这些库mark一下:

没有解决,后来还是考虑自己用canvas画算了,参考下文:

canvas裁剪圆

canvas透明背景

iPhone上竖屏拍摄图片旋转bug

iphone和部分三星手机上竖屏拍摄图片会旋转, 需要用读取Orientation,来自己纠正。

轮播图

轮播图太通用不过了,网上也有很多代码或者插件(很多jQuery的插件)实现。推荐两个:

图片裁剪

html5里面有FileReader特性, 可以在前端读取修改文件内容,再结合canvas,很容易就实现前端裁剪图片了。

读取图片每个像素点的RGB

滑动到屏幕底部

需要了解viewport、clientHeight、offsetHeight、scrollHeight、scrollTop等概念。

ReactRouter v4在非组件页面使用history

React高阶组件

最后用React高阶组件把各个模板重构了一下。 https://reactjs.org/docs/higher-order-components.html

Concretely, a higher-order component is a function that takes a component and returns a new component.

注意,高阶组件是一个function,而不是component, 所以你只能hoc(config)(ComponentA)这样调用, 而不能<Hoc config={config} component={ComponentA} />这样调用, 因为调用过一次之后,返回的已经是React.Elements了。具体可以看https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html

高阶组件概念来自于函数式编程里面的高阶函数,如果不熟悉函数式编程, 可以看看下面的资料:

React 16

在开发的过程中发现如下代码:

f() {
  this.setState({...})
};
this.a += 1;
...
render() {
  ...
}

居然render()this.a += 1之前执行?!!!跟setState函数是异步调用的说法不一致啊, 不知道是不是React16Fiber带来的特性, 抽空得好好研究下React16了。