为图像创建复杂的剪切路径?
Posted
技术标签:
【中文标题】为图像创建复杂的剪切路径?【英文标题】:Creating complex clipping path for image? 【发布时间】:2017-06-04 18:16:09 【问题描述】:我是 fabricjs 的新手(以及一般的 javascript 开发)。我正在“移植”一个遗留的 Flex/Actionscript 项目,并且需要使用户能够为图像创建一个复杂的剪切路径。
我在 Actionscript 中的方法是使用 Actionscript
Graphics
类,使用 BlendMode.ERASE
从黄色基础矩形“擦除”(即呈现擦除的外观),然后使用该组矩形创建位图用作动态创建的最终图像(第 3 步)的 Alpha 通道。
谁能建议我如何在 Fabric 中完成类似的功能?它似乎不支持html5 Canvas Blend modes,虽然我看到它支持图像的剪切路径,但我没有看到如何使用户能够交互地创建剪切路径,而无需进行大量交叉检查以尝试导出点以动态创建新路径。
谢谢!
第 1 步: 用户绘制了一个基本矩形后,拖动选项/alt-key 使他们能够绘制一个矩形(红线),该矩形将从基本矩形中减去。
第 2 步: 基础矩形显示为减法。
第 3 步:基本矩形用于剪切或遮盖基本图像的一部分
第一步
第 2 步
第 3 步
【问题讨论】:
【参考方案1】:威尔塔,
没有简单的方法可以做到这一点。步骤如下:
-
绘制“黄色”矩形
绘制“红色”矩形
使用 PolyBool 之类的裁剪库进行交集和异或运算
将绘制结果转换为组合矩形的剪切路径
剪辑您的图像
我创建了一些快速的fiddle。您必须单击每个按钮才能进行剪辑。如果您不在画布上添加 2 个矩形,它将不会剪辑。这是一个非常简单的例子。为了正常工作,您必须用鼠标绘制矩形(使它们动态)。此外,这个逻辑没有考虑到这些变化(你也必须处理它们): 对于这些用例 Clipping Library 将返回给您 2 组结果,这意味着应该实现不同的逻辑。
没有 jQuery、FabriJs 和 PolyBool 库的实际代码:
var imgURL = 'http://fabricjs.com/lib/pug.jpg';
var clipYellowRect = null;
var clipRedRect = null;
var pug = null;
var canvas = new fabric.Canvas('c');
// insert image into canvas
var pugImg = new Image();
pugImg.onload = function (img)
pug = new fabric.Image(pugImg,
angle: 0,
width: 500,
height: 500,
left: 100,
top: 50,
scaleX: 0.5,
scaleY: 0.5,
clipName: 'pug',
);
canvas.add(pug);
;
pugImg.src = imgURL;
//draw yellow rectangle
$('#btnYellowRect').on('click', function()
clipYellowRect = new fabric.Rect(
originX: 'left',
originY: 'top',
left: 120,
top: 60,
width: 200,
height: 200,
fill: 'rgba(255,255,0,0.5)',
strokeWidth: 0,
selectable: false
);
canvas.add(clipYellowRect);
);
//draw red rectangle
$('#btnRedRect').on('click', function()
clipRedRect = new fabric.Rect(
originX: 'left',
originY: 'top',
left: 90,
top: 120,
width: 100,
height: 100,
strokeWidth: 3,
fill: 'transparent',
stroke: 'rgba(255,0,0,1)', /* use transparent for no fill */
strokeWidth: 0,
selectable: false
);
canvas.add(clipRedRect);
);
//clip
$('#btnClip').on('click', function()
var yellowRectRegion = getRegion(clipYellowRect);
var redRectRegion = getRegion(clipRedRect);
//determine inersection
var intersectResult = PolyBool.intersect(
regions: [yellowRectRegion],
inverted: false
,
regions: [redRectRegion],
inverted: false
);
//generate clipping path
var xorResult = PolyBool.xor(
regions: [yellowRectRegion],
inverted: false
,
regions: intersectResult.regions,
inverted: false
);
clipImage(xorResult.regions[0]);
);
//prepare data for clipping library
function getRegion(rect)
return [[rect.left, rect.top],
[rect.left + rect.width, rect.top],
[rect.left + rect.width, rect.top + rect.height],
[rect.left, rect.top + rect.height]]
function clipImage(points)
//actual clipping
pug.clipTo = function (ctx)
var scaleXTo1 = (1 / pug.scaleX);
var scaleYTo1 = (1 / pug.scaleY);
ctx.save();
var ctxLeft = -( pug.width / 2 );
var ctxTop = -( pug.height / 2 );
ctx.translate( ctxLeft, ctxTop );
ctx.scale(scaleXTo1, scaleYTo1);
ctx.beginPath();
console.log(points)
ctx.moveTo(points[0][0] - pug.oCoords.tl.x, points[0][1] - pug.oCoords.tl.y);
for (var i=1; i < points.length; i++)
ctx.lineTo(points[i][0] - pug.oCoords.tl.x, points[i][1] - pug.oCoords.tl.y);
ctx.closePath();
ctx.restore();
;
clipYellowRect.remove();
clipRedRect.remove();
canvas.renderAll();
希望对你有所帮助。
【讨论】:
太棒了——感谢您的帮助!看起来我将不得不重新考虑一些事情,因为看起来剪切路径在转换剪切的图像时不会缩放或移动。我还是 JS(和 Fabric)的新手,所以我对将其他库与它结合起来有点胆怯。我想我会研究一个 Node 图像库(如pngjs-image
)以动态创建一个带有 alpha 的图像——这是用于 Electron 中的桌面应用程序,因此速度和安全性都可以。以上是关于为图像创建复杂的剪切路径?的主要内容,如果未能解决你的问题,请参考以下文章
使用 iTextSharp 将图像转换为 PDF 保留剪切路径
如何告诉 Ghostscript 在从 eps 到 tiff 的转换中不要使用剪切路径?