Unicode To PNG
下面将一个代表7筒麻将牌Unicode字符转换为一个编码为Base64字符串的URL,并向一个Image的src赋值。
ctx.font = '130px Helvetica';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = '#BBB';
ctx.fillText('\u{1F01F}', canvas.clientWidth / 2, canvas.clientHeight / 2);
const dataURL = canvas.toDataURL("image/png", 1);
console.log(dataURL);
let img = new Image();
img.src = dataURL;
let lastChild = document.body.lastChild;
if (canvas !== lastChild) {
lastChild.remove();
}
document.body.appendChild(img);
body {
display: flex;
gap: 1em;
}
canvas {
border: 1px solid gray;
width: 200px;
height: 200px;
}
img {
width: 200px;
height: 200px;
border: 1px solid gray;
}
HTMLCanvasElement的toDataURL方法,目前只支持image/png
及image/jpeg
的MIME Type。
指定Canvas的大小
function initCanvas(width, height) {
canvas.style.width = width;
canvas.style.height = height;
canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
ctx = canvas.getContext('2d');
ctx.scale(devicePixelRatio, devicePixelRatio);
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
}
function drawCharInCanvas(char, font, fillColor) {
ctx.font = font;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = fillColor;
ctx.fillText(char, canvas.clientWidth / 2, canvas.clientHeight / 2);
}
initCanvas('150px', '200px');
drawCharInCanvas('\u{1F01F}', '130px Helvetica', '#BBB');
canvas {
border: 1px solid gray;
}
initCanvas很重要,它在根据用户的要求来定制canvas的大小的前提下,又可享受高清分辨率的重要保障。
求出字符的边框
function initCanvas(width, height) {
canvas.style.width = width;
canvas.style.height = height;
canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
ctx = canvas.getContext('2d');
ctx.scale(devicePixelRatio, devicePixelRatio);
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
}
function drawCharInCanvas(char, font, fillColor) {
ctx.font = font;
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillStyle = fillColor;
ctx.fillText(char, 0, 0);
const metrics = ctx.measureText(char);
let width = metrics.width;
let height = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
ctx.strokeStyle = 'cyan';
ctx.strokeRect(0, 0, width, height);
}
initCanvas('150px', '200px');
drawCharInCanvas('\u{1F01F}', '130px Monospace', '#BBB');
canvas {
border: 1px solid gray;
}
根据不同的字体,每个字符的实际大小、上下左右的偏移值都不一样,代表7筒的这个字符稍微往下偏移了一点(这属于该Unicode字符的设计缺陷),但所求出的外围方框基本上均将其包含在内了。可换成其他字符及字体查看不同的效果。
在Canvas中居中绘制
function initCanvas(width, height) {
canvas.style.width = width;
canvas.style.height = height;
canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
ctx = canvas.getContext('2d');
ctx.scale(devicePixelRatio, devicePixelRatio);
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
}
function drawCharInCanvas(char, font, fillColor) {
ctx.font = font;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const metrics = ctx.measureText(char);
let width = metrics.width;
let height = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
ctx.strokeStyle = 'cyan';
ctx.strokeRect((canvas.clientWidth - width) / 2, (canvas.clientHeight - height) / 2, width, height);
ctx.fillStyle = fillColor;
ctx.fillText(char, canvas.clientWidth / 2, canvas.clientHeight / 2);
}
initCanvas('150px', '200px');
drawCharInCanvas('\u{1F01F}', '130px Monospace', '#BBB');
canvas {
border: 1px solid gray;
}
这样,在指定了canvas的大小后,我们就可以微调其字体大小来达到最佳效果。下面将扑克牌中的大鬼字符转换为PNG图像。
function initCanvas(width, height) {
canvas.style.width = width;
canvas.style.height = height;
canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
ctx = canvas.getContext('2d');
ctx.scale(devicePixelRatio, devicePixelRatio);
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
}
function drawCharInCanvas(char, font, fillColor) {
ctx.font = font;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const metrics = ctx.measureText(char);
let width = metrics.width;
let height = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
ctx.fillStyle = fillColor;
ctx.fillText(char, canvas.clientWidth / 2, canvas.clientHeight / 2);
}
function drawImage() {
const dataURL = canvas.toDataURL("image/png", 1);
let img = new Image();
img.src = dataURL;
img.width = canvas.clientWidth;
img.height = canvas.clientHeight;
let lastChild = document.body.lastChild;
if (canvas !== lastChild) {
lastChild.remove();
}
document.body.appendChild(img);
}
initCanvas('150px', '200px');
drawCharInCanvas('\u{1F0CF}', '130px Monospace', '#BBB');
drawImage();
body {
display: flex;
gap: 1em;
}
canvas, img {
border: 1px solid gray;
}
通过这种方式,我们可将任意Unicode字符无损耗地转换个任意大小的PNG图像,并且可以精细调节图像的颜色、图像的位置,我们可用的图像来源又多了许多,从而有效解决了图像资源匮乏的问题。
访问本站的Unicode查询表,找到中意的字符后,将其Unicode编码粘帖至上面代码中,即可生成相应的PNG图像,对其按右边即可下载使用。
要想了解如何居中源图像后再绘制,可参见getImageData。