Добавить текстовый контур к текущему пути холста - PullRequest
0 голосов
/ 13 июля 2020

Цитата из спецификации 2d контекста холста на strokeText и fillText:

Эти фигуры окрашиваются без влияния на текущий путь

Это имеет смысл и согласуется с strokeRect и fillRect, которые также не влияют на путь. При этом, похоже, не существует эквивалента rect (например, text), который вместо этого просто добавлял бы форму к текущему пути. Это не похоже на техническое ограничение, так как если текст можно обводить, контур должен быть известен в какой-то момент.

Вариант использования будет использовать текстовую форму с clip, isPointInPath, drawFocusIfNeeded или любая другая функция, связанная с путями.

Я не нашел ни одного предложения, ни даже людей, просящих о таком дополнении. Может ли кто-нибудь подтвердить, что в настоящее время это невозможно и что я не пропустил ни одной дискуссии по этому поводу?

Обходной путь

В моем конкретном c случае (клипе) можно было эмулировать поведение с использованием другого холста и значения source-atop для globalCompositeOperation. Пример:

function drawClipped(ctx, drawClipRegion, drawClippedContent) {
  let sourceCanvas = ctx.canvas;
  let alt = document.createElement('canvas');
  alt.width = sourceCanvas.width;
  alt.height = sourceCanvas.width;
  let altCtx = alt.getContext('2d');
  drawClipRegion(altCtx);
  altCtx.globalCompositeOperation = 'source-atop';
  drawClippedContent(altCtx);
  ctx.drawImage(alt, 0, 0);
}

let c = document.querySelector('canvas');
let ctx = c.getContext('2d');

// Background
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, c.width, c.height);
ctx.beginPath();
for (let i = 2; i < c.width; i += 5) {
  ctx.moveTo(i, 0);
  ctx.lineTo(i, c.height);
}
ctx.stroke();

// Text
drawClipped(
  ctx,
  ctx => {
    ctx.font = '900 80px Impact, "Arial Black", sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillStyle = 'white';
    ctx.fillText('TEXT', c.width / 2, c.height / 2);
  },
  ctx => {
    ctx.beginPath();
    for (let i = 2; i < c.height; i += 5) {
      ctx.moveTo(0, i);
      ctx.lineTo(c.width, i);
    }
    ctx.stroke();
  }
);
<canvas width="200" height="200"></canvas>

Это все еще сложнее, чем простой clip, и не решает вариант использования isPointInPath.

...