Next, I will put the pure front-end implementation of poster generation process to tell you clearly, the pit I have encountered, to share and explain in detail, to prevent you from similar problems, even if there is a problem, there will be a clear direction, and suggest that we collect a wave, in case of a rainy day. (You can’t guarantee the future requirements, there is no similar, if there is, please check it out)

The road is long, someone has to dare to step on the pit first step, I think I am that 😂😂, I hope you can step on my risk to carry the ambulance hole filled, leading to the small program generated poster victory road. Send rose, hand left lingering fragrance, reading friends can give the author praise, pay attention to a wave of updated super dry, super core front-end articles.

Let me write one out front

1 Canvas draws posters with QR codes. There is always one of these pits that you may step on. I will take you step by step to solve these pits

Technical selection background: TARO3.0-VUE

Let’s start with eleven questions. I believe you will meet them in the process of drawing posters

Taro framework encountered pits

Taro-vue createCanvasContext: Invalid canvas instance ✅

(2) Taro-vue initialization can not obtain the canvas context, how to draw the picture completely? ✅

The pit encountered by the applet canvas

(3) Regarding the canvas width, height and zoom ratio, the elements drawn are distorted. Is the canvas height really equal to the width and height set by the Cavans tag? ✅

④ How does canvas draw two pictures stacked together and control the level? ✅

⑤ How to use Canvas to draw multi-line text? ✅

⑥ How to accurately restore the location of each element of the poster according to the design draft. ✅

⑦ Canvas how to draw base64 pictures ✅

⑧ how to draw network pictures, two kinds of Canvas canvas API, draw pictures what is the difference between complete ✅

Generate the qr code encountered by the pit

⑨ How to select the tool to generate TWO-DIMENSIONAL code correctly? ✅

⑩ Generated two-dimensional code, can not identify what to do, ✅

How to draw the LOGO ✅ on the QR code

2 Implementation Effect

The first stage: small program CANva initialization

1. Two ways of CAVNAS to obtain context

The problem we’re about to solve

Taro-vue createCanvasContext: Invalid canvas instance

(2) Taro-vue initialization cannot obtain canvas context.

Wechat official website introduces two ways for canvas to obtain context, one is the old API and the other is the new API. Next, I will explain the usage of these two apis.

Old version createCanvasContext

CreateCanvasContext is an old interface provided by wechat to get canvas instance. It can be used as follows.

wxml

<canvas style="width: 300px; height: 200px;" canvas-id="firstCanvas"></canvas>
Copy the code

Start your day by writing hello,world.

Js

onReady(){
    /* Use wx.createcontext to get the drawing context. FirstCanvas corresponds to canvas-id in the Canvas property
    const context = wx.createCanvasContext('firstCanvas')
    /* Set the font size */
    context.setFontSize(20) 
    /* Set the font color */
    context.setFillStyle('pink')
    /* Sets the text content, position */
    context.fillText('hello,world'.0.0)
    context.draw()
}

Copy the code

The old version uses the Canvas-id attribute in the canvas tag passed by createCanvasContext to obtain the Canvas instance. To be honest, the old version is not flexible enough to use. Many Settings of canvas lines and colors are encapsulated as methods, and methods need to be called every time they are changed.

New version getContext context mode

The new method is to get the Canvas element node through createSelectorQuery and then get the context through getContext.

wxml

 <canvas type="2d" id="myCanvas"></canvas>
Copy the code

js

const query = wx.createSelectorQuery()
query.select('#myCanvas')
.fields({
    node: true.size: true
})
.exec((res) = >{
    const { node } = res[0]
    if(! node)return
    /* Get canvas instance */
    const context = node.getContext('2d')
    context.fillStyle = 'pink'
    /* Set font style size font type */
    context.font = 'normal 400 12px PingFangSC-Regular',
    context.fillText('hello,world'.0.0)})Copy the code

This approach is slightly different from the first createSelectorQuery approach in terms of how the API is used. This approach is more like the native DOM approach, setting the color, style, and context properties without calling the corresponding API.

Taro – vue using canvas

Taro-vue createCanvasContext: Invalid canvas instance

Taro-vue2 is our applet technology choice, so I will focus on the taro-vue, currently using createCanvasContext to get canvas instance, drawing canvas has never been successful. Even though createCanvasContext can create a context, nothing can be drawn (passing schemes such as this is tried again). If you ask me why? Actually, I don’t know, only the students in Bump Lab should know better. There is also an issue on GitHub, and I hope the Taro team can pay attention to it.

The solution is to adopt the latest API, which is the second solution mentioned above. The code is as follows:

import Taro  from '@tarojs/taro'
const query = Taro.createSelectorQuery()
query.select('#myCanvas')
.fields({
    node: true.size: true
})
.exec(res= >{
    //TODO:.
})
Copy the code

(2) Taro-vue initialization cannot obtain canvas context.

When using taro-vue, you may encounter a problem that the small program node cannot be obtained. This problem may be caused by the life cycle of the small program itself and the chaos of the vue life cycle. This is especially true if we choose components instead of pages. In such cases, official documents provide the answer. Executed when the page is first rendered, this life cycle corresponds to the onReady life cycle of the applet page on the applet side. The real DOM can be accessed from this lifecycle using apis such as createCanvasContext or CreatesElectorQuery.

So if we want to get a real DOM node, we can do this,

In the component

mounted () {
    eventCenter.once(getCurrentInstance().router.onReady, () = > {
       const query = Taro.createSelectorQuery()
        query.select('#myCanvas')
        .fields({
           node: true.size: true
        })
        .exec(res= >{
        //TODO:.})})}Copy the code

Embarrassingly, this can sometimes result in the eventCenter.once() callback not executing, for example if the current component is receiving a V-IF control. So what’s the solution? For this situation, LET me show you a solution.

NextTick we can use taro, through the taro. NextTick method, the task of obtaining elements in the next nextTick execution.

mounted(){
  Taro.nextTick(() = > {
      // Get the element})}Copy the code

2 the initializationcanvasSet the width/height percentage

The questions we will tackle:

(3) Regarding the canvas width, height and zoom ratio, the elements drawn are distorted. Is the canvas height really equal to the width and height set by the Cavans tag?

<template>
    <view>
        <canvas
            id="myPoster"
            type="2d"
            class="canves"
            :style="canvasStyle"
        />
    </view>
</<template>
Copy the code

Here, we should first understand two concepts, namely, the width and height of the container: the width and height we set for the Canvas tag is the canvasStyle in the above code, which is the width and height of the Canvas container. Canvas width and height: The width and height of our canvas, in the new VERSION of the API, is dynamically set to the node.width and Node.height values of the Node node.

We expect to use the entire screen as a canvas, and the screen size will vary from phone to phone, so dynamically capture the width and height of the device. The reason is as follows: The canvas canvas of the applet has an original canvas width and height, as well as a scaling ratio of one pixel. When we set the canvas container width and height, If there is no corresponding canvas width, height and scale, the painted canvas will be seriously deformed. Let’s use an example to explain.

For example, if we want to draw an image on the top half of the canvas, we want to draw the canvas at normal scale, if we only widen the cavans tag, but do not set the width and height of the canvas. It will be drawn in accordance with the width to height ratio of the original canvas.

As a result, the canvas fills the screen and the images are displayed in normal proportions. When we do not set the canvas width, height and zoom ratio for the Cavnas canvas. Here’s what happens.

Actual results:

So when we initialize, we give the canvas something like this. This is explained in the official documents of wechat.

import Taro, {
    eventCenter,
    getCurrentInstance
} from '@tarojs/taro'

export default {
    
    name:'myPoster'.data(){
        const {
            windowHeight,
            windowWidth,
            pixelRatio
        } = Taro.getSystemInfoSync() /* Dynamically get the width and height of the device */
       return {
            canvasStyle: {           /* Width and height of cavnas */
                width: windowWidth + 'px'.height: windowHeight + 'px',
            },
            windowWidth,
            pixelRatio,   /* Screen zoom ratio */
            windowHeight,
            scale:1}},mounted(){
        Taro.nextTick(() = > {
            const query = Taro.createSelectorQuery()
            query.select('#myPoster').fields({
                node: true.size: true
            }).exec(res= > {
                let {
                    node,
                } = res[0]
                if(! node)return
                 The width and height of the canvas and the width and height of the element must have the same aspect ratio column, otherwise it will distort */
                const dpr = this.pixelRatio
                const context = node.getContext('2d')
                node.width = windowWidth * dpr
                node.height = windowHeight * dpr
                context.scale(dpr, dpr)
                context.fillStyle = '#fff'
                context.fillRect(0.0, windowWidth, windowHeight)
            })
        })
    }
}
Copy the code

Once we set the canvas width, height, and zoom ratio, we can draw in the normal ratio column. Let’s take a look at how the image looks after we set the zoom ratio.

Next comes the drawing phase.

The second stage: virtual point drawing canvas stage

Before explaining how Canvas generates posters and perfectly restores the design draft, we should ask a question, because canvas canvas, after all, is not a DOM model, and can use div or View to customize the layout style. Cavnas requires us to draw the layout effect of elements, which is to accurately obtain the x and Y values of each element on the canvas relative to the canvas. So the first thing that comes to mind is how to get the exact x and y values for each element.

1. Restore the actual design draft at virtual points

Solve the problem: â‘¥ How to accurately restore the location of each element of the poster according to the design draft. For the perfect restoration of the design, the more reliable solution is to first 1:1 normal hanging in the DOM element, and then by obtaining the location of the element, draw the element position of the Canvas. Let’s draw a picture to show how this works.

Matters needing attention

Note 1: Select the correct element fetch point

For example, we might have a structure like this in a DOM element.

<view class="box" >
    <view class="parent" >
        <view class="son" >Here's what you're going to draw to the canvas.</view>
    </view>
</view>
Copy the code

For the above structure, we only need to draw the content in son to the canvas canvas, then there is a question, which level of element information we want to obtain (left,top,width,height), the answer should be the closest layer of the content to draw, namely the son level. If we choose the outer layer, we may be affected by the parent elements such as padding and margin, resulting in inaccurate position.

Note 2: Try not to add elements that get informationpadding marignIf you draw text content, try to make the container height equal to the text height

Another problem is to try not to add attributes such as padding marign to elements that need to be drawn. If you are drawing plain text, do not set lineHeight, as shown in the following example:

We expect to get location information at point A, but we end up getting location information at point B. If point B is used to draw canvas, it is bound to fail to restore the design draft perfectly. Therefore, we should pay attention to these details when drawing canvas in this way.

Encapsulate methods to get location information

We need to draw each point on the poster, and the first thing that comes to mind is to get the applets element location method and wrap that method. We use promises to prevent deep callbacks and to make it easier to use async await syntactic candy. Without further ado, it doesn’t fit the code.

    /* Get the element position */
    geDomPostion(dom, isAll) {
        return new Promise((resolve) = > {
            Taro.createSelectorQuery().select(dom).boundingClientRect(rect= > {
                const {
                    top,
                    left
                } = rect
                /* isAll Whether to obtain the device width information */
                resolve(isAll ? rect : {
                    top,
                    left
                })
            }).exec()
        })
    },
Copy the code

Tip: if you are using WX native or another cross-end framework mpvue wepy UniApp, change Taro to WX.

2 Draw network images

Draw network pictures

⑨ How to draw a web image, what is the difference between drawing an image using the Canvas API?

When drawing pictures with Canvas, local pictures can be drawn directly by drawing the drawImage provided by canvas, but network pictures cannot be drawn in this way. We first need to obtain the temporary path of the picture through getImageInfo. When using getImageInfo to draw network resources, please pay attention to configure the legitimate download domain name, otherwise we will not be able to successfully obtain the image information. We first need to configure the legal domain name downloadFile in the background of the small program.

The steps are as follows: Step 1:

The second step:

Step 3:

The next thing we need to do is read the temporary path of the image and draw it onto the Canvas canvas.

 /* backGroundImageUrl is the address of the network image we want to draw */
 this.getImageInfo(this.backGroundImageUrl).then(res= >{
      const {
        width,   / * * / width
        height,  
        path     /* Temporary path */
      } = res1
      /* Step 2: Draw the banner */
    const bannerImage = await this.geDomPostion('#bannerImage')
    this.startTop = bannerImage.top - 30
    this.drawImage(context, node, path, 0.0, width, height, 0.this.startTop, windowWidth, windowWidth)
    context.save()
 })
Copy the code

This. DrawImage is the method we encapsulated. As mentioned earlier, there are some differences between the two interfaces for small programs to get the context and draw a Canvas image, which we’ll cover in a minute.

The difference between new and old interface drawing pictures

Old version drawing method

Older versions of the createCanvasContext API can draw images directly using drawImage. The following

/* Draw a picture */
context.drawImage(url,x,y,width,height,dx,dy,dwidth,dheight)
Copy the code

The second new API that we were using in the project was getContext and we were getting the context, so we were going to change the way we drew the image.

New version drawing method

  const image = node.createImage()
  image.src = url
  image.onload = () = > {
    context.drawImage(image,x,y,width,height,dx,dy,dwidth,dheight)
  }
Copy the code

For those drawing images using the new VERSION of the API, please note that the onLoad callback is executed when the image is finished loading, so the description is asynchronous. One other thing to note is that unlike the old version of drawImage, where the first parameter is the path of the image, the new version of drawImage takes the image element as its first parameter.

Package drawing picture method

Just at the end of drawing the network image, we called this. DrawImage. During the whole process of poster generation, multiple pictures will be drawn inside, so we have encapsulated a method of drawing pictures separately.

/* Draw a picture */
drawImage(context, node, url, ... arg) {
    return new Promise((resolve) = > {
        const image = node.createImage()
        image.src = url
        image.onload = () = >{ context.drawImage(image, ... arg) resolve() } }) },Copy the code

So we can say “async” and “await” to see if the image is loaded.

Brief introduction to the context. DrawImage

I’m going to give you a quick overview of how to use context. DrawImage.

CanvasContext.drawImage(imageResource / dom, sx,  sy,  sWidth,  sHeight,  dx,  dy,  dWidth,  dHeight)
Copy the code

Draw image to canvas, the first parameter, which in the old API represents the path, in the new API represents the imagDom element,

Sx needs to be drawn to the canvas, imageResource/DOM’s rectangle (clipping) selection box in the upper left x-coordinate

Sy needs to be drawn to the canvas, imageResource/DOM’s rectangle (clipping) selection box in the upper left y-coordinate

SWidth needs to be drawn to the canvas, imageResource/DOM’s rectangle (clipping) selection box width

SHeight needs to be drawn into the canvas, imageResource/DOM’s rectangle (clipping) selection box height

The upper-left corner of the DX imageResource is on the X-axis of the target canvas

The upper left corner of the Dy imageResource is positioned on the Y-axis of the target canvas

DWidth The width to draw the imageResource on the target canvas, allowing scaling of the drawn imageResource

DHeight The height at which the imageResource is drawn on the target canvas, allowing scaling of the drawn imageResource

We have a picture of what each property corresponds to.

3 Draw a hierarchy picture

Problem solved: â‘£ How does canvas draw two pictures stacked together and control the hierarchy?

If we draw two images stacked on top of each other, what kind of work do we need to do? The first thing that comes to mind is the hierarchy. We expect the background image to be on the bottom, such as an avatar on top, but there is no property in the canvas that controls the zIndex hierarchy. The answer is that in fact, in canvas, the order of drawing is the hierarchical order of canvas, and the last one is drawn at the upper level of the first one. As for such hierarchical problems, we can solve them perfectly as long as we ensure that the elements of higher level are drawn after the first one and the elements of lower level are drawn first. Then, we can draw the head picture, text and other information in the poster.

<! -- Avatar area -->
<image  class="userheadImage"  id="userheadImage"  :src="headImage"  />

Copy the code
    / *TODO:Draw your avatar */
    const userheadImage = await this.geDomPostion('#userheadImage'.true)
    /* Circular image */
    let d = userheadImage.height / 2
    const cx = userheadImage.left + userheadImage.width / 2
    let cy = userheadImage.top + userheadImage.height / 2
    context.arc(cx, cy, d, 0.2 * Math.PI)
    context.strokeStyle = '#FFFFFF'
    context.stroke()
    context.clip()
    await this.drawImage(context, node, this.headImage, userheadImage.left, userheadImage.top, userheadImage.width, userheadImage.height)
    context.restore()
    this.drawText(context,{ top: userheadImage.top + userheadImage.height + 40 ,left : userheadImage.left - 70 },'I'm not an Alien' Front-end Sharing.18.'normal 600 20px PingFangSC-Regular'.'#fff')
Copy the code

After we use context.clip(), remember to reset with context.restore(), otherwise no other elements will be drawn.

Effect:

We have solved the problem of text hierarchy perfectly. Next, we are going to draw the main content of the poster. When we draw posters, we may encounter multiple lines of text, so many lines of text, how do we solve?

4 Draw multiple lines of text

⑤ How to draw multi-line text on Canvas?

The text drawn on canvas cannot be wrapped automatically like the text under our DOM element. How can we restore the effect of multi-line text? Here is a method to teach you, we can draw one word at a time to the canvas, and then add the width of each word, if the total width is greater than the width of the container, then start another line, increase the height of each line, and start from scratch. Let’s go straight to the code.

       /** Draw multi-line text *@param CTX Canvas context *@param STR multi-line text *@param The initial top value of the initHeight container *@param InitWidth The container's initial left value *@param CanvasWidth Container width */
        drawRanksTexts(ctx, str, initHeight, initWidth, canvasWidth) {
            let lineWidth = 0;
            let lastSubStrIndex = 0;
            /* Set the text style */
            ctx.fillStyle = "# 303133"
            ctx.font = 'normal 400 15px PingFangSC-Regular'
            for (let i = 0; i < str.length; i++) {
                lineWidth += ctx.measureText(str[i]).width
                if (lineWidth > canvasWidth) { / * * / a new line
                    ctx.fillText(str.substring(lastSubStrIndex, i), initWidth, initHeight)
                    initHeight += 20
                    lineWidth = 0
                    lastSubStrIndex = i
                }
                if (i == str.length - 1) {  /* No newline */
                    ctx.fillText(str.substring(lastSubStrIndex, i + 1), initWidth, initHeight)
                }
            }

        },
Copy the code

call

/ *TODO:Copy multiple lines of text */
const rowsText = await this.geDomPostion('#context'.true)
this.drawRanksTexts(context, this.skuName, rowsText.top, rowsText.left, rowsText.width)
Copy the code

The effect

The third stage: generate two-dimensional code

Next we do is to draw two-dimensional code, two-dimensional code drawing process, the author stepped on a lot of pits, especially taro-Vue does not support createCanvasContext method, I hope I can use my own pit, let everyone avoid the same mistake, to avoid a lot of detour. Drawing two-dimensional code is not as complex as you can imagine. In fact, it is to convert the link into two-dimensional code so that the phone can scan or long press to identify it. Although the principle is very simple, there are still a lot of details to pay attention to.

There are two ways to draw two-dimensional code. The first way is to draw it with canvas. The second turns the link into a base64 link and then lets the image display the link. Next we for these two ways, two-dimensional code library technology selection.

1 about the selection of TWO-DIMENSIONAL code library

⑨ How to select the tool to generate TWO-DIMENSIONAL code correctly?

The formation of two-dimensional code process, we certainly can not masturbate algorithm, because even if we can masturbate out, will take a lot of time, there will be a lot of bugs, because now the generation of two-dimensional code ecology has been very sound, such as qrcode.js and so on is very good, but the only bad is not support small program side. Here I introduce a few two-dimensional code library

weapp-qrcode

For short links like the author’s GitHub github.com/GoodLuckAli… Or nuggets home page juejin.cn/user/241858… If you do not need to spell long parameters, you can use p-qrcode adequately. This is based on the first canvas drawing method. And it’s using the old version of the API, so there’s a problem with that, if you want to use the new getContext method, you have to download the source code, and then modify it to support getContext. Let’s take a look at the use of app-qrcode.

use

If you use taro Uniapp or other frameworks, NPM install can be used
import drawQrcode from '.. /.. /utils/weapp.qrcode.esm.js'

drawQrcode({
  width: 200.height: 200.canvasId: 'myQrcode'.// ctx: wx.createCanvasContext('myQrcode'),
  text: 'https://juejin.cn/user/2418581313687390'.V1.0.0 + supports drawing images on qr codes
  image: {
    imageResource: '.. /.. /images/icon.png'.dx: 70.dy: 70.dWidth: 60.dHeight: 60}})Copy the code

The results of

It worked because I used github short links when I was doing the demo. However, when I returned to the project of the author’s company, the link was very long, but the two-dimensional code generated was so dense that the mobile phone could not recognize it. I had no choice but to change other technical solutions, so the author chose the second more stable way to form base64 files.

qrcode-base64

Qrcode-base64 is to convert the link of qrcode into the link of base64, and assign the link to the image as the SRC attribute. Let’s start with the basics.

download

npm install qrcode-base64
Copy the code

use

import QR from 'qrcode-base64'

var imgData = QR.drawImg(this.data.codeText, {
    typeNumber: 4.errorCorrectLevel: 'M'.size: 500
})
// Return output base64 encoded imgData
Copy the code

As shown in the above code block, imgData is the base64 link generated, we can directly use it as the SRC of the image, and then ask Canvas to draw the image into our poster, but there is another problem, canvas does not support drawing the base64 link image, there is no effect on the real machine. It’s a big mistake. We still have to figure out how to solve this problem.

2 Canvas draws base64 images

How does canvas draw base64 pictures

As for the pictures that canvas does not support Base64 mentioned above, we need to draw the TWO-DIMENSIONAL code into the poster, so there is no problem, we can use the file system provided by the small program to solve the problem.

Applets file system

Wx.getfilesystemmanager gets the globally unique file manager and returns a value similar to fs in Node.

WriteFile writes files, which can write pictures to the system.

const fs = wx.getFileSystemManager()

fs.writeFile(/* Write file */)
Copy the code

Encapsulation method

Package drawing two-dimensional code method

  /* Generate a QR code */
        drawCode(ctx, node, x, y) {
            return new Promise((resolve) = > {
                const codeImageWidth = 150   /* Draw the width of the QR code */
                const canvasImageWidth = 85 /* The width of the qr code drawn to the canvas */
                const left = x - 15          / * * / left value
                const top = y - 22           / * * / top value
                const LogoWidth = 15       /* Width of qr code logo */
                const url = 'https://juejin.cn/user/2418581313687390'
                
                const base64 = QR.drawImg(url, {
                    typeNumber: 4.errorCorrectLevel: 'L'.size: codeImageWidth
                })
                /* Create a read/write stream */
                const fs = Taro.getFileSystemManager()
                const times = new Date().getTime()
                const codeimg = Taro.env.USER_DATA_PATH + '/' + times + '.png'

                /* Write the base64 image to */
                fs.writeFile({
                    filePath: codeimg,
                    data: base64.slice(22),  /* Data stream */
                    encoding: 'base64'.success: async() = > {const offset = (canvasImageWidth - LogoWidth) / 2 /* Offset */
                         /* Draw a picture */
                        await this.drawImage(ctx, node, codeimg, 0.0, codeImageWidth, codeImageWidth, left, top, canvasImageWidth, canvasImageWidth)
                        await this.drawImage(ctx, node, this.logoUrl, left + offset, top + offset, LogoWidth, LogoWidth)
                        resolve()

                    }
                })
            })

        },
Copy the code

As shown above, we have completed the drawing of the TWO-DIMENSIONAL code. Let’s see how it works.

use

We write an element on WXML as a placeholder so that we can get the location of the QR code.

<view id="qrCode" class="store-uscode" />
Copy the code
/ *TODO:Step 4: Draw the QR code */
const qrCode = await this.geDomPostion('#qrCode')
await this.drawCode(context, node, qrCode.left - 20, qrCode.top - this.cavnsOffsetop)
Copy the code

The effect

Scan success

3 debug the size of the TWO-DIMENSIONAL code, how to make the two-dimensional code can be recognized, draw the TWO-DIMENSIONAL code logo

â‘© Generated two-dimensional code, can not identify what to do.

Sometimes when the TWO-DIMENSIONAL code we show is relatively small, because the color block is too dense, the phone will also be unable to recognize the situation. So how do we adjust the TWO-DIMENSIONAL code, there can make the page as far as possible hi-fi restore design draft, here to teach you a tip, you can go to the two-dimensional code generation site, first adapted to mobile phone can identify the best proportion, to avoid identifying the situation. We can debug the pixel of the TWO-DIMENSIONAL code and the size of the logo online until it is adjusted to meet the optimal size of the design.

Adjust qr code online

Micro-adjustment Sometimes, we need to micro-adjust the size of the TWO-DIMENSIONAL code, I suggest that in the debugging stage, establish constant control, and adjust the writing of the adjustment method or formula. The advantage of this is that whenever we make a small adjustment, we do not affect the calculation due to the current adjustment, as shown below.

const codeImageWidth = 150   /* Draw the width of the QR code */
const canvasImageWidth = 85  /* The width of the qr code drawn to the canvas */
const left = x - 15          / * * / left value
const top = y - 22           / * * / top value
const LogoWidth = 15         /* Width of qr code logo */

const offset = (canvasImageWidth - LogoWidth) / 2 /* Offset */
Copy the code

4. Generate posters and pictures and forward them to friends

We’ve gone through the whole process. The last step is to generate the poster image and forward the image. To generate a poster, you can use the canvasToTempFilePath in the Wechat applet canvas to generate the image path, and then browse the image using the previewImage method. When you browse the image, you can wake up the wechat applet’s share friends function. One thing we should pay attention to here is to intercept the effective height of the canvas.

The code:

/* Generate the poster */
makePc(node) {
    const {
        startTop,    /* Capture the top of the canvas */
        endTop,      /* Capture the bottom of the canvas */
        windowWidth  /* Screen width */
    } = this
    const _this = this
    Taro.canvasToTempFilePath({
        x: 0.y: startTop,
        width: windowWidth,
        height: endTop - startTop,
        destWidth: windowWidth * 3.destHeight: (endTop - startTop) * 3.canvas: node,
        success: function (res) {
            Taro.hideLoading()
            Taro.previewImage({
                urls: [res.tempFilePath]
            })

        }
    })
}
Copy the code

CanvasToTempFilePath Precautions

Going back to the original problem, the old and new apis pass different arguments when calling the canvasToTempFilePath method.

In older versions of the API, the canvas drawn by createCanvasContext, canvasToTempFilePath configuration property canvas, the wechat developer documentation explains that the canvas canvas identifier, Pass the Canvas component instance (used when Canvas Type =”2d”), which is the Canvas context.

But we’re using a new canvas drawn with getContext, and when we pass in the context, it doesn’t work. What? There is this kind of thing, is there a problem with the wechat developer documentation? Query. Select canvas node. Query. Select canvas node. A mouthful of old blood is about to come out

5 Effect Overview

Five summarizes

When doing this function, I really encountered a lot of pits, and even had a feeling of wanting to cry without tears. However, stepping on the pits all the way, I really harvested a lot.

The project address

I put the whole process of poster generation demo project, uploaded to Github, interested students, you can have a look, especially those who are doing this function, come on ~

Please stamp the project address here

Happy New Year!

In the New Year, I wish you all the best in the New Year. I wish the nuggets community better and better.