preface

Everyone in the circle of friends a few days ago @ WeChat official, grant flag, didn’t get the little friends, WeChat official have frustrated ah ~ on a whim, I decided to use js to write a function, add the flag to face and then I will send his flag, it has been proved that want something or can only rely on their own hands to create. Ha, ha, ha, ha, this chicken soup is not touchable ~, back to the subject, let’s see how I achieved it ~~

The implementation process

ideas

In fact, the realization principle of adding a national flag to your profile picture is very simple. It is to get your picture resources (that is, your profile picture), draw the picture with canvas, and then draw a small national flag in the lower right corner of the picture, so that the basic functions are realized. Let’s go step by step to add a flag to the avatar function. The source address

As required by the comments section, I have posted a rendering of the avatar after the code processing (the image has a white rounded border, which may overlap with the white background of the blog, so it is not very good aesthetic, just look at it ~).

I summarized my thought process for developing this feature as follows:

  1. Create the input tag, define the onchange event, read the image resource, get the base64 encoding of the avatar;
  2. To create a Canvas tag, find a picture of the national flag on the Internet, also get the Base64 encoding of the picture, and then use the Canvas drawImage API in turn to draw the head picture and the national flag in a specific position.
  3. The right Angle of the head and flag was too stiff, so I wrote a way to add a white rounded border to the head and flag.
  4. Writing the height of the canvas will cause the image to stretch, so I want to fix the width of the canvas. The height of the canvas will be set to the height of the canvas based on the senior aspect ratio of the image and the known width. Since the drawing area of the flag is relative to the lower right corner of the canvas, it is necessary to draw the flag after the height of the canvas is determined (that is, after the head painting is completed).
  5. Download the pictures drawn on canvas and write the logic of downloading pictures.

Start coding

HTML code:

The < div > < div > < button class = "input - the container" > upload picture < input accept = "image/GIF image/jpeg, image/PNG" class = "file - input" Id ="fileInput" type="file" /> </button> <button class="save-btn" onclick="downLoad()"> Save pictures </button> </div> <canvas id="canvas" class="canvas"></canvas> </div>Copy the code

Js code:

Const options = {avatarImgX: 0, // avatarImgY: 0, // avatarImgY: 0, // avatarX: 0, // avatarImgY: 0, // avatarX: 0 AvatarWidth: 200, // The width of the head to be drawn on the canvas avatarHeight: 200, // Width of the head to be drawn on the canvas radius: 5, // Radius of the head's corner guoqiRadius: 3, // Radius of the flag's corner guoqiX: 0, // X coordinate of the flag to be clipped GuoqiHeight: 50, // The width of the flag to draw on the canvas // The width of the flag to be drawn on the canvas // The base64 encoding of the flag is stored. } // define some constants const canvas = document.getelementById ('canvas'); const ctx = canvas.getContext('2d'); const inputUpload = document.getElementById('fileInput'); // Define the input onchange event, Window.onload = function() {inputupload.onchange = function uploadAvatar() {const file = window.onload = function() {inputupload.onchange = function uploadAvatar() {const file = this.files[0]; Const fileReader = new fileReader (); fileReader.readAsDataURL(file); Filereader.onload = function () {// To ensure that the image is not distorted, the height of the canvas is calculated based on the width ratio of the uploaded avatar and the width defined in the options. // We need to draw the flag in the callback function after drawing the head. function cb() { const param = { sx: options.guoqiX, sy: options.guoqiY, x: canvas.width - options.guoqiWidth - options.radius * 2, y: canvas.height - options.guoqiHeight - options.radius * 2, width: options.guoqiWidth, height: Options. guoqiHeight} // Call the tool function to draw the picture, Incoming drawAvatar required parameters (options. Guoqi, cb, param sx, param. Sy, param. X, param. Y, param. Width, param. Height, Options. guoqiRadius)} // Call the drawing tool function, Incoming drawAvatar required parameters (this result, cb, the options. AvatarImgX options. AvatarImgY, options.avatarX,options.avatarY,options.avatarWidth, options.avatarHeight); }}}; Function drawAvatar(imgSrc,cb,... args) { let img = new Image(); img.src = imgSrc; // In many cases, the logic for drawing images will be written in onload. // This is because the image resources are usually obtained by network request. // We will ensure that the drawing can be completed properly after the resource is loaded. Img. onload = function () {args.splice(2, 0, img.width,img.height); // Calculate and set the height of the canvas, If (args[6] === options.avatarWidth) {args[7] = parseInt(args[6] / (img.width/img.height)); canvas.width = args[6] + 20; canvas.height = args[7] + 20; inputUpload.value = ''; } const r = args[8] || options.radius, x = args[4], y = args[5], w = args[6], h=args[7]; ctx.drawImage(img, ... args); DrawRadius (x, y, w, h, r); Typeof cb === 'function' && cb(); Function drawRadius(x,y,w,h,r) {ctx.beginPath(); ctx.strokeStyle='white'; ctx.fillStyle ='white' ctx.lineWidth= r; console.log(ctx.lineWidth); ctx.moveTo(x+r, y); ctx.arcTo(x+w, y, x+w, y+h, r); ctx.arcTo(x+w, y+h, x, y+h, r); ctx.arcTo(x, y+h, x, y, r); ctx.arcTo(x, y, x+w, y, r); ctx.stroke(); ctx.closePath(); Function downLoad(url){let oA = document.createElement("a"); // Let oA = document.createElement("a"); oA.download = 'avatar'; // Use canvas.todataURL to generate the download address of the image oA. Href = saveAsPNG(); document.body.appendChild(oA); oA.click(); oA.remove(); Function saveAsPNG() {return canvas.todataurl ("image/ PNG "); }Copy the code

The CSS code:

.save-btn, .input-container{ border: none; box-shadow: none; width: 150px; padding: 10px; margin-bottom: 20px; margin-right: 20px; text-align: center; color: #fff; background-color: blue; border-radius: 5px; cursor: pointer; } .save-btn { background-color: #67c23a; } .input-container { background-color: #409eff; position: relative; .file-input { cursor: pointer; position: absolute; display: inline-block; width: 100%; height: 100%; top: 0; left: 0; opacity: 0; }}Copy the code

conclusion

At this point, the function of adding the flag to the avatar is complete, I don’t know if you have learned it? In fact, there are still many areas to be improved, such as the material of the flag. The flag picture I chose is very regular without too much sense of design. Other CANVAS APIS can also be used to make the generated picture more interesting, better looking and more natural. I share today to here, what doubts or suggestions can comment area message to me ~~, finally, I wish our motherland a happy birthday ~, peaceful and prosperous, this prosperous times, as you wish!

Further reading

  • Solid base series: JavaScript variables and data types
  • Intensive reading source code series: Vue DOM asynchronous update and vue.nexttick () principle analysis
  • Solid foundation series: JavaScript class inheritance
  • PostMessage is so useful
  • Use SockJS to achieve webSocket communication in VUE