如何使Canvas字体大小与html字体大小匹配



我试图在画布上呈现文本,并试图使画布的大小仅包含文本。

以下是用给定字体在画布上呈现文本行的代码:

(代码取自较大的代码(:

// Renderer base class is used to calculate width and height of the terminal
// based on char size
class Renderer {
constructor(render, { color = '#cccccc', background = 'black', char = { width: 7, height: 14 }} = {}) {
this._options = {
background,
color,
char
};
this._render = render;
}
option(arg, value) {
if (typeof arg === 'object') {
Object.assign(this._options, arg);
} else if (typeof value === 'undefined') {
return this._options[arg];
} else {
this._options[arg] = value;
}
}
render() {
const char = this.option('char');
const lines = this._render();
const max = Math.max(...lines.map(l => l.length));
const width = max * char.width;
const size = char.height;
const height = lines.length * size;
this.clear({ width, height, size });
for (let line = 0; line < lines.length; ++line) {
const text = lines[line];
this.line(text, 0, size * line);
}
}
line(text, x, y) {
throw new Error('Renderer::line invalid Invocation');
}
clear({ width, height, size } = {}) { }
}
// child class is used to render the text calculated in base class on a Canvas
class CanvasRenderer extends Renderer {
constructor(render, options = {}) {
super(render, options);
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
}
clear({ width, height, size }) {
this.canvas.width = width;
this.canvas.height = height;
this.ctx.fillStyle = this.option('background');
this.ctx.fillRect(0, 0, width, height);
this.ctx.font = `${size}px monospace`;
this.ctx.textBaseline = 'hanging';
this.ctx.fillStyle = this.option('color');
}
line(text, x, y) {
this.ctx.fillText(text, x, y);
}
}

var span = document.getElementsByTagName('span')[0];
span.getBoundingClientRect();

var renderer = new CanvasRenderer(() => (["Hello", "World"]), {
background: 'white',
color: 'black',
char: span.getBoundingClientRect()
});
document.body.appendChild(renderer.canvas);
renderer.render();
html, body {
font-family: monospace;
}
<p>Some Text</p>
<span>&nbsp;</span>
<br/>

问题是画布和HTML上的字体相同,大小不匹配。您可以像在HTML中一样计算每行的字符数。

我的问题是如何使字体大小与HTML中的相同?或者,在画布上渲染文本时,我如何计算每行的数字?

使用this.ctx.font = '1rem monospace';怎么样?

// Renderer base class is used to calculate width and height of the terminal
// based on char size
class Renderer {
constructor(render, { color = '#cccccc', background = 'black', char = { width: 7, height: 14 }} = {}) {
this._options = {
background,
color,
char
};
this._render = render;
}
option(arg, value) {
if (typeof arg === 'object') {
Object.assign(this._options, arg);
} else if (typeof value === 'undefined') {
return this._options[arg];
} else {
this._options[arg] = value;
}
}
render() {
const char = this.option('char');
const lines = this._render();
const max = Math.max(...lines.map(l => l.length));
const width = max * char.width;
const size = char.height;
const height = lines.length * size;
this.clear({ width, height, size });
for (let line = 0; line < lines.length; ++line) {
const text = lines[line];
this.line(text, 0, size * line);
}
}
line(text, x, y) {
throw new Error('Renderer::line invalid Invocation');
}
clear({ width, height, size } = {}) { }
}
// child class is used to render the text calculated in base class on a Canvas
class CanvasRenderer extends Renderer {
constructor(render, options = {}) {
super(render, options);
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
}
clear({ width, height, size }) {
this.canvas.width = width;
this.canvas.height = height;
this.ctx.fillStyle = this.option('background');
this.ctx.fillRect(0, 0, width, height);
this.ctx.font = `1rem monospace`;
this.ctx.textBaseline = 'hanging';
this.ctx.fillStyle = this.option('color');
}
line(text, x, y) {
this.ctx.fillText(text, x, y);
}
}

var span = document.getElementsByTagName('span')[0];
span.getBoundingClientRect();

var renderer = new CanvasRenderer(() => (["Hello", "World"]), {
background: 'white',
color: 'black',
char: span.getBoundingClientRect()
});
document.body.appendChild(renderer.canvas);
renderer.render();
html, body {
font-family: monospace;
}
<p>Some Text</p>
<span>&nbsp;</span>
<br/>

您可以通过选择一个带有window.getComputedStyle(document.querySelector('p')).getPropertyValue("font"):

// Renderer base class is used to calculate width and height of the terminal
// based on char size
class Renderer {
constructor(render, { color = '#cccccc', background = 'black', char = { width: 7, height: 14 }} = {}) {
this._options = {
background,
color,
char
};
this._render = render;
}
option(arg, value) {
if (typeof arg === 'object') {
Object.assign(this._options, arg);
} else if (typeof value === 'undefined') {
return this._options[arg];
} else {
this._options[arg] = value;
}
}
render() {
const char = this.option('char');
const lines = this._render();
const max = Math.max(...lines.map(l => l.length));
const width = max * char.width;
const size = char.height;
const height = lines.length * size;
this.clear({ width, height, size });
for (let line = 0; line < lines.length; ++line) {
const text = lines[line];
this.line(text, 0, size * line);
}
}
line(text, x, y) {
throw new Error('Renderer::line invalid Invocation');
}
clear({ width, height, size } = {}) { }
}
// child class is used to render the text calculated in base class on a Canvas
class CanvasRenderer extends Renderer {
constructor(render, options = {}) {
super(render, options);
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
}
clear({ width, height, size }) {
this.canvas.width = width;
this.canvas.height = height;
this.ctx.fillStyle = this.option('background');
this.ctx.fillRect(0, 0, width, height);
this.ctx.font = window.getComputedStyle(document.querySelector('p')).getPropertyValue("font");
this.ctx.textBaseline = 'hanging';
this.ctx.fillStyle = this.option('color');
}
line(text, x, y) {
this.ctx.fillText(text, x, y);
}
}

var span = document.getElementsByTagName('span')[0];
span.getBoundingClientRect();

var renderer = new CanvasRenderer(() => (["Hello", "World"]), {
background: 'white',
color: 'black',
char: span.getBoundingClientRect()
});
document.body.appendChild(renderer.canvas);
renderer.render();
html, body {
font-family: monospace;
}
<p>Some Text</p>
<span>&nbsp;</span>
<br/>

最新更新