zoukankan      html  css  js  c++  java
  • Canvas -- 应用Konva绘制canvas保存成图片,显示在页面中

    需求:移动端,做如下图片的一个海报,可以长按保存,其中标题文字,说明文字,logo图片,二维码(动态生成二维码)图片,都是可变元素,其余部分是一张图片!

    我的canvas学习笔记gitlab

    如果前端来做,首先,我想到的就是利用canvas绘制出来,然后,转换成img,放在页面中,这样用户就可以通过长按保存功能,保存图片了!

    思路步骤以及遇到的坑

    1. 使用Konva库绘制canvas,绘制文字(可以绘制在同一个组上);
    2. 先生成二维码图片,再将二维码图片绘制到层上;
    3. 绘制logo图片和背景图片;
    4. canvas正确设置宽高属性单位必须是px、百分比适配;

    HTML

    <div id="wrapper"><div id="container"></div></div>
    

    文字绘制方法封装

    // @param: data 数组(因为可能有多个文字)
    function TextTitle(data){
        this._init(data);
    }
    TextTitle.prototype = {
        _init: function(data){
            this.data = data;
            // 新建文字组
            this.textGroup = new Konva.Group({
                x: 0,y: 0
            })
            var self = this;
            this.data.forEach(function(item,index){
                var x = item.x === 0 ? 0 : (item.x || 1);
                var y = item.y === 0 ? 0 : (item.y || 1);
                var txt = new Konva.Text({
                    x: x,y: y,
                    text: item.text,
                     item.width,
                    height: item.height,
                    fontSize: item.fontSize || 16,
                    fontStyle: item.fontStyle || 'normal',
                    fontFamily: item.fontFamily || 'Arial',
                    align: item.align || 'left',
                    fill: item.fill || '#000',
                });
                self.textGroup.add(txt);
            })
        },
        addToGroupOrLayer: function(arg){
            arg.add(this.textGroup);
        }
    }
    

    整个图片绘制

    // 创建舞台
    var stage = new Konva.Stage({
        container: 'container', // 需要存放舞台的dom容器
         621/2, // 设置全屏
        height: 974/2
    });
    // 创建层
    var layer = new Konva.Layer(); // 创建一个层
    // stage.add(layer); // 把层添加到舞台(这里写在了最后)
    
    // 中心点坐标
    // var cenX = stage.width()/2; // 注意Konva获取数据都是用方法获取值
    // var cenY = stage.height()/2;
    
    // 创建一个组存放文字
    var group = new Konva.Group({
        x: 0,y: 0
    })
    // 绘制文字数据
    var dataObj = [
        { // 创建标题的文字
            x: 0,
            y: 30,
             stage.width(),
            align: 'center',
            text: "活动名称",
            fontSize: 26,
            fontStyle: 'bold',
            fill: 'white'
        },
        { // 创建活动说明文字
            x: 0,
            y: 66,
             stage.width(),
            align: 'center',
            text: '最终解释权归门店所有',
            fontSize: 16,
            fill: 'white' 
        }
    ];
    var text = new TextTitle(dataObj);
    // 绘制二维码
    // 创建二维码图片,先转成img,再绘制到canvas中,然后将img移除
    var divEle = document.createElement("div"); 
    var divattr = document.createAttribute("id");  
    divattr.value = "temp"; 
    divEle.setAttributeNode(divattr);  
    document.getElementById("wrapper").appendChild(divEle);  
    new QRCode(document.getElementById("temp"), {
        text: window.location.href, // 首页链接
         72, //生成的二维码的宽度
        height: 72, //生成的二维码的高度
        colorDark : "#000000", // 生成的二维码的深色部分
        colorLight : "#ffffff", //生成二维码的浅色部分
        correctLevel : QRCode.CorrectLevel.H
    });
    var qrcodeImg = $('#temp img')[0];
    // 绘制logo,背景的图片
    var imgBig = new Image();
    imgBig.src = "base64图片";
    // 将绘制方法都写在图片onload内部
    imgBig.onload = function(){
        var kImage = new Konva.Image({
            image: imgBig,
            x: 0,
            y: 0,
             stage.width(),
            height: stage.height()
        });
        group.add(kImage);
        // 添加二维码图片
        var qrCodeImage = new Konva.Image({
            image: qrcodeImg,
            x: 204,
            y: 366,
             72,
            height: 72
        });
        group.add(qrCodeImage);
        layer.add(group);
        text.addToGroupOrLayer(layer);
        layer.draw();
        stage.add(layer); // 把层添加到舞台
        // 绘制完二维码后将标签删除
        var temp = document.getElementById("temp");  
        document.getElementById('wrapper').removeChild(temp);
    
        // 使用canvas.toDataURL()方法,将canvas生成base64
        var dataURL = stage.toDataURL();
        var actulImg = new Image();
        actulImg.src = dataURL;
        actulImg.onload = function(){ // 生成后删除canvas
            var konvajs = document.getElementsByClassName('konvajs-content')[0];
            document.getElementById('container').removeChild(konvajs); 
            document.getElementById('container').appendChild(actulImg);
        }
    }
    

    使用的是canvas.toDataURL()方法,出现跨域问题

    报错信息:

    Konva error: Unable to get data URL. Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
    

    翻译:Konva错误:无法获取数据URL。未能对“htmlcanvaseelement”执行“toDataURL”:无法导出受污染的画布

    整个报错信息的原因就是,使用canvas.toDataURL()方法,出现跨域问题了。

    因为很多情况下都会使用CDN存储的图片,在这里使用本地图片还是不现实,所以,需要解决这个问题。

    解决办法尝试:

    1. img设置img.crossOrigin = "anonymous"是没用的;
    2. URL.createObjectURL和URL.revokeObjectURL也是转换图片格式的方式,自测没写通;
    3. 将图片转换成base64使用(这里需要借助后端配合了),如果使用这种办法,出现某个图片或者二维码图片未显示出来,可能是绘制顺序出错。

    使用base64图片方式,在PC模拟器上效果显示是符合的,那么我们用微信浏览器试试吧!

    问题又出现了:

    1. 生成的canvas不虚,img图片太虚虚虚虚虚虚虚......导致根本没办法使用;
    2. 生成的二维码不见了,safari浏览器可以显示出二维码,偶发性如果第一次进入,点击显示的按钮,safair整张图片都不显示了,应该是未生成就显示了;

    后续再开发再更新!!!

    使用html2canvas.js实现页面截图(生成海报效果)

    生成海报功能最终使用的是html2canvas.js库实现的,不过过程中也有些兼容性问题需要解决,下面是生成海报方法:

    createIMG () { //一键生成图片
       window.scrollTo(0, 0); // 解决部分手机生成图片大片白边
       var _this = this;
       // 海报布局,将布局好的结构进行canvas转换,再将canvas转换成图片
       var targetDom = document.getElementById("pic_wrapper_page");
       html2canvas( targetDom, 
         {
          useCORS: true,   
          height: targetDom.offsetHeight-2,// 解决部分手机生成图片部分白边
           targetDom.offsetWidth-2,
         }).then(function(canvas) {
            var image = canvas.toDataURL("image/png");  
            _this.pic_src = image  // 最终生成的图片
        });                    
    }
    
  • 相关阅读:
    WCF 第八章 安全 确定替代身份(中)使用AzMan认证
    WCF 第八章 安全 总结
    WCF 第八章 安全 因特网上的安全服务(下) 其他认证模式
    WCF Membership Provider
    WCF 第八章 安全 确定替代身份(下)模仿用户
    WCF 第八章 安全 因特网上的安全服务(上)
    WCF 第九章 诊断
    HTTPS的七个误解(转载)
    WCF 第八章 安全 日志和审计
    基于比较的排序算法集
  • 原文地址:https://www.cnblogs.com/lisaShare/p/12682358.html
Copyright © 2011-2022 走看看