#javascript #html #canvas
Вопрос:
Я пытаюсь отобразить текст на холсте, и я пытаюсь сделать так, чтобы размер холста содержал только текст.
Вот код, который отображает строку текста на холсте заданным шрифтом:
(Код взят из большего кода):
// 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>amp;nbsp;</span>
<br/>
проблема в том, что при использовании одного и того же шрифта на холсте и HTML размер не совпадает.
И вы можете рассчитать количество символов в строке так же, как в HTML.
Мой вопрос в том, как я могу сделать размер шрифта таким же, как в HTML? Или, может быть, как я могу рассчитать количество строк при отображении текста на холсте?
Ответ №1:
Как насчет использования 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>amp;nbsp;</span>
<br/>
Комментарии:
1. Спасибо. это решило проблему, но в моем случае мне нужно было использовать
1em
, чтобы я мог изменить размер холста.
Ответ №2:
Вы можете динамически получить шрифт, выбрав случайный элемент абзаца с 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>amp;nbsp;</span>
<br/>
Комментарии:
1. Спасибо, только что понял, что высота символа не совпадает с размером шрифта.