js 的canvas使用 -- canvas转图片、图片转canvas、base64图片下载到本地、复制剪贴板、生成二维码的canvas

将canvas 转图片 以及 将 图片转成 canvas的方法

1. 图片转到画布上

// Converts image to canvas; returns new canvas element
function convertImageToCanvas(image) {
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);

    return canvas;
}
// (image, 0, 0); 其中0,0表示canvas的坐标点

2. 画布转成图片

// Converts canvas to an image
function convertCanvasToImage(canvas) {
    var image = new Image();
    image.src = canvas.toDataURL("image/png");
    return image;
}
// "image/png"表示canvas转成的图片类型,默认是png,可以改成"image/jpeg"

3. base64图片下载到本地(android另说)

/**
 * 下载Base64到本地
 1. trident内核都不可以(IE,猎豹)
 2. chrome, opera 等使用blink内核 可以(但是chrome好像还是webkit内核)
 3. firefox(Gecko) 可以
 4. 三星可以(多余后缀)
 5. 小米自带的手机浏览器可以(但filename乱码)
 6. qq, uc(PC都可以)
 * */
function downloadFile(content, fileName) { //下载base64图片
    const base64ToBlob = function(code) {
        let parts = code.split(';base64,');
        let contentType = parts[0].split(':')[1];
        let raw = window.atob(parts[1]);
        let rawLength = raw.length;
        let uInt8Array = new Uint8Array(rawLength);
        for(let i = 0; i < rawLength; ++i) {
            uInt8Array[i] = raw.charCodeAt(i);
        }
        return new Blob([uInt8Array], {
            type: contentType
        });
    };
    let aLink = document.createElement('a');
    let blob = base64ToBlob(content); //new Blob([content]);
    let evt = document.createEvent("HTMLEvents");
    evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
    aLink.download = fileName;
    aLink.href = URL.createObjectURL(blob);
    // aLink.click();
    aLink.dispatchEvent(new MouseEvent("click", {bubbles: true, cancelable: true, view: window}));  //
}

4. 复制剪贴板

/**
 * 复制进剪贴板
 * @param str
 */
export function copyText(message) {
    // copy(str){
    //     let save = function (e){
    //         e.clipboardData.setData('text/plain',str);//clipboardData对象
    //         e.preventDefault();//阻止默认行为
    //     };
    //     document.addEventListener('copy',save);
    //     return document.execCommand("copy");//使文档处于可编辑状态,否则无效
    // }

    let input = document.createElement("textarea");
    input.value = message;
    document.body.appendChild(input);
    input.select();
    input.setSelectionRange(0, input.value.length);
    document.execCommand('Copy');
    document.body.removeChild(input);
    console.log("复制成功")     //"复制成功"
}

5. 生成二维码的canvas(使用jquery 和 jquery.qrcode.js )

// 生成二维码canvas - 使用jquery 和 jquery.qrcode.js 
function() {  
     var imgBuffer = $("<div></div>");
        imgBuffer.qrcode({
            render: 'canvas',
             0.24 * deviceWidth * ratio,
            height: 0.24 * deviceWidth * ratio,
            text: url,
            foreground: "#000000",
            correctLevel: 3,
            minVersion: 1,
            //src: require("../image/logo-qrcode.png"),
        });
        // var ctx = imgBuffer.children("canvas")[0].getContext("2d");
        // this.qrcodeImageObj = imgBuffer.children("canvas")[0];
        // this.qrcodeImageSrc = imgBuffer.children("canvas")[0].toDataURL();
        // this.qrCodeData = ctx.getImageData(0,0,imgBuffer.children("canvas")[0].width, imgBuffer.children("canvas")[0].height);
}
// 123

方法二: 使用 npm i qrcode

// 使用 npm i qrcode 的二维码生成功能   
function getQrcodeCanvas = { 
    const _this = this;
        await QRCode.toCanvas(url, {
             0.24 * deviceWidth * ratio,
            height: 0.24 * deviceWidth * ratio,
            text: url,
            foreground: "#000000",
            correctLevel: 3,
            minVersion: 1,
        }, function (err, canvas) {
            var ctx = canvas.getContext("2d");
            _this.qrcodeImageObj = canvas;
            _this.qrcodeImageSrc = canvas.toDataURL();
            _this.qrCodeData = ctx.getImageData(0,0, canvas.width, canvas.height);
        });
}

最后: 实例

  1 /**
  2  * 使用
  3  */
  4 const data = {
  5      document.body.clientWidth,
  6     height: document.body.clientHeight
  7 }
  8 new DrawInvitation(data, (src, canvas, imageObj, imageSrc) => {
  9     // success callback
 10     // 显示 canvas
 11     // 显示 image
 12     // 保存 image
 13 }, () => {
 14     // fail callback
 15 })
 16 
 17 
 18 
 19 
 20 /**
 21  * 画图
 22  */
 23 class DrawCanvas {
 24     constructor(data, successCallback, errorCallback) {
 25         this.url = "https://123.com";
 26 
 27         var deviceWidth = data.width ? data.width : window.screen.width;
 28         var deviceHeight = data.height ? data.height : window.screen.width * 16/9;
 29         var dpr = window.devicePixelRatio || 1;
 30         var canvas = $("<canvas id='qrcode-canvas'></canvas>");
 31         canvas.attr("width",deviceWidth);
 32         canvas.attr("height",deviceHeight);
 33         canvas.css("position", "absolute");
 34         canvas.css("left", "0");
 35         canvas.css("top", "0");
 36         canvas.css("z-index", "1");
 37         // canvas.css("display", "none");
 38         canvas.css("background-color", "#000000");
 39         var ctx = canvas[0].getContext("2d");
 40         var bspr = ctx.webkitBackingStorePixelRatio ||
 41             ctx.mozBackingStorePixelRatio ||
 42             ctx.msBackingStorePixelRatio ||
 43             ctx.oBackingStorePixelRatio ||
 44             ctx.BackingStorePixelRatio || 1;
 45         var ratio = dpr / bspr;
 46         canvas.css("width", canvas.attr("width"));
 47         canvas.css("height", canvas.attr("height"));
 48         canvas.attr("width", canvas.attr("width") * ratio);
 49         canvas.attr("height", canvas.attr("height") * ratio);
 50 
 51         this.qrCodeData = null;
 52         this.deviceWidth = deviceWidth;
 53         this.deviceHeight = deviceHeight;
 54         this.ctx = ctx;
 55         this.ratio = ratio;
 56         this.canvas = canvas;
 57         this.successCallback = successCallback;
 58         this.errorCallback = errorCallback;
 59     }
 60 
 61     /**
 62      * 生成二维码
 63      */
 64     async qrCodeCreater(){
 65         // 二维码的生成路径
 66         let {deviceWidth, ratio} = this;
 67         var imgBuffer = $("<div></div>");
 68         let url = this.url;
 69         // imgBuffer.qrcode({
 70         //     render: 'canvas',
 71         //      0.24 * deviceWidth * ratio,
 72         //     height: 0.24 * deviceWidth * ratio,
 73         //     text: url,
 74         //     foreground: "#000000",
 75         //     correctLevel: 3,
 76         //     minVersion: 1,
 77         //     //src: require("../image/logo-qrcode.png"),
 78         // });
 79         // var ctx = imgBuffer.children("canvas")[0].getContext("2d");
 80         // this.qrcodeImageObj = imgBuffer.children("canvas")[0];
 81         // this.qrcodeImageSrc = imgBuffer.children("canvas")[0].toDataURL();
 82         // this.qrCodeData = ctx.getImageData(0,0,imgBuffer.children("canvas")[0].width, imgBuffer.children("canvas")[0].height);
 83 
 84         const _this = this;
 85         await QRCode.toCanvas(url, {
 86              0.24 * deviceWidth * ratio,
 87             height: 0.24 * deviceWidth * ratio,
 88             text: url,
 89             foreground: "#000000",
 90             correctLevel: 3,
 91             minVersion: 1,
 92         }, function (err, canvas) {
 93             var ctx = canvas.getContext("2d");
 94             _this.qrcodeImageObj = canvas;
 95             _this.qrcodeImageSrc = canvas.toDataURL();
 96             _this.qrCodeData = ctx.getImageData(0,0, canvas.width, canvas.height);
 97         });
 98     };
 99 
100     /**
101      * 生成图片
102      */
103     draw() {
104         // 生成二维码的图片
105         this.qrCodeCreater();
106         const _this = this;
107         // var imgBuffer = $("<img></img>");
108         // imgBuffer.on("load", function() {})  //jquery的监听从1.8版本开始,不可使用load直接进行
109         var imgBuffer = new Image();
110         imgBuffer.crossOrigin = "Anonymous";
111         imgBuffer.src = "图片1.png";
112         imgBuffer.onload = function(){
113             var imgBuffer_2 = new Image();
114             imgBuffer_2.crossOrigin = "Anonymous";
115             imgBuffer_2.src = "图片2.png";
116             imgBuffer_2.onload = function(){
117                 var imgBuffer_3 = new Image();
118                 imgBuffer_3.crossOrigin = "Anonymous";
119                 imgBuffer_3.src = "图片3.png";
120                 imgBuffer_3.onload = function(){
121                     _this.drawCanvas(imgBuffer, imgBuffer_2, imgBuffer_3);
122                 };
123                 imgBuffer_3.onerror = function () {
124                     showErrorMessage(i18n.home.generate_card_fail, _this.errorCallback);    //'生成邀请函失败!'
125                 };
126             };
127             imgBuffer_2.onerror = function () {
128                 showErrorMessage(i18n.home.generate_card_fail, _this.errorCallback);    //'生成邀请函失败!'
129             }
130         };
131         imgBuffer.onerror = function () {
132             showErrorMessage(i18n.home.generate_card_fail, _this.errorCallback);    //'生成邀请函失败!'
133         }
134     }
135 
136     /**
137      * onload 图片后合成canvas
138      * @param imgBuffer
139      * @param imgBuffer_2
140      */
141     drawCanvas(imgBuffer, imgBuffer_2, imgBuffer_3) {
142         let {qrCodeData, ctx, canvas, deviceWidth, deviceHeight, ratio, successCallback} = this;
143         ctx.clearRect(0,0,canvas.attr("width"), canvas.attr("height"));
144         //背景颜色
145         ctx.fillStyle = "#ffffff";
146         ctx.fillRect(0, 0, canvas.attr("width"), canvas.attr("height"));
147         ctx.textAlign="center";
148         // ctx.drawImage(imgBuffer, 0, 0, canvas.attr("width"), canvas.attr("height"));
149 
150         let canvasWidth= canvas.attr("width"), canvasHeight = canvas.attr("height");
151         // 顶部橙色圆弧背景
152         ctx.beginPath();
153         // ctx.arc(300, -540, 750, 0, 2*Math.PI);
154         ctx.arc(canvasWidth/6*5, -canvasWidth/9*13.5, canvasWidth/12*25, 0, 2*Math.PI);
155         ctx.stroke();
156         ctx.fillStyle="#03bcd5";
157         ctx.fill();
158         // logo图片
159         ctx.drawImage(imgBuffer, canvasWidth * 0.2, canvasWidth * 0.14, canvasWidth*0.6, canvasWidth*0.6*0.31466);//0.31466470154753131908621960206338
160         // 底部图片
161         ctx.drawImage(imgBuffer_2, canvasWidth * 0.382/2, canvasHeight-canvasWidth * 0.618, canvasWidth * 0.618, canvasWidth * 0.618);
162         // 二维码背景
163         ctx.beginPath();
164         ctx.rect(canvasWidth*0.38-canvasWidth*0.01, canvasHeight*0.59-canvasWidth*0.008, qrCodeData.width+canvasWidth*0.02, qrCodeData.height+canvasWidth*0.02);
165         ctx.stroke();
166         ctx.fillStyle="#ffffff";
167         ctx.fill();
168         // 二维码
169         ctx.putImageData(qrCodeData, canvas.attr("width") * 0.38, canvas.attr("height") * 0.59);
170 
171         ctx.drawImage(imgBuffer_3,
172             canvas.attr("width") * 0.38 + this.qrcodeImageObj.width/2 - this.qrcodeImageObj.width/4.7/2,
173             canvas.attr("height") * 0.59 + this.qrcodeImageObj.height/2 - this.qrcodeImageObj.height/4.7/2,
174             this.qrcodeImageObj.width/4.7,
175             this.qrcodeImageObj.height/4.7);
176 
177         //文字颜色
178         ctx.fillStyle = "#000000";
179         var in_text3 = "123456789";
180         var in_text4 = "123456789";
181         var in_text5 = "123456789";
182         var in_text6 = "123456789";
183 
184         // 1
185         ctx.font= "900 " + deviceWidth * ratio / (getCurrentInputLength(in_text3) * 1 > 12 ? getCurrentInputLength(in_text3) * 1 : 12) +"px 微软雅黑";
186         ctx.fillText(in_text3, 0.5 * deviceWidth * ratio , 0.42 * deviceHeight * ratio);
187         // 2
188         this.fillTextAndAutoChangeLine(ctx, deviceWidth, ratio, deviceHeight, in_text4);
189         // 3
190         ctx.font= "bold " + deviceWidth * ratio / 22 + "px exo, JiaLiDaYuan, 微软雅黑";
191         ctx.fillText(in_text5, 0.5 * deviceWidth * ratio , 0.815 * deviceHeight * ratio);
192         ctx.fillText(in_text6, 0.5 * deviceWidth * ratio, 0.855 * deviceHeight * ratio);
193 
194         // $("#imgBox").children("img").attr("src", canvas[0].toDataURL());
195         successCallback(canvas[0].toDataURL(), canvas, this.qrcodeImageObj, this.qrcodeImageSrc);
196     }
197 
198 
199     /** 绘制文字时自动换行 */
200     fillTextAndAutoChangeLine(ctx, deviceWidth, ratio, deviceHeight, text) {
201         ctx.font= deviceWidth * ratio / 22 +"px 微软雅黑";
202         // 一个字符的宽度
203         const oneCharWidth = ctx.measureText("M").width;
204         // canvas的宽度, 这里特意少个字符
205         const canvasWidth = deviceWidth * ratio - 3 * oneCharWidth;
206         const len = text.length;
207         // 初始Y的距离
208         let initY = 0.45 * deviceHeight * ratio;
209         const lineHeight = 0.03 * deviceHeight * ratio;
210         // 预存字符串
211         let preWriteText = "";
212         let preWriteTextWidth = 0;
213         // 整个单词, 遇到不完整的就换行
214         let totalWord = "";
215         for (let i = 0; i < len; i ++) {
216             const char = text.charAt(i);
217             // 判断是否遇到空格
218             if (char === " ") {
219                 totalWord = "";
220             } else {
221                 totalWord += char;
222             }
223             // 计算字体的宽度
224             const charWidth = ctx.measureText(char).width;
225             preWriteTextWidth += charWidth;
226             // 如果大于cavas宽度并且不是最后一个字符并且是一个完整的单次, 则将这行写下来, 并换行
227             if (i != len - 1 && preWriteTextWidth >= canvasWidth) {
228                 // 通过下一个是不是空格判断是不是一个完整的单次
229                 if (char != " "&& preWriteText.indexOf(" ") !== -1) {
230                     // 不是完整的单次, 则退回到单次开头
231                     const wordFirstCharPos = preWriteText.length - totalWord.length + 1;
232                     preWriteText = preWriteText.substring(0, wordFirstCharPos);
233                     initY += lineHeight;
234                     ctx.fillText(preWriteText, 0.5 * deviceWidth * ratio , initY);
235                     i -= totalWord.length;
236                     // 单次的第一个字母
237                     const wordFirstChar = text.charAt(wordFirstCharPos);
238                     preWriteText = "";
239                     preWriteTextWidth = 0;
240                 }
241                 // 下一个不是空格, 并且这一行中没有空格, 则把这行写下来 ||
242                 else {
243                     initY += lineHeight;
244                     // 当前单次切掉, 确保不爆框
245                     preWriteText = preWriteText.substring(0, preWriteText.length);
246                     ctx.fillText(preWriteText, 0.5 * deviceWidth * ratio , initY);
247                     // 换行
248                     preWriteText = char;
249                     preWriteTextWidth = charWidth;
250                 }
251             } else {
252                 preWriteText += char;
253             }
254             // 直到最后一个字
255             if (i == len - 1) {
256                 initY += lineHeight;
257                 ctx.fillText(preWriteText, 0.5 * deviceWidth * ratio , initY);
258             }
259         }
260     }
261 }
View Code
原文地址:https://www.cnblogs.com/nangezi/p/13807307.html