jscanvas合成图片实现微信公众号海报功能

在微信公众号开发中,很多时候都有个需求是一张图加上头像和昵称或者其他数据生成自己的二维码海报或者是生成分享海报


这个需求,php的gd库是可以实现的,但是用服务器进行图片合成,会消耗服务器大量的资源


所以我们可以考虑用以下方式实现


一:js的canvas图片合成方法


 $(function () {
        draw(function () {//生成之后的回调
            $('#img')[0].innerHTML='<img src="'+base64[0]+'">';//将base生成图片
        });
    });
    var data=[图片1地址,图片2地址,图片3地址];
    base64=[];//用于保存生成之后的base64
    function draw(fn) {
        var img1= new Image;
        img1.src = data[0];
        img1.onload = function () {//这步必须,因为图片加载是异步的,必须等图片加载完成才开始下面的这些步骤
            var c = document.createElement('canvas'),
                    ctx = c.getContext('2d');
                        c.width = img1.naturalWidth;
                        c.height = img1.naturalHeight;
                        ctx.rect(0, 0, c.width, c.height);
                        ctx.fillStyle = '#fff';
                        ctx.fill();
            //生成一张图片1的底图
                        
            /*下面是为底图增加上文字*/
            ctx.drawImage(img1, 0, 0, c.width, c.height);(绘制图片资源,x坐标,y坐标,宽,高)
            //设置字体样式
            ctx.font = "24px Courier New";
            //设置字体填充颜色
            ctx.fillStyle = "write";
            //从坐标点(92,800)开始绘制文字
            ctx.fillText("这是文字内容", 92, 800);
            /*上面是增加文字,可以无限加*/
            
            
            var img2= new Image;
            img2.src = data[1];
            img2.onload = function () {//同理,如果是加载图片的话,需要等图片加载出来再下一步,所以要加onload
                ctx.drawImage(img2, 245, 660, 150, 150);(绘制图片资源,x坐标,y坐标,宽,高)
                    base64.push(c.toDataURL("image/jpeg", 1));//如果绘制完成了,就把base64数据填进数组,然后回调,没完成则继续这步
                fn();//回调
            };
        };
    }
 ///如果是坐标相同,或者觉得代码这样不美观的,可以使用递归方法实现onload的步骤,例如:

    function draw(fn) {
            
         a(0);
         
         fn();
    }
 
 function a(i){ 
       if (i == 0) {
         var img1= new Image;
        img1.src = data[0];
        img1.onload = function () {
            var c = document.createElement('canvas'),
            ctx = c.getContext('2d');
                        c.width = img1.naturalWidth;
                        c.height = img1.naturalHeight;
                        ctx.rect(0, 0, c.width, c.height);
                        ctx.fillStyle = '#fff';
                        ctx.fill();
            //生成一张图片1的底图
                        
            /*下面是为底图增加上文字*/
            ctx.drawImage(img1, 0, 0, c.width, c.height);(绘制图片资源,x坐标,y坐标,宽,高)
            //设置字体样式
            ctx.font = "24px Courier New";
            //设置字体填充颜色
            ctx.fillStyle = "write";
            //从坐标点(92,800)开始绘制文字
            ctx.fillText("这是文字内容", 92, 800);
            /*上面是增加文字,可以无限加*/
            a(1);//到第2个步骤
        }
        } else if (i == 1) {
           var img2= new Image;
            img2.src = data[1];
            img2.onload = function () {//同理,如果是加载图片的话,需要等图片加载出来再下一步,所以要加onload
                ctx.drawImage(img2, 245, 660, 150, 150);(绘制图片资源,x坐标,y坐标,宽,高)
                    base64.push(c.toDataURL("image/jpeg", 1));//如果绘制完成了,就把base64数据填进数组,然后回调,没完成则a(2)到第三步;
                return;
            };
        } 
   }

二:使用html2canvas进行网页保存成图片//需引入html2canvas.js

<div class="qrcodepic">
    <img src="图片1" class="qrbg">
    <img src="图片2" class="qrcode" />
    <span class="niname"><img src="图片3" class="touxiang" />文字</span>
    <div class="qrcodemain"></div>
</div>
//使用css进行网页布局
$(window).load(function(){
    var shareContent = $(".qrbg")[0]; 
    var width = shareContent.offsetWidth; 
    var height = shareContent.offsetHeight;
    $(".qrcodepic").height(height);
    var canvas = document.createElement("canvas"); 
    var scale = 2; 
    canvas.width = width * scale; 
    canvas.height = height * scale; 
    canvas.getContext("2d").scale(scale, scale); 
    var rect = shareContent.getBoundingClientRect();
    canvas.getContext("2d").translate(-rect.left,-rect.top);
    var opts = {
        scale: scale, 
        canvas: canvas, 
        width: width, 
        height: height,
        useCORS:true
    };
    html2canvas($(".qrcodepic"), opts).then(function (canvas) {
        dataURL =canvas.toDataURL("image/png");
        $(".qrcodemain").html("<img src='"+dataURL+"' style='display:block; width:100%;' />");
    });
});

最后给个效果图吧

方法1

仙士可博客仙士可博客

方法2

仙士可博客仙士可博客仙士可博客仙士可博客


仙士可博客
请先登录后发表评论
  • 最新评论
  • 总共2条评论
仙士可博客

 :弄了一晚上。ctx没定义???...

2018-11-11 00:14:38 回复

仙士可博客

.:canvas生成海报,存在跨域问题,怎么解决的?目前我是后端返回给base64,照片有点大,此方法不太好。但是,如果使用oss的链接地址,存在跨域问题。

2018-05-06 12:39:33 回复

仙士可博客
  • 仙士可 回复 .:使用第二种方法,html标签加载图片,理论上是不存在跨域的
  • 2018-05-06 13:15:24 回复
仙士可博客
  • 仙士可 回复 .:额,之前说的有误,html标签加载图片base64不会跨域,如果是直接链接还是会跨域的,跨域暂时没去研究如何解决,稍后回答你
  • 2018-05-06 13:26:40 回复
仙士可博客
  • 仙士可 回复 .:刚刚试了下,回答下你的问题一:如果只用前端js的话,无法解决跨域问题二:跨域是浏览器根据服务器标识产生的,所以只能从这2个方面去进行解决1:修改本地浏览器参数(仅仅是本地解决,其他用户没有解决)2:服务器响应头增加参数Access-Control-Allow-Origin可解决,至于oss,可设置跨域域名
  • 2018-05-06 13:51:27 回复
仙士可博客
  • 微风徐徐 回复 仙士可:最近我也遇到一个公从号生成图片海报的需求,还需要保存到本地。使用a标签来下载到本地,在浏览器上有效果,但在公众号里就不行 了,老铁,你有遇到过吗
  • 2018-08-06 10:33:42 回复
仙士可博客
  • 仙士可 回复 微风徐徐:a标签不是下载标签,公众号上可以img标签渲染图片,长按即可保存
  • 2018-08-07 16:04:18 回复
  • 本站由白俊遥博客程序搭建
    © 2017-1-17 php20.cn 版权所有 ICP证:闽ICP备17001387号
  • 联系邮箱:1067197739@qq.com