阅读 132

canvas pc移动端下载,使用img,toBlob,toDataURL跨域,画布污染,高清图制作

我们需求是把当前url合成二维码与当前logo合成一张图片让用户下载,支持pc,移动端,下面是我们需要合成的图片

二维码

生成二维码,我们使用qrcode.react组件就好啦,这个直接照搬就好了

import QRCode from 'qrcode.react';
<QRCode    style={{ height: 70, width: 70, display: "none" }}    className="QR-code-Img"    value={window.localtion.href}   />
复制代码

然后我们直接画图就好啦,在图片中引用二维码就好了,比较简单,页面显示也是ok的

const img3 = document.createElement('img');const getQRdom = document.querySelector('.QR-code-Img');img3.src = getQRdom.toDataURL("image/png");ctx.drawImage(img3, 12.5, 212.5, 65, 65);
复制代码

下载的时候问题来啦

我们的下载也简单,直接转化为base64下载就好啦,代码是:

const ctx = document.getElementById('myCanvas');
const dom = document.createElement("a");
dom.href = ctx.toDataURL("image/png");
dom.download = new Date().getTime() + ".png";
dom.click();
复制代码

第三方图片跨域

发现我们在canvas绘制图片的时候调用img,这个在画布上正常显示没问题,但是在下载的时候会认为是调用第三方资源,就是跨域,所以我们需要在绘制的时候加一个"crossOrigin", 'Anonymous',源,如下:

const img3 = document.createElement('img');
img3.setAttribute("crossOrigin", 'Anonymous')img3.src = '*****.jpg';img3.onload = function () {   ctx.drawImage(img3, 12.5, 212.5, 65, 65);}
复制代码

然后pc端大功告成

移动端就比较坑了,应为他不支持base64,所以我们要想办法转化为成二进制文件,所以我们只能用toBlob转化,代码如下

const ctx = document.getElementById('myCanvas');
canvas.toBlob(blob => {let dom = document.createElement("a");  dom.href = URL.createObjectURL(blob);let filename = `${title}.jpg`;  dom.download = filename;  dom.filename = filename;  dom.click();},"image/jpeg",1 // [0,1] 表示图片质量);
复制代码

再加一段兼容性代码

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' }));      }    });}
复制代码

测试安卓机ok,然后iphone问题来了SecurityError The operation is insecure,这啥玩意问题?搜了下都是讲手机权限,跨域问题,我跨域不是解决了吗,what?

解决方式

鬼晓得咋解决,没办法,一段段删代码呗,然后手机测试。。。

当发现把二维码那张图片删除的时候,页面不报错了,可是我crossOrigin", 'Anonymous也设置了,发现我这里用了一层转化toDataURL("image/png"),qrcode.react生成的本身也是一个canvas,我将他转化为base64在另外一张画布上使用,按照逻辑没错,但是在下载的时候,该img链接读取的是base64,会认为画布已经被污染,所以认为该操作有风险,于是改成

const getQRdom = document.querySelector('.QR-code-Img');
ctx.drawImage(getQRdom, 12.5, 212.5, 65, 65);
复制代码

于是完美解决!!

高清图制作

我们画布可视尺寸固定,但是怎么在可视尺寸内画出高清图,

Canvas有两种width、height:
1、一种是width、height属性,一般称其为画布尺寸,即图形绘制的地方。
例:
<canvas id="canvas" width="300" height="300">
2、另一种是css样式里的width、height属性,可通过内联样式、内部样式表或外部样式表设置。一般称其为画板尺寸,用于渲染绘制完成的图形。默认值为空。
例:
<canvas id="canvas" style="width:300px; height:300px;">

我们可视尺寸就是画板尺寸,那么我们只需要设置画板尺寸,然后手动设置画布尺寸就ok了

var device=2
var canvas=document.getElementById('canvas');    
canvas.width=canvas. clientWidth*device;
canvas.height=canvas.clientHeight*device; 
//后续尺寸全部*device
复制代码
文章分类
前端
文章标签