FabricJS предотвращает canvas.clipTo от обрезки canvas.backgroundImage
Я хочу установить глобальный clipTo
в моем холсте, наполненном Fabric, который повлияет на все слои, добавленные пользователем. Я хочу фоновое изображение и оверлейное изображение, которые не подвержены этой маске клипа.
Пример:
![введите описание изображения здесь]()
Вот что происходит на этой фотографии:
- Изображение наложения на холсте делает футболку естественным образом морщинистым. Это оверлейное изображение в основном прозрачное.
- Было добавлено фоновое изображение в точной форме футболки, которое должно сделать синюю майку.
- Добавлена функция
canvas.clipTo
, которая закрепляет холст в прямоугольной форме
- Добавлен добавленный пользователем образ (знаменитый мотив Ткань)
Я хочу, чтобы пользовательское изображение (мопс) было ограничено прямоугольной областью.
Я делаю не изображение фонового изображения (форма синей футболки), на которое влияет область клипа.
Есть ли простой способ сделать это? Я действительно не хочу добавлять clipTo
на каждый отдельный пользовательский слой, а не один аккуратный глобальный clipTo
.
Вы можете играть со скриптом JS, отображающим проблему здесь.
Ответы
Ответ 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.
Преимущество составных операций заключается в том, что у вас есть контроль над отсечением на уровне пикселей, в том числе объем отсечения с помощью альфа-значения пикселя