The introduction

In my spare time, I took a spare time to write a small program for the manual of the Killing of generals of The Three Kingdoms. In the middle, there was a requirement to design a synthetic skin picture of generals, the names of generals in vertical rows, and a small program code, and then provide pictures to be saved to the album, so that users can finally share to the circle of friends or other platforms. There is no problem that the composite picture should be done according to the Canvas document, mainly there is a requirement of vertical text, here to share with you.

If you like The killing of three Kingdoms, you can follow it. If you have any questions, you can also add my wechat to discuss.

Scan code experience small procedures

Scan code to add friends, please note: The Killing of three Kingdoms

The body of the

Start by putting an image that will be saved to your album

I feel good about myself, at least as I expected

Let’s take a step-by-step look at how to do this.

The whole picture is divided into three parts:

  1. Blow to the picture
  2. Small program code
  3. Military general text message

Let’s take a look at the code in WXML, which basically puts a Canvas tag and controls the height and width properties.

<view>
  <canvas class='share-canvas' style="width:100%; height:{{canvasHeight}}px" canvas-id="share_canvas"></canvas>
</view>
Copy the code

Blow to the picture

drawHeroImage: function(path) { var that = this; // Get the Canvas Contextlet ctx = wx.createCanvasContext('share_canvas'); Wx.getimageinfo ({SRC: path, success:function(res) {// Calculate the image ratio informationletMaxWidth = math.min (res.width, tha.data.canvasWidth * 0.65); maxWidth = math.min (res.width, tha.data.canvasWidth * 0.65);let radio = maxWidth / res.width;

        let offsetY = (that.data.canvasHeight - res.height * radio) / 2;
        console.log('offsetY='+ offsetY); that.setData({ imageWidth: res.width * radio, imageHeight: res.height * radio, offsetY: offsetY, }); // Draw the canvas background, not part of the drawing image part ctx.setfillstyle ('white') ctx.fillRect(0, 0, that.data.canvasWidth, that.data.canvasHeight); // Path is the local path, can not pass the network URL, CTX. DrawImage (path, 10, offsetY, res.width * radio, Res.height * radio) // drawQrCodeImage(CTX); / / draw the forces Chinese characters: that wu drawInfluence (CTX, that. Data. Hero. Hero. INFLUENCE); DrawName (CTX, that.data.hero.name); drawName(CTX, that.data.hero.name); drawName(CTX, that.data.hero.name); Title: / / draw the military commanders Jiang Linghou that. DrawHorner (CTX, that. Data. Hero. Hero. HORNER); Draw (ctx.draw()); draw(ctx.draw()); }}); }Copy the code

Small program code

The small program code and the general picture is the same type, is nothing more than the need to calculate the position of the draw, here will not show the relevant code.

Military general text message

From just code, you can see that I got the three parts to map, in fact, wu and tracing the cause should be together, but I found that when drawing Spaces when drawing will cause abnormal, leading to the blank space at the back of the texts are not mapped, so I’m here to wu and tracing the cause in the middle of the blank is done by the position offset.

Here is how to draw the title of warrior.

// Draw the title of warrior: Jiangling Marquis drawHorner:function(CTX, text) {// Set the size ctx.setfontsize (26); // Set the font color ctx.setfillstyle ("# 000000"); // Calculate the starting point of drawinglet x = this.data.offsetX + 35;
    let y = this.data.offsetY + 10;
    console.log('drawHorner'+ text); console.log(x); console.log(y); DrawTextVertical (CTX, text, x, y); drawTextVertical(CTX, text, x, y); }Copy the code

Draw vertical text from the Internet to find an open source code, need to see the principle of please see here

Of course, I’ve made some changes to fit the applet. The function prototype looks like this:

CanvasRenderingContext2D.prototype.letterSpacingText = function (text, x, y, letterSpacing)
Copy the code

Forgive me for not being very good at JS, and I don’t understand what syntax this is. After reading it for a while, I didn’t understand it. It feels like adding new attributes to the class, regardless of him.

It doesn’t matter whether a cat is black or white, but it’s a good cat that catches mice

The modified function looks like the following:

canvas.js

/**
* @author zhangxinxu(.com)
* @licence MIT
* @description http://www.zhangxinxu.com/wordpress/?p=7362
*/
function drawTextVertical(context, text, x, y) {
  var arrText = text.split(' ');
  var arrWidth = arrText.map(function (letter) {
    return26. // Const metrics = context.measureText(letter); // console.log(metrics); // const width = metrics.width; //return width;
  });
  
  var align = context.textAlign;
  var baseline = context.textBaseline;

  if (align == 'left') {
    x = x + Math.max.apply(null, arrWidth) / 2;
  } else if (align == 'right') {
    x = x - Math.max.apply(null, arrWidth) / 2;
  }
  if (baseline == 'bottom' || baseline == 'alphabetic' || baseline == 'ideographic') {
    y = y - arrWidth[0] / 2;
  } else if (baseline == 'top' || baseline == 'hanging') {
    y = y + arrWidth[0] / 2;
  }

  context.textAlign = 'center';
  context.textBaseline = 'middle'; // Start to draw arrtext.foreach (functionVar letterWidth = arrWidth[index]; Var code = letter.charcodeat (0);if(code <= 256) { context.translate(x, y); Rotate (90 * math.pi / 180); rotate(90 * math.pi / 180); context.translate(-x, -y); }else if(index > 0 && text. CharCodeAt (index-1) < 256) {// y fix y = y + arrWidth[index-1] / 2; } context.fillText(letter, x, y); Context.settransform (1, 0, 0, 1, 0, 0); Var letterWidth = arrWidth[index]; y = y + letterWidth; }); // Restore context.textAlign = align; context.textBaseline = baseline; } module.exports = { drawTextVertical: drawTextVertical }Copy the code

Draw network pictures

Because network pictures cannot be drawn directly, you need to download them to the local first, and then press the local picture drawing process to go through.

downloadHeroImage: function() {// wechat does not support non-HTTPS image download, here is a replacementlet url = this.data.hero.HERO.ICON.replace(/http/, "https");
    var that = this;
    wx.downloadFile({
      url: url,
      success: functionVar path = res.tempFilepath; that.drawHeroImage(path); }, fail:function (res) {
        console.log(res)
      }
    });
  }
Copy the code

Save the picture

Having said that, the final step is to save the picture drawn to the canvas to the phone album, which requires user authorization and you need to deal with it yourself.

We used the interface wX.CanvastoTempFilepath provided by wechat. We need to pass in the starting coordinates (x, y) and the canvas size (width, height) and canvasId.

saveShareImage: function () {
    wx.showLoading({
      title: 'Saving pictures.. '});let that = this;
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: that.data.canvasWidth,
      height: that.data.canvasHeight,
      canvasId: 'share_canvas',
      success: function (res) {
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
            console.log(res);
            wx.showToast({
              title: 'Save to album successful',
              duration: 1500,
            })
          },
          fail(res) {
            console.log(res)
            wx.showToast({
              title: 'Save to album failed',
              icon: 'fail'
            })
          },
          complete(res) {
            console.log(res)
          }
        })
      }
    })
  }
Copy the code

Open source

In the spirit of open source, the source code has been posted on Github, where you can check out the code.

Github.com/HistoryZhan…

If it is helpful to you, please give a Star