Front-end generation and sharing poster is compatible with H5 and applet

Mobile sharing poster generation

Recently, the demand for a project is to generate a product sharing poster, and save it to the mobile phone to be compatible with H5 and applets

After communicating with the back-end classmates, the poster is generated in the front-end with the most low-performance and better interactive experience, first look at the effect

Please add a link description for the source code address

Mar-16-2021 14-07-57.gif

Mar-16-2021 14-08-45.gif

The front-end framework uses uni-app to be easily packaged into H5 and small programs. The
implementation solution is to get the data returned from the back-end and use the canvas to put the data together and generate a picture. The
main parameters are: background image, product Picture, QR code, price, original price, title

After you get the product image and QR code, you need to download them. Use the uni-app API
to write a download method and templatedefine the canvas component

<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)
      }
    });
  }
}

In this way, the picture is temporarily saved to a local temporary file

uni.downloadFileIt should be noted that
when each applet platform is running, network-related APIs need to be configured with a domain name whitelist before use. It is cross-domain on h5, and users need to handle cross-domain issues.

Write down the method for canvas to generate pictures

/**
    * 获取分享海报
    * @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: '无法获取图片信息'
            });
        }
    })
},

First create a canvascanvas<br>
get the background image information, get the width and height, and then draw the product image and save it<br>
Next, draw the QR code and place the coordinates and save it.<br>
When dealing with the word wrapping problem and setting the size Color and its method<br>
Set the color and size of the price and the original price correspondingly, as well as the coordinates.<br>
Because the price has a horizontal line, I searched the horizontal line on the Internet and just looked at the method.< br>
Finally generate picture information and use the uni.canvasToTempFilePathmethod to export the contents of the specified area of ​​the current canvas to generate a picture of the specified size, and return the file path. <br>In
this way, we will get a temporary .png file. Now we have the last step to render the file into the component. From the callback function, we can go back to it.<br>
This method uses a lot of examples. I wrote it in a public method. Inside and bound to the vue prototype for us to use later<br>
Now write method calls

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

In this way, the generated picture is a temporary file. Now put it on the page and display it. The
save picture function H5 can long press to save the picture. Here, only the small program is used.
First, check the authorization and call uni after the authorization is obtained. -app's api is fine

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) {
                        ....失败了
                    }
                });
            }
        }
    });
},

This way the front-end poster generation is complete, have you abandoned it?

Guess you like

Origin blog.51cto.com/15135607/2662531