Форма холста внутренняя тень + режим смешивания - PullRequest
0 голосов
/ 13 мая 2018

так что это сводило меня с ума в течение последних нескольких дней.

Я пытаюсь скопировать внутреннюю тень Photoshop в JS с различными режимами наложения, такими как overlay.

Существуют простые способы добавления теней к таким фигурам, как ctx.shadowBlur или ctx.filter = 'drop-shadow(...)', но они генерируют только внешние тени. Вы можете создать внутреннюю тень с помощью некоторой магии композиции с помощью xor, но это оставляет изображение с не ровными краями (я думаю, xor не очень хорошо обрабатывает сглаживание), как в этом примере:

https://jsfiddle.net/89pes8ap/1/

Итак, у меня была другая идея, которая работала, потому что она использовала xor только один раз:

https://jsfiddle.net/3cnwtvyj/

Но, как вы можете видеть, версия overlay по-прежнему не имеет гладких краев.

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

1 Ответ

0 голосов
/ 13 мая 2018

Составные операции работают на альфа-канале и, следовательно, плохо сочетаются с тенями.

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

Одна маленькая вещь, которую я вижу, это то, что вам на самом деле не нужна часть xor, и вы можете заменить ее на путь, состоящий из прямоугольника и дуги, которую вы бы заполнили как 'даже странно'.Это создаст дыру напрямую, уменьшив немного артефактов сглаживания.

drawOP();
drawEvenOdd();



function drawEvenOdd() {
  let canvas = document.getElementById('evenodd');
  canvas.width = 150;
  canvas.height = 200;
  let ctx = canvas.getContext('2d')
  ctx.textAlign = 'center';

  ctx.shadowColor = 'black';
  ctx.shadowBlur = 10 * 2;
  ctx.shadowOffsetY = 5;

  ctx.beginPath();
  ctx.rect(0, 0, canvas.width, canvas.height);
  ctx.arc(100, 100, 50, 0, 2 * Math.PI);
  // will draw an hole
  ctx.fill('evenodd');

  // remove shadow
  ctx.shadowColor = 'transparent';
  ctx.shadowBlur = ctx.shadowOffsetY = 0;

  ctx.globalCompositeOperation = 'destination-out';
  ctx.fill('evenodd');
  ctx.globalCompositeOperation = 'source-over';
  ctx.fillText('evenodd', 100, 180)
}

function drawOP() {
  let canvas = document.getElementById('OP')
  canvas.width = 150;
  canvas.height = 200;
  let ctx = canvas.getContext('2d')
  ctx.textAlign = 'center';

  ctx.fillStyle = 'black'
  ctx.fillRect(0, 0, canvas.width, canvas.height)
  ctx.globalCompositeOperation = 'xor'

  ctx.arc(100, 100, 50, 0, 2 * Math.PI)
  ctx.fill()

  ctx.filter = 'drop-shadow(0 5px 10px black)'
  ctx.drawImage(canvas, 0, 0)
  ctx.filter = 'none';
  ctx.fillText('OP', 100, 180)
}
<canvas id="OP"></canvas>
<canvas id="evenodd"></canvas>
...