Подтвердить что ты не робот

FabricJS предотвращает canvas.clipTo от обрезки canvas.backgroundImage

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

Пример:

введите описание изображения здесь

Вот что происходит на этой фотографии:

  • Изображение наложения на холсте делает футболку естественным образом морщинистым. Это оверлейное изображение в основном прозрачное.
  • Было добавлено фоновое изображение в точной форме футболки, которое должно сделать синюю майку.
  • Добавлена ​​функция canvas.clipTo, которая закрепляет холст в прямоугольной форме
  • Добавлен добавленный пользователем образ (знаменитый мотив Ткань)

Я хочу, чтобы пользовательское изображение (мопс) было ограничено прямоугольной областью.

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

Есть ли простой способ сделать это? Я действительно не хочу добавлять clipTo на каждый отдельный пользовательский слой, а не один аккуратный глобальный clipTo.

Вы можете играть со скриптом JS, отображающим проблему здесь.

4b9b3361

Ответ 1

Одно (sorta hacky) решение: установите фоновое изображение CSS на ваш элемент canvas, как показано в https://jsfiddle.net/qpnvo3cL/

<canvas id="c" width="500" height="500"></canvas>
<style>
  background: url('http://fabricjs.com/assets/jail_cell_bars.png') no-repeat;
</style>
<script>
  var canvas = window._canvas = new fabric.Canvas('c');
  canvas.clipTo = function(ctx) {
      ctx.rect(100,100,100,100);
  }
</script>

Ответ 2

Я пришел сюда с такой же потребностью и в конечном итоге нашел решение для того, над чем я работаю. Может быть, это помогает:

Для путей SVG в функции clipTo вы можете изменить ctx непосредственно перед вызовом render(ctx), и эти изменения применяются за пределами обрезанного пути o. Например:

var clipPath = new fabric.Path("M 10 10 L 100 10 L 100 100 L 10 100", {
  fill: 'rgba(0,0,0,0)',
});

var backgroundColor = "rgba(0,0,0, 0.2)";

var opts = {
  controlsAboveOverlay: true,
  backgroundColor: 'rgb(255,255,255)',
  clipTo: function (ctx) {
    if (typeof backgroundColor !== 'undefined') {
      ctx.fillStyle = backgroundColor;
      ctx.fillRect(0, 0, 300, 150);
    }
    clipPath.render(ctx);
  }
}
var canvas = new fabric.Canvas('c', opts);

canvas.add(new fabric.Rect({
  width: 50,
  height: 50,
  left: 30,
  top: 30,
  fill: 'rgb(255,0,0)'
}));

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

здесь скрипка

Ответ 3

Вы пробовали обрезать ткань Group? Вы могли бы сделать всю рубашку одной полосой. Центральная графика будет одной группой, которую вы кликаете туда, где вы хотите. Белая футболка и синяя накладка, конечно, не будут частью обрезанной группы.

Здесь пример отсечения группы:

var rect = new fabric.Rect({width:100, height: 100, fill: 'red' });
var circle = new fabric.Circle({ radius: 100, fill: 'green' });
var group1 = new fabric.Group([ circle, rect ], { left: 100, top: 100 });
canvas.add(group1);

group1.clipTo = function(ctx) {
    ctx.rect(50,50,200,200);
};

См. этот jsfiddle, который я сделал: https://jsfiddle.net/uvepfag5/4/

Ответ 4

Я считаю, что клип довольно медленный, поэтому я стараюсь использовать globalCompositeOperation для маскировки.

Если вам действительно нужно использовать клип, используйте его вместе с сохранением и восстановлением.

// ctx is canvas context 2d
// pug is the image to be clipped

// draw your background
ctx.save(); // save state
ctx.rect(100,100,100,100); // set the clip area
ctx.clip(); // apply the clip 
ctx.drawImage(pug,x,y); // draw the clipped image
ctx.restore(); // remove the clipping
// draw the other layers.

или вы можете

// draw background
ctx.globalCompositeOperation = "xor";  // set up the mask
ctx.fillRect(100,100,100,100); // draw the mask, could be an image. 
                               // Alpha will effect the amount of masking,
                               // not available with clip 
ctx.globalCompositeOperation = "destination-over";
ctx.drawImage(pug,x,y); // draw the image that is masked                        
ctx.globalCompositeOperation = "source-over";
// draw the stuff that needs to be over everything.

Преимущество составных операций заключается в том, что у вас есть контроль над отсечением на уровне пикселей, в том числе объем отсечения с помощью альфа-значения пикселя