wechat save and share image
参考 一次 H5 「保存页面为图片」 的踩坑之旅 可以完成 90% 的工作量。项目主要用到的是 html2canvas。
Discover the different features supported by html2canvas
Unsupported CSS properties
These CSS properties are NOT currently supported
- background-blend-mode
- border-image
- box-decoration-break
- box-shadow
- filter
- font-variant-ligatures
- mix-blend-mode
- object-fit
- repeating-linear-gradient()
- writing-mode
- zoom
3.2.2 图片画出来怎么不见了
什么是“被污染”的 canvas?
尽管不通过 CORS 就可以在画布中使用图片,但是这会污染画布。一旦画布被污染,你就无法读取其数据。例如,你不能再使用画布的 toBlob(), toDataURL() 或 getImageData() 方法,调用它们会抛出安全错误。
方案一:将图片转换成 base64
前提条件:
- 给 img 元素设置 crossOrigin 属性,值为 anonymous
- 图片服务端设置允许跨域(返回 CORS 头)
function toDataURL(src, callback, outputFormat) {
var img = new Image()
img.crossOrigin = 'Anonymous'
img.onload = function () {
var canvas = document.createElement('CANVAS')
var ctx = canvas.getContext('2d')
var dataURL
canvas.height = this.naturalHeight
canvas.width = this.naturalWidth
ctx.drawImage(this, 0, 0)
dataURL = canvas.toDataURL(outputFormat)
callback(dataURL)
}
img.src = src
if (img.complete || img.complete === undefined) {
img.src =
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='
img.src = src
}
}
toDataURL(
'https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0',
function (dataUrl) {
console.log('RESULT:', dataUrl)
}
)
方案二:html2canvas
开启 useCORS
(Whether to attempt to load images from a server using CORS)
html2canvas(document.body, {
useCORS: true,
}).then(function (canvas) {
let img = new Image()
img.src = canvas.toDataURL()
document.body.appenChild(img)
})
canvas 绘制模糊
1.canvas 锯齿
CanvasRenderingContext2D.imageSmoothingEnabled 是 Canvas 2D API 用来设置图片是否平滑的属性,true 表示图片平滑(默认值),false 表示图片不平滑。当我们获取 imageSmoothingEnabled 属性值时, 它会返回最新设置的值。
以缩放画布为例,这个属性对像素为主的游戏很有用。默认的改变大小的算法会造成图片模糊并且破坏图片原有的像素。 如果那样的话,设置属性值为 false。
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
var img = new Image()
// ios 会报错: The operation is insecure.
img.crossOrigin = 'anonymous'
img.onload = function () {
ctx.mozImageSmoothingEnabled = false
ctx.webkitImageSmoothingEnabled = false
ctx.msImageSmoothingEnabled = false
ctx.imageSmoothingEnabled = false
// 浏览器为了达到抗锯齿的效果会做额外的运算。为了避免这种情况,请保证在你调用 drawImage() 函数时,
// 用 Math.floor() 函数对所有的坐标点取整。
ctx.drawImage(img, 0, 0, 400, 200)
}
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png'
2.解决 Retina 屏下的 图片模糊问题
function setupCanvas(canvas) {
// Get the device pixel ratio, falling back to 1.
var dpr = window.devicePixelRatio || 1
// Get the size of the canvas in CSS pixels.
var rect = canvas.getBoundingClientRect()
// Give the canvas pixel dimensions of their CSS
// size * the device pixel ratio.
canvas.width = rect.width * dpr
canvas.height = rect.height * dpr
var ctx = canvas.getContext('2d')
// Scale all drawing operations by the dpr, so you
// don't have to worry about the difference.
ctx.scale(dpr, dpr)
return ctx
}
// Now this line will be the same size on the page
// but will look sharper on high-DPI devices!
var ctx = setupCanvas(document.querySelector('.my-canvas'))
ctx.lineWidth = 5
ctx.beginPath()
ctx.moveTo(100, 100)
ctx.lineTo(200, 200)
ctx.stroke()
3.移动端 zoom 适配问题
项目中遇到了重构用了 zoom
来自适应,但是根据 Discover the different features supported by html2canvas 目前是不支持 zoom
属性的。可以使用 transform: scale(0.5, 0.5)
来替换 zoom