Home  >  Article  >  WeChat Applet  >  How to use canvas to draw posters in a small program

How to use canvas to draw posters in a small program

hzc
hzcforward
2020-06-17 09:18:314631browse

The first article of 2020. I was busy reviewing and answering questions at the beginning of the year and never had time to write anything. The more books I read, the more I feel inferior to others. I have always been a novice. I happened to have a canvas in my recent project. The business suddenly ignited my UI front-end fire again, and I wrote down the pitfalls and thoughts.

Step on the Pit

Question 1: Why are pictures drawn on canvas blurred?

When drawing pictures/text on canvas, we set the width and height of canvas: 375*667. You will find that the drawn picture is very blurry and feels like a picture with poor resolution. The text There will also appear to be overlaying.

How to use canvas to draw posters in a small program

Note: A physical pixel refers to the smallest unit displayed on a mobile phone screen, while a device-independent pixel (logical pixel) in a computer device A point, the pixel set in css refers to the pixel.

Reason: In front-end development, we know that there is a property called devicePixelRatio (device pixel ratio). This property determines how many (usually 2) will be used when rendering the interface. ) physical pixels to render a device-independent pixel.

For example, for a picture of 100*100 pixels, on a retina screen, 2 pixels will be used to render one pixel of the picture, which is equivalent to doubling the picture, so the picture will Becomes blurry, which is why 1px becomes thicker on retina screens.

How to use canvas to draw posters in a small program

solve: Enlarge canvas-width and canvas-height by 2 times, and reduce the canvas display width and height by 2 times through style. Times.

For example:

<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>

Question 2: How to handle the conversion of px and rpx?

rpx is a unique size unit in the mini program, which can be adapted according to the width of the screen. On iPhone6/iphonex, 1rpx is equal to different px. Therefore, it is likely that your canvas display will be inconsistent under different mobile phones.

Before drawing the poster, the design drafts we get are usually based on the 2x image of iPhone6. And from the solution to the previous problem, we know that the size of canvas is also 2 times, so we can directly measure the design draft of 2 times the picture and draw the canvas directly, and the size needs to be paid attention to rpxtoPx.

/**
   * 
   * @param {*} rpx 
   * @param {*} int  //是否变成整数
   factor => 0.5 //iphone6
   pixelRatio => 2 像素比
   */
toPx(rpx, int) {
    if (int) {
      return parseInt(rpx * this.factor * this.pixelRatio)
    }
    return rpx * this.factor * this.pixelRatio
  }

Question 3 :About canvasContext.measureText when calculating pure numbers, it is 0 on the mobile phone

In the mini program, this.ctx.measureText(text).width is provided to calculate the length of the text, but if you If all digits are used, you will find that the API will always calculate to 0. Therefore, the simulated measureText method is finally used to calculate the text length.

measureText(text, fontSize = 10) {
    text = String(text)
    text = text.split('')
    let width = 0
    text.forEach(function(item) {
      if (/[a-zA-Z]/.test(item)) {
        width += 7
      } else if (/[0-9]/.test(item)) {
        width += 5.5
      } else if (/\./.test(item)) {
        width += 2.7
      } else if (/-/.test(item)) {
        width += 3.25
      } else if (/[\u4e00-\u9fa5]/.test(item)) { // 中文匹配
        width += 10
      } else if (/\(|\)/.test(item)) {
        width += 3.73
      } else if (/\s/.test(item)) {
        width += 2.5
      } else if (/%/.test(item)) {
        width += 8
      } else {
        width += 10
      }
    })
    return width * fontSize / 10
  }

Question 4: How to ensure that a line of fonts is displayed in the center? How many lines?

If the font is too long, it will exceed the canvas, making the drawing ugly. At this time, we should make the excess part become ...You can set a width and calculate it in a loop Extract the width of the text. If it exceeds the width, use substring to intercept it and add ....

let fillText=''
let width = 350
for (let i = 0; i <= text.length - 1; i++) { // 将文字转为数组,一行文字一个元素
        fillText = fillText + text[i]
        // 判断截断的位置
        if (this.measureText(fillText, this.toPx(fontSize, true)) >= width) {
          if (line === lineNum) {
            if (i !== text.length - 1) {
              fillText = fillText.substring(0, fillText.length - 1) + '...'
            }
          }
          if (line <= lineNum) {
            textArr.push(fillText)
          }
          fillText = &#39;&#39;
          line++
        } else {
          if (line <= lineNum) {
            if (i === text.length - 1) {
              textArr.push(fillText)
            }
          }
        }
      }

The calculation formula shown in the text play:

Centering in canvas can be used (width of canvas - width of text)/2 x (x is the movement of the x-axis of the font)

let w = this.measureText(text, this.toPx(fontSize, true))
this.ctx.fillText(text, this.toPx((this.canvas.width - w) / 2 + x), this.toPx(y + (lineHeight || fontSize) * index))

Question 5: How to process network diagrams in mini programs?

Regarding the use of network images in mini programs, such as images on CDN, you need to go down to WeChat for local LRU management, so that you can save download time when you draw the same image later. So first of all, you need to configure the legal domain name of downloadFile in the background of the WeChat applet. Secondly, before drawing on the canvas, it is best to download the image in advance and wait for the image to be downloaded before starting to draw to avoid some drawing failure problems.

Question 6: Base64 image data can be set in the IDE for drawing, but is it useless on the real machine?

First convert base64 into Uint8ClampedArray format. Then draw it to the canvas through wx.canvasPutImageData(OBJECT, this), and then export the canvas as a picture.

Question 6: How to draw a rounded corner picture?

Question 7: About wx.canvasToTempFilePath

After using Canvas to draw successfully, directly call this method to generate pictures. There is no problem on the IDE, but the generated pictures will be incomplete on the real machine. In this case, you can use a setTimeout to solve this problem.

this.ctx.draw(false, () => {
        setTimeout(() => {
            Taro.canvasToTempFilePath({
              canvasId: 'canvasid',
              success: async(res) => {
                this.props.onSavePoster(res.tempFilePath)//回调事件
                // 清空画布
                this.ctx.clearRect(0, 0, canvas_width, canvas_height)
              },
              fail: (err) => {
                console.log(err)
              }
            }, this.$scope)
          }, time)
    })

Question 8: About canvasContext.font

fontsize cannot use decimals If the font size part of the font setting contains decimals, the entire font setting will be invalid.

Question 9: Font rendering is misaligned under Android?

How to use canvas to draw posters in a small program

This problem occurs on Android phones, and iOS behaves normally. When I first saw this problem, I couldn't figure out why some were in the middle while others were much further forward. Later I found out that this.ctx.setTextAlign(textAlign) default is center under Android, which caused confusion. After changing it to left, it became normal.

Question 10: Draw a line chart

How to use canvas to draw posters in a small program

Use canvas to draw a simple line chart, just use lineTo and moveTo just connect the dots of the two API. Use createLinearGradient to draw shadows.

Thinking

Thinking 1: Limitations of using json configuration table to generate posters

The current poster generation only needs to measure the size according to the design draft, but the measurement The process is still very cumbersome, and manual fine-tuning is required in areas where the design draft is insufficient. Later, you can also use drag and drop to complete the design draft on the web side, and automatically generate json and apply it to the poster of the mini program.

Thinking 2: Limitations of back-end generated posters

The posters were initially generated by back-end classmates. The advantage is that it does not require front-end drawing time, and there is no need to step on the pitfalls of WeChat API and interface. Return to get the URL and display it, but the effect generated on the back end is not good. After all, this kind of work is more front-end.

Thinking 3: Limitations of front-end generation of posters

When the front-end generates posters, I find that it takes longer, including downloading the image locally, and also needs to write a special setTimeout for Android to ensure drawing normal. Various compatibility issues, mobile DPR, Android and ios and other non-stop Easter eggs will make your head bald~ Hahahaha~

Easter Egg

It is impossible to use the latest canvas-2d background image Draw them all?

During the development process of canvas, there was always a glimmer of light in the mini program to remind me.

How to use canvas to draw posters in a small program

I also tried the latest canvas2d api. It is indeed synchronized with the web side and the writing method is smoother. I can see it in the developer tools. Everything works fine. When running on a mobile phone, only half of the width is displayed. The same is true when testing on various models.

How to use canvas to draw posters in a small program

It will be fine if you change it to the original canvas later. . . The specific reason has not yet been found in the WeChat community. We will study it in subsequent iterations and upgrades.

How to use canvas to draw posters in a small program

Recommended tutorial: "JS Tutorial"

The above is the detailed content of How to use canvas to draw posters in a small program. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete