需求
每次上传图片至oss之前给图片添加logo.png水印
开发
1.获取到文件流之后,渲染到img标签
const blobToImg = function(filePath) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.addEventListener('load', () => {
const img = new Image()
img.src = reader.result
img.addEventListener('load', () => resolve(img))
})
reader.readAsDataURL(filePath)
})
}
2.将img标签内容绘制到canvas画布
const imgToCanvas = function(img) {
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
return canvas
}
3.canvas画布上绘制水印并转换为Blob对象
const watermark = function(canvas) {
return new Promise((resolve, reject) => {
const ctx = canvas.getContext('2d')
var eleImgCover = document.getElementById('imgCover') //水印
for (let i = 0; i < 20; i++) {
for (let j = 0; j < 20; j++) {
ctx.rotate((-45 * Math.PI) / 180) // 水印初始偏转角度
ctx.drawImage(eleImgCover, -canvas.width * 2 + i * 300, j * 250, eleImgCover.width, eleImgCover.height)
ctx.rotate((45 * Math.PI) / 180) // 把水印偏转角度调整为原来的,不然他会一直转
}
}
canvas.toBlob(blob => resolve(blob))
})
}
4.将生成的blob文件传至oss
测试
Edge报错
Unhandled promise rejection TypeMismatchError
解决
1.一开始以为是toBlob()方法兼容问题,在MDN上看到不支持Edge和IE<10,所以按照官方给出的polyfill方法,在调用toBlob()前加入
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
len = binStr.length,
arr = new Uint8Array(len);
for (var i=0; i<len; i++ ) {
arr[i] = binStr.charCodeAt(i);
}
callback( new Blob( [arr], {type: type || 'image/png'} ) );
}
});
}
未果
2.因为报的是DOMException对象所以定位不到错误,只能在上面三个方法打断点,发现流文件渲染img标签时没有获取到流,log看了一下获取到的文件流,发现file:'不支持file文件类型',果断使用dataURL渲染img即可