I am trying to add background to a sentence and draw it on canvas.
On click on animate button, the text-background (red) drawn improperly on first word. When consoled measuretext() on that word, the value is way lesser.
Here is the function which animates and add text background.
const fillMixedText = (canv, ctx, args, x, y) => {
let defaultFillStyle = "black";
let defaultFont = "600 54px Arial";
ctx.save();
let i = 0;
args.forEach(({ text, fillStyle, font }) => {
// console.log("x",x);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.textBaseline = "top";
ctx.fillStyle = "red";
console.log(x,text,ctx.measureText(text).width)
ctx.fillRect(x, y, ctx.measureText(text).width , 70);
// console.log(text, ctx.measureText(text).width);
ctx.fillStyle = fillStyle || defaultFillStyle;
ctx.font = defaultFont;
ctx.fillText(text, x, y);
x += ctx.measureText(text).width;
i++;
});
ctx.restore();
};
This is the JSFiddle
I want the whole sentence to get a background.
measureText
will use the currently set font
property, and is also relative to the current context's transform (well, its scale at least).
So you must use it with the actual settings you'll be drawing your text with to get a correct measure:
var canvas = document.getElementById("canvas-1");
var ctx = canvas.getContext("2d");
var args = [
{text: "constantinople "},
{text: "is "},
{text: "a "},
{text: "city. "}
];
document.getElementById('click').onclick = function() {
var startTime = new Date().getTime();
var interval = setInterval(function() {
if (new Date().getTime() - startTime > 2000) {
clearInterval(interval);
}
ctx.clearRect(0, 0, canvas.width, canvas.width);
animateText();
}, 33);
}
var interval;
let distance = 0;
let speed = 15;
function animateText() {
// interval = setInterval(function() {
distance = distance + speed;
textAnimation(
ctx,
canvas,
args, -200,
canvas.height / 2,
distance
); // console.log(thiscanvas.width/16)
}
textAnimation = (ctx, canv, args, x, y, distance) => {
if (distance >= 280) {
distance = 0;
// clearInterval(interval);
x = canv.width / 16;
}
fillMixedText(canv, ctx, args, x + distance, y);
};
const fillMixedText = (canv, ctx, args, x, y) => {
let defaultFillStyle = "black";
let defaultFont = "600 54px Arial";
ctx.save();
let i = 0;
args.forEach(({ text, fillStyle, font }) => {
// console.log("x",x);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.textBaseline = "top";
ctx.fillStyle = "red";
// set the font first
ctx.font = defaultFont;
// now it's correct
ctx.fillRect(x, y, ctx.measureText(text).width, 70);
ctx.fillStyle = fillStyle || defaultFillStyle;
ctx.fillText(text, x, y);
x += ctx.measureText(text).width;
i++;
});
ctx.restore();
};
canvas {
border: 2px solid black;
width: 700px;
height: 400px;
margin-left: 30px;
margin-top: 10px;
}
<canvas id="canvas-1" width="1280px" height="720px"></canvas>
<button id="click">animate</button>