如何高效地在 canvas 上加载和绘制表情符号?
How to load and draw emojis on canvas efficiently?
我想在 html canvas 上打印表情符号。
用图片也可以,但是比较麻烦。有没有更好的方法?
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>
编辑:
好的,我想我的问题被误解了。我可以在 canvas 上将表情符号绘制为图像。我不想那样做。因为我必须将所有表情符号截图并裁剪后再打印到 canvas,这很麻烦。我正在寻找更有效的方法。
如果您不想使用图像,那么我这里有一个纯编码示例。如您所见,它需要更多的编码。
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>
<canvas> 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();
您可以查看结果here。
我认为你的做法是不正确的。要使用 CanvasRenderingContext2D.drawImage()
方法,您需要加载图像,然后修改图像并将其绘制到 canvas 上,因此您还需要调整 canvas 的大小。如果您只使用 Unicode emoji characters.
提供的表情符号呢?
此示例将帮助您通过其 codepoint
值使用表情符号。我们只需要通过 String.fromCodePoint
方法传递一个十六进制代码。此方法 returns 使用指定代码点序列创建的字符串。然后我们可以将该字符串作为表情符号打印到 canvas 中。这种方法将花费大量时间来切割、调整大小和渲染每个表情符号。这是一个简短的例子:
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>
备注
请记住,这可能不适用于所有浏览器,表情符号会根据显示它的操作系统而改变。
您可以使用 fillText
绘制 unicode 表情符号。
您可以从 emojipedia.
复制和粘贴表情符号
我当然不是这方面的专家,所以我不知道这样做是否有很大的缺点,但不管怎样,这里有一些事情需要考虑。
- 这可能不适用于所有浏览器/操作系统。
- 除非您使用自定义字体
,否则 browsers/systems 之间的标准表情符号看起来可能会有所不同
- 您应该确保您的 js 被读取为 UTF-8 才能正常工作。这是 HTML5 的标准配置,因此您可能不必更改任何内容,除非它不适合您。
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>
我想在 html canvas 上打印表情符号。
用图片也可以,但是比较麻烦。有没有更好的方法?
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>
编辑:
好的,我想我的问题被误解了。我可以在 canvas 上将表情符号绘制为图像。我不想那样做。因为我必须将所有表情符号截图并裁剪后再打印到 canvas,这很麻烦。我正在寻找更有效的方法。
如果您不想使用图像,那么我这里有一个纯编码示例。如您所见,它需要更多的编码。
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>
<canvas> 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();
您可以查看结果here。
我认为你的做法是不正确的。要使用 CanvasRenderingContext2D.drawImage()
方法,您需要加载图像,然后修改图像并将其绘制到 canvas 上,因此您还需要调整 canvas 的大小。如果您只使用 Unicode emoji characters.
此示例将帮助您通过其 codepoint
值使用表情符号。我们只需要通过 String.fromCodePoint
方法传递一个十六进制代码。此方法 returns 使用指定代码点序列创建的字符串。然后我们可以将该字符串作为表情符号打印到 canvas 中。这种方法将花费大量时间来切割、调整大小和渲染每个表情符号。这是一个简短的例子:
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>
备注
请记住,这可能不适用于所有浏览器,表情符号会根据显示它的操作系统而改变。
您可以使用 fillText
绘制 unicode 表情符号。
您可以从 emojipedia.
复制和粘贴表情符号我当然不是这方面的专家,所以我不知道这样做是否有很大的缺点,但不管怎样,这里有一些事情需要考虑。
- 这可能不适用于所有浏览器/操作系统。
- 除非您使用自定义字体 ,否则 browsers/systems 之间的标准表情符号看起来可能会有所不同
- 您应该确保您的 js 被读取为 UTF-8 才能正常工作。这是 HTML5 的标准配置,因此您可能不必更改任何内容,除非它不适合您。
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>