How to load and draw emojis on canvas efficiently?

你说的曾经没有我的故事 提交于 2021-02-08 21:47:30

问题


I would like to print an emoji on html canvas.

It can be done using images, but it is cumbersome. Is there a better way?

const canvas = document.querySelector("#canvas");
const contex = canvas.getContext("2d");

var img = new Image();
img.src = "emoji.jpg";
img.addEventListener(
  "load",
  () => {
    context.drawImage(img, 0, 0, 200, 200);
  }
);
img.src = "img.jpg";
#canvas {
  background: red;
}
<canvas id="canvas"></canvas>

Edit:

Okey, I think my question is misunderstood. I am able to draw emoji as an image on canvas. I don't want to do that. Because I have to screenshot all the emojis and crop them before printing them on canvas, which is cumbersome. I am looking for a more efficient way.


回答1:


You can use fillText to draw the unicode emoji.

You can copy and paste the emojis from emojipedia.

I'm certainly not an expert on this so I don't know if there's big drawbacks to doing it this way, but here are some things to consider regardless.

  1. This might not work on all browsers / operating systems.
  2. The standard emoji will likely look different between browsers/systems unless you use a custom font
  3. You should make sure your js is being read as UTF-8 for this to work. This is standard with HTML5, so you probably don't have to change anything unless it doesn't work for you.

const canvas = document.querySelector("#canvas");
const contex = canvas.getContext("2d");

// The size of the emoji is set with the font
contex.font = '100px serif'
// use these alignment properties for "better" positioning
contex.textAlign = "center"; 
contex.textBaseline = "middle"; 
// draw the emoji
contex.fillText('😜😂😍', canvas.width / 2, canvas.height / 2)
#canvas {
  background: #ccc;
}
<canvas id="canvas"></canvas>



回答2:


If you don't want to use images then I have an example here that is pure coding. As you can see it requires way more coding tho.

index.html

<!doctype html>
<html lang="en">
<head>
<title>Smiley Face</title>
<meta charset="utf-8" />

   <link rel="stylesheet" href="css/smiley.css" >

</head>
<body>
    <canvas width="600" height="600" id="smiley">
        <p>You need canvas!</p>
        <p>This example requires a browser that supports the
        <a href="http://www.w3.org/html/wg/html5/">HTML5</a> 
        &lt;canvas&gt; feature.</p>
    </canvas>
    <script src="js/smiley.js"></script>
</body>
</html>

smiley.js

//smileyView Object literal
class smileyComponent {
  constructor() {
    //initialise window, cv & ctx, drawSmiley & call drawsmiley
    this._window = this;
    this._cv = document.getElementById('smiley');
    this._ctx = this._cv.getContext('2d');
    this.drawSmiley();
  }
  //getters
  get window() {
    return this._window;
  }
  get cv() {
    return this._cv;
  }
  get ctx() {
    return this._ctx;
  }

  drawArc(x, y, radius, startAngle, endAngle, clockwise) {
    this._ctx.arc(x, y, radius, startAngle, endAngle, clockwise);
  }
  drawLine(xs, ys, xe, ye) {
    this._ctx.moveTo(xs, ys);
    this._ctx.lineTo(xe, ye);
  }
  drawSmiley() {
    //initialise lineWidth & fillStyle
    this._ctx.fillStyle = "yellow";
    this._ctx.strokeStyle = "black";
    this._ctx.lineWidth = 5;

    //head
    this._ctx.beginPath();
    this.drawArc(300,300,200,smileyComponent.degreesToRadians(0),smileyComponent.degreesToRadians(360),true);
    this._ctx.fill();

    //left eye
    this._ctx.beginPath();
    this.drawArc(200,200,50,smileyComponent.degreesToRadians(0),smileyComponent.degreesToRadians(360),true);
    this._ctx.fillStyle = "black";
    this._ctx.fill();
    this._ctx.beginPath();
    this.drawArc(220,220,25,smileyComponent.degreesToRadians(0),smileyComponent.degreesToRadians(360),true);
    this._ctx.fillStyle = "white";
    this._ctx.fill();


    //right eye
    this._ctx.beginPath();
    this.drawArc(400,200,50,smileyComponent.degreesToRadians(0),smileyComponent.degreesToRadians(360),true);
    this._ctx.fillStyle = "black";
    this._ctx.fill();
    this._ctx.beginPath();
    this.drawArc(420,220,25,smileyComponent.degreesToRadians(0),smileyComponent.degreesToRadians(360),true);
    this._ctx.fillStyle = "white";
    this._ctx.fill();

    //nose
    this._ctx.beginPath();
    this.drawLine(300,350,300,250);
    this._ctx.stroke();


    //smile
    this._ctx.beginPath();
    this.drawArc(300,300,150,smileyComponent.degreesToRadians(160),smileyComponent.degreesToRadians(380),true);
    this._ctx.stroke();
  }

  static degreesToRadians(degrees) {
    return degrees * Math.PI / 180;
  }
}
window.onload = () => new smileyComponent();

You can check the result here.




回答3:


I think your approach it is not the correct. To use the CanvasRenderingContext2D.drawImage() method you need to load an image then you will modify the image and to draw it onto the canvas, so you also need to resize the canvas. What about if you just use the emojis provided by Unicode emoji characters.

This example will help you to use an emoji via its codepoint value. We just need to pass a hexcode through the String.fromCodePoint method. This method returns a string created by using the specified sequence of code points. Then we can print that string into the canvas as an emoji. This approache will have a lot of time chopping, resizing and rendering each emoji. This is an short example:

let canvas1, canvas2, ctx1, ctx2;

let emoji = [];

let emo,
  size = 80,
  rad = 20;

let emojis = [
        0x1F600, 0x1F601, 0x1F603, 0x1F603, 0x1F604, 0x1F605, 0x1F606,
        0x1F607, 0x1F609, 0x1F60A, 0x1F642, 0x1F643, 0x1F355, 0x1F354,
];

for (let i = 0; i < 2; i++) {
  emoji.push({
    x: size,
    y: size,
    src: getEmoji()
  });
}


window.onload = function() {
  canvas1 = document.getElementById('canvas-01');
  ctx1 = canvas1.getContext('2d');
  loadEmoji(canvas1, ctx1, 0);


  canvas2 = document.getElementById('canvas-02');
  ctx2 = canvas2.getContext('2d');
  loadEmoji(canvas2, ctx2, 1);
}


function loadEmoji(canvas, ctx, index) {
  // Use the intrinsic size of image in CSS pixels for the canvas element
  canvas.width = w = size * 2.5;
  canvas.height = h = size * 2.5;

  ctx.font = size * 2 + 'px Arial';
  ctx.textBaseline = 'middle'; 
  ctx.textAlign = 'center';

  emo = emoji[index];
  emo.x = w/2;
  emo.y = h-size-10;

  ctx.fillText(emo.src, emo.x, emo.y);
}

function getEmoji() {
  let len = emojis.length;

  let emos = Math.floor(Math.random() * len);
  return String.fromCodePoint(emojis[emos]);
}
#canvas-01,
#canvas-02 {
  background: red;
}
<canvas id="canvas-01"></canvas>
<canvas id="canvas-02"></canvas>

Note

Remember that this might not work on all browsers and the emojis will change according to the operating system where it's been displayed.



来源:https://stackoverflow.com/questions/56312457/how-to-load-and-draw-emojis-on-canvas-efficiently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!