Canvas context.measureText не работает должным образом - PullRequest
1 голос
/ 31 марта 2020

Я пытаюсь добавить фон к предложению и нарисовать его на холсте.

При нажатии на кнопку анимации текстовый фон (красный) неправильно отображается на первом слове. Когда утешенный measuretext () для этого слова, значение намного меньше.

Вот функция, которая анимирует и добавляет текстовый фон.

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();
};

Это JSFiddle

Я хочу, чтобы все предложение получило фон.

1 Ответ

0 голосов
/ 01 апреля 2020

measureText будет использовать текущее установленное свойство font, а также относится к преобразованию текущего контекста (ну, по крайней мере, к его масштабу).

Так что вы должны использовать его с фактическими настройками, которые вы Вы будете рисовать ваш текст, чтобы получить правильную меру:

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>
...