关于javascript:前端生成分享海报兼容H5和小程序

7次阅读

共计 3992 个字符,预计需要花费 10 分钟才能阅读完成。

挪动端分享海报生成

最近做我的项目需要是生成商品分享海报,并且保留到手机中要兼容 H5 和小程序

与后端同学沟通后,海报在前端生成最省性能和有较好的交互体验,先看做好的成果

前端框架应用的是 uni-app 不便打包成 H5 和小程序
实现计划是拿到后端返回的数据后,利用 canvas 画布把各个数据拼在一起并且生成一张图片
次要的参数有:背景图、商品图、二维码、价格、原价、题目

首先拿到产品图和二维码之后须要把它们下载下来用 uni-app 的 api 就能够
先写一个下载办法并且在 template 定义画布组件

<template>
<canvas class="canvas" canvas-id="myCanvas" v-if="canvasStatus"></canvas>
</template>
onReady(){this.downloadFileImg('','pic');
  this.downloadFileImg('','code');
},
methods:{downloadFileImg(url,name){
    let self = this
    uni.downloadFile({
      url: url,
      success: function(res) {self[name] = res.tempFilePath;
      },
      fail: function(erros) {console.log(error)
      }
    });
  }
}

这样图片就临时保留到本地临时文件了

uni.downloadFile 须要留神的是
在各个小程序平台运行时,网络相干的 API 在应用前须要配置域名白名单。在 h5 上是跨域的,用户须要解决好跨域问题。

下来编写 canvas 生成图片的办法

/**
    * 获取分享海报
    * @param array imgArr 海报素材 0 背景图 1 商品图 2 二维码
    * @param string store_name 素材文字
    * @param string price 价格
    * @param string ot_price 原始价格
    * @param function successFn 回调函数
*/
PosterCanvas: function(imgArr, store_name, price, ot_price, successFn) {
    let that = this;
    uni.showLoading({
        title: '海报生成中',
        mask: true
    });
    const ctx = uni.createCanvasContext('myCanvas');
    ctx.clearRect(0, 0, 0, 0);

    /**
    * 只能获取非法域名下的图片信息, 本地调试无奈获取
    * 
    */
    ctx.fillStyle = '#fff';
    ctx.fillRect(0, 0, 750, 1150);
    uni.getImageInfo({src: imgArr[0],
        success: function(res) {
            const WIDTH = res.width;
            const HEIGHT = res.height;
            ctx.drawImage(imgArr[1], 0, 0, WIDTH, WIDTH);
            ctx.save();
            let r = 110;
            let d = r * 2;
            let cx = 480;
            let cy = 790;
            ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);
            // ctx.clip();
            ctx.drawImage(imgArr[2], cx, cy, d, d);
            ctx.restore();
            const CONTENT_ROW_LENGTH = 20;
            let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name, CONTENT_ROW_LENGTH);
            if (contentRows > 2) {
                contentRows = 2;
                let textArray = contentArray.slice(0, 2);
                textArray[textArray.length - 1] += '……';
                contentArray = textArray;
            }
            ctx.setTextAlign('left');
            ctx.setFontSize(36);
            ctx.setFillStyle('#000');
            // let contentHh = 36 * 1.5;
            let contentHh = 36;
            for (let m = 0; m < contentArray.length; m++) {if (m) {ctx.fillText(contentArray[m], 50, 1000 + contentHh * m + 18, 1100);
                } else {ctx.fillText(contentArray[m], 50, 1000 + contentHh * m, 1100);
                }
            }
            ctx.setTextAlign('left')
            ctx.setFontSize(72);
            ctx.setFillStyle('#DA4F2A');
            ctx.fillText('¥' + price, 40, 820 + contentHh);

            ctx.setTextAlign('left')
            ctx.setFontSize(36);
            ctx.setFillStyle('#999');
            ctx.fillText('¥' + ot_price, 50, 876 + contentHh);
            var underline = function(ctx, text, x, y, size, color, thickness, offset) {var width = ctx.measureText(text).width;
                switch (ctx.textAlign) {
                    case "center":
                        x -= (width / 2);
                        break;
                    case "right":
                        x -= width;
                        break;
                }

                y += size + offset;
                ctx.beginPath();
                ctx.strokeStyle = color;
                ctx.lineWidth = thickness;
                ctx.moveTo(x, y);
                ctx.lineTo(x + width, y);
                ctx.stroke();}
            underline(ctx, '¥' + ot_price, 55, 865, 36, '#999', 2, 0)
            ctx.setTextAlign('left')
            ctx.setFontSize(28);
            ctx.setFillStyle('#999');
            ctx.fillText('长按或扫描查看', 490, 1030 + contentHh);
            ctx.draw(true, function() {
                uni.canvasToTempFilePath({
                    canvasId: 'myCanvas',
                    fileType: 'png',
                    destWidth: WIDTH,
                    destHeight: HEIGHT,
                    success: function(res) {uni.hideLoading();
                        successFn && successFn(res.tempFilePath);
                    }
                })
            });
        },
        fail: function(err) {uni.hideLoading();
            that.Tips({title: '无奈获取图片信息'});
        }
    })
},

首先创立一个 canvas 画布

获取背景图图片信息拿到宽和高再绘制商品图片并保留

接下来绘制二维码并把坐标放好并保留

在解决文字换行问题并设置大小色彩和对其形式

在绝对应的设置价格和原价的色彩和大小还有坐标

因为价格还有条横线,我在网上又搜下了横线的做法间接看办法就行

最初生成图片信息并且应用 uni.canvasToTempFilePath 办法把以后画布指定区域的内容导出生成指定大小的图片,并返回文件门路。

这样咱们就失去一个.png 的临时文件当初就剩最初一步把文件渲染到组件里了,从回调函数就能够回去到

此办法用的比如比拟多我把它写到公共办法外面并且绑定到 vue 原型下面不便咱们前面应用

当初编写办法调用

handelCanvas(){let imgArr = ['背景图门路',this.pic,this.code]
    this.$util.PosterCanvas(imgArr,'题目','价格','原价',function(tempFilePath){console.log(tempFilePath)
    })
}

这样就拿到生成好的图片的是一个临时文件 当初把他放到页面中展现就 ok 了
保留图片性能 H5 能够长按保留图片这里只用解决小程序的就行
首先检测受权拿到受权后调用 uni-app 的 api 就能够了

savePosterPath: function() {
    let that = this;
    uni.getSetting({success(res) {if (!res.authSetting['scope.writePhotosAlbum']) {
                uni.authorize({
                    scope: 'scope.writePhotosAlbum',
                    success() {
                        uni.saveImageToPhotosAlbum({
                            filePath: 'canvas 生成的长期图片',
                            success: function(res) {.... 胜利了},
                            fail: function(res) {.... 失败了}
                        });
                    }
                });
            } else {
                uni.saveImageToPhotosAlbum({
                    filePath: 'canvas 生成的长期图片',
                    success: function(res) {.... 胜利了},
                    fail: function(res) {.... 失败了}
                });
            }
        }
    });
},

这样前端生成海报就功败垂成了,你学废了吗?

最初打一波广告:

CRMEB 商城一个收费开源我的项目

挪动端应用 uni-app 框架目前曾经适配公众号、小程序、app(暂未公布)

治理后盾应用 vue+iview 框架

开源不易,心愿各位关注下,说不定你会有意外播种!

地址:http://github.crmeb.net/u/qiang

正文完
 0