使用PHP+微信公众号+canvas生成海报

浏览866

效果展示:

image.png

每到节假日可以看到有很多获取个人信息,然后生成指定的海报,那些这些是如何做的呢?

首先我们需要一个企业服务号,配置相关服务器,域名等信息,接下来就是代码的编写和开发了,以下是博主的一种写法,供大家参考。

1、在csn目录下新建index.php文件,用于授权跳转

<?php
$appid='wx53a5d0130a982gf1';
$redirect_uri = urlencode ( 'http://h5.example.com/csn/getUserInfo.php' );
$url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
header("Location:".$url);

?>

2、在csn目录下新建getUserInfo.php文件,用于获取用户信息

<?php
$appid = "wx53a5d0130a982gf1";
$secret = "75cc1d6c1b577e7fef34249f994h5jg6";
if (!isset($_GET['code'])){
echo '授权失败!';
}else{
$code = $_GET['code'];
//获取token
$url1='https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$appid.'&secret='.$secret.'&code='.$code.'&grant_type=authorization_code';
$result= getJson($url1);
$access_token=$result['access_token'];
$openid=$result['openid'];
if (!$openid) {
$redirect_uri = urlencode ( 'http://h5.example.com/csn/getUserInfo.php' );
$url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
header("Location:".$url);
}
//获取用户信息
$url2='https://api.weixin.qq.com/sns/userinfo?access_token='.$access_token.'&openid='.$openid.'&lang=zh_CN';
$userinfo= getJson($url2);
}
//get请求方法
function getJson($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
return json_decode($output, true);
}
// 步骤2.生成签名的随机串
    function nonceStr($length){
        $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJK1NGJBQRSTUVWXYZ';//随即串,62个字符
        $strlen = 62;
        while($length > $strlen){
            $str .= $str;
            $strlen += 62;
        }
        $str = str_shuffle($str);
        return substr($str,0,$length);
    }
    // 步骤3.获取access_token
    $result = http_get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$secret);
    $json = json_decode($result,true);
    $access_token = $json['access_token'];
    function http_get($url){
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if(intval($aStatus["http_code"])==200){
            return $sContent;
        }else{
            return false;
        }
    }
    // 步骤4.获取ticket
    $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$access_token";
    $res = json_decode ( http_get ( $url ) );
    $ticket = $res->ticket;
    // 步骤5.生成wx.config需要的参数
    $surl = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    $ws = getWxConfig( $ticket,$surl,time(),nonceStr(16) );
    function getWxConfig($jsapiTicket,$url,$timestamp,$nonceStr) {
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
        $signature = sha1 ( $string );
        $WxConfig["appId"] = $appid;
        $WxConfig["nonceStr"] = $nonceStr;
        $WxConfig["timestamp"] = $timestamp;
        $WxConfig["url"] = $url;
        $WxConfig["signature"] = $signature;
        $WxConfig["rawString"] = $string;
        return $WxConfig;
    }
?>
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" name="viewport">
<head>
<title>中秋贺国庆海报生成</title>
    <link rel="shortcut icon" href="/favicon.ico" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script type="text/javascript">
        function fontSize(){
            var deviceWidth=document.documentElement.clientWidth>750?750:document.documentElement.clientWidth;
            document.documentElement.style.fontSize=(deviceWidth/25)+"px";
        }
        fontSize();
        window.onresize=fontSize;
    </script>
</head>
<style>
*,html{font-family: '微软雅黑'}
body{width: 100%;max-width: 750px;margin: 0px; padding: 0px;width: 100%;text-align: center;font-size: 1.5rem; overflow-x: hidden; background-color: #ffb612; font-family: '微软雅黑';}
    .app{ width: 100%;max-width: 750px; height: auto;overflow-y:scroll;overflow-x:hidden; background: #fff;  }
    .app img{width: 100%; height: auto;}
    .app p{ font-size: 1rem; color: #333; line-height: 1.2rem; text-align: center;}
    .app a{ list-style: none;outline:none; text-decoration: none; display: block; color: #fff; background: #f05555; font-size: 1.2rem; height: 3rem; line-height: 3rem; margin: 0 auto; margin-bottom: 1.2rem;}

</style>
<body>
<div id="app"></div>
</body>
    <!-- 画布 -->
    <script>
// 图片上传
        let canvas = document.createElement('canvas')
        canvas.width = "1024"
        canvas.height = "1374"  //创建画布,并设置宽高
        let ctx = canvas.getContext("2d")

        let wx_img = '<?php echo $userinfo['headimgurl']; ?>';
        wx_img = wx_img.substr(0, wx_img.length - 3);
       
        //随机背景图片
        var bgImg = './bg.jpg'; //背景图
        var qcode = './qcode.jpg'; //验证码


        loadImg([
            bgImg,
            wx_img+'0',
            qcode,
        ]).then(([img1, img2,qcode])=> {
                ctx.drawImage(img1, 0, 0, 1024, 1374) //画布上先绘制背景图`
                drawRoundRect(ctx,100,782,93, 87,87,img2);  //绘制头像
                drawRoundRect(ctx,2,782,1168, 90,90,qcode);  //绘制二维码

                // 对象 - 行高  - 文字一行内的数量  -文本 - x 坐标位置 -y
                writeTextOnCanvas(ctx,30,50,'<?php echo $userinfo['nickname']; ?>',750,153,'#fff','normal 25px Microsoft YaHei');  //名字

            imageURL = canvas.toDataURL("image/png") //获取图片合并后的data-URL,参数可选图片格式,图片质量,详自查API`
            let img3 = new Image()
            $('#app').fadeIn();
            document.getElementsByClassName("app")[0].append(img3)
            img3.src = imageURL
            canvas.style.display = "none"
            $("#app").append(" <p>长按图片保存</p><a href='javascript:;' onclick='colse()'>关闭</a>")
        });
    // }
    // 画圆形头像方法
    // r: 半径
     function drawRoundRect (ctx,r,x,y,w,h,img) {
                ctx.save()
                if (w < 2 * r) r = w / 2
                if (h < 2 * r) r = h / 2
                ctx.beginPath()
                ctx.moveTo(x+r, y)
                ctx.arcTo(x+w, y, x+w, y+h, r)
                ctx.arcTo(x+w, y+h, x, y+h, r)
                ctx.arcTo(x, y+h, x, y, r)
                ctx.arcTo(x, y, x+w, y, r)
                ctx.closePath();
                ctx.clip()
                ctx.drawImage(img, x, y, w, h)
                ctx.restore() // 返回上一状态
            }

    /****绘制自动换行的字符串****/
    //ctx_2d        getContext("2d") 对象  
    //lineheight    段落文本行高  
    //bytelength    设置单字节文字一行内的数量  
    //text          写入画面的段落文本  
    //startleft     开始绘制文本的 x 坐标位置(相对于画布)  
    //starttop      开始绘制文本的 y 坐标位置(相对于画布)  
    //ctx_fillStyle      字体颜色
    //ctx_font      字体
    //istrue 是否设置
    function writeTextOnCanvas(ctx_2d, lineheight, bytelength, text ,startleft, starttop,ctx_fillStyle,ctx_font){  
        function getTrueLength(str){//获取字符串的真实长度(字节长度)  
            var len = str.length, truelen = 0;  
            for(var x = 0; x < len; x++){  
                if(str.charCodeAt(x) > 128){  
                    truelen += 2;  
                }else{  
                    truelen += 1;  
                }  
            }  
            return truelen;  
        }  
        function cutString(str, leng){//按字节长度截取字符串,返回substr截取位置  
            var len = str.length, tlen = len, nlen = 0;  
            for(var x = 0; x < len; x++){  
                if(str.charCodeAt(x) > 128){  
                    if(nlen + 2 < leng){  
                        nlen += 2;  
                    }else{  
                        tlen = x;  
                        break;  
                    }  
                }else{  
                    if(nlen + 1 < leng){  
                        nlen += 1;  
                    }else{  
                        tlen = x;  
                        break;  
                    }  
                }  
            }  
            return tlen;  
        }  
        ctx_2d.textAlign="right";

        for(var i = 1; getTrueLength(text) > 0; i++){  
            var tl = cutString(text, bytelength); 
            ctx_2d.fillStyle= ctx_fillStyle; //字体颜色
            ctx_2d.font= ctx_font; //字体 
            ctx_2d.fillText(text.substr(0, tl).replace(/^\s+|\s+$/, ""), startleft, (i-1) * lineheight + starttop); 
            
            text = text.substr(tl);  
        }  
    }
    // --

    function loadImg(src) {
        let paths = Array.isArray(src) ? src : [src]
        let promise = paths.map((path) => {
            return new Promise((resolve, reject) => {
                let img = new Image()
                img.setAttribute("crossOrigin", 'anonymous')
                img.src = path
                //只是更新了DOM对象,图片数据信息还未加载完成,加载资源是异步执行的,需要监听load事件的,事件发生后,就能获取资源
                img.onload = () => {
                    resolve(img)
                }
                img.onerror = (err) => {
                    alert('图片加载失败')
                }
            })
          })
          return Promise.all(promise)
    }
    function ShowTheObject(obj){
        var des = "";
        for(var name in obj){
            des += name + ":" + obj[name] + ";";
        }
        return des;
    }
    //点击关闭按钮关闭
    function colse(){
        $('#app').html('')
        $('#app').fadeOut()
        $('.username').val('')
        $('.tel').val('')
        $('.rank').val('')
        
    }
    </script>
    <!-- 画布 -->
    <!-- 分享start -->
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <script>
            wx.config({
                debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                appId: '<?php echo $appid; ?>', // 必填,公众号的唯一标识
                timestamp: '<?php echo $ws["timestamp"]; ?>', // 必填,生成签名的时间戳
                nonceStr: '<?php echo $ws["nonceStr"]; ?>', // 必填,生成签名的随机串
                signature: '<?php echo $ws["signature"]; ?>',// 必填,签名,见附录1
                jsApiList: [
                    'checkJsApi',
                    'onMenuShareTimeline',
                    'onMenuShareAppMessage',
                    'onMenuShareQQ',
                    'onMenuShareWeibo'
                ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
            });
            wx.error(function(res){
                console.log(res.errMsg)
            })
            var wstitle = "中秋国庆月饼海报生成"; //此处填写分享标题
            var wsdesc = '中秋国庆海报生成,长按图片保存即可。'; //此处填写分享简介
            var wslink = "http://h5.example.com/csn"; //此处获取分享链接
            var wsimg = "<?php echo $userinfo['headimgurl']; ?>"; //此处获取分享缩略图
    </script>
    <script src="wxshare.js"></script>
    <!-- 分享start -->
</html>

3、分享wxshare.js文件代码

wx.ready(function () {
	// 分享到朋友圈
	wx.onMenuShareTimeline({
		title: wstitle,
		link: wslink,
		imgUrl: wsimg,
		success: function () {
			alert('分享成功');
		},
		cancel: function () {
		}
	});
	// 分享给朋友
	wx.onMenuShareAppMessage({
		title: wstitle,
		desc: wsdesc,
		link: wslink,
		imgUrl: wsimg,
		success: function () {
			alert('分享成功');
		},
		cancel: function () {
		}
	});
	// 分享到QQ
	wx.onMenuShareQQ({
		title: wstitle,
		desc: wsdesc,
		link: wslink,
		imgUrl: wsimg,
		success: function () {
			alert('分享成功');
		},
		cancel: function () {
		}
	});
	// 微信到腾讯微博
	wx.onMenuShareWeibo({
		title: wstitle,
		desc: wsdesc,
		link: wslink,
		imgUrl: wsimg,
		success: function () {
			alert('分享成功');
		},
		cancel: function () {
		}
	});
	// 分享到QQ空间
	wx.onMenuShareQZone({
		title: wstitle,
		desc: wsdesc,
		link: wslink,
		imgUrl: wsimg,
		success: function () {
			alert('分享成功');
		},
		cancel: function () {
		}
	});
});

说明:通过微信公众号获取用户信息,包含昵称,头像信息,使用js的canvas画布生成海报,长按图片,即可保存生成的海报。


  • 暂无任何回答