我遇到FabricJS对象的问题。我想创建一个剪辑区域(svg对象),它将剪切加载的图像。
我在加载的图像上使用clipTo方法将其传递到剪切区域形状对象(SVG),但它不起作用,因为SVG不是FabricJS意义上的形状对象。有没有办法将加载的SVG转换为FabricJS形状,如Polygon或Rect?
如果我将使用它几乎可行:
globalCompositeOperation = 'source-atop'
在加载的图像上(并删除clipTo函数),但是如果我将移动/调整大小/旋转图像,它会与主剪切区域(最大矩形)的边界重叠。图像不应与灰色矩形之外的其他对象交互,尤其是对于主剪切区域。 也许通过使用globalCompositeOperation可以实现这一目标吗?
我将非常感谢任何提示。
这是我的问题的JSFiddle: https://jsfiddle.net/6nfdr1ng/
这里几乎正常工作的版本(带有source-atop): https://jsfiddle.net/ud9nev1g/
<input type="file" id="image"><br>
<canvas id="canvas" width="530" height="600"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<script type="text/javascript">
var canvas = new fabric.Canvas('canvas', {
'selection': false
});
/**
* loading man clipping rect
*/
var clippingRect = new fabric.Rect({
width: 185,
height: 400,
fill: 'transparent',
stroke: 1,
opacity: 1,
hasBorders: false,
hasControls: false,
hasRotatingPoint: false,
selectable: false,
preserveObjectStacking: true,
objectCaching: false
});
canvas.add(clippingRect);
canvas.renderAll();
/**
* loading shape which should be another clipping area for loaded image
*/
var svgString = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 63.7 63.7"><defs><style>.cls-1{fill:#79797a;fill-rule:evenodd;}</style></defs><title>Asset 4</title><g id="Layer_2" data-name="Layer 2"><g id="kwadrat"><path class="cls-1" d="M0,0H63.7V63.7H0Z"/></g></g></svg>';
var retinaScalling = canvas.getRetinaScaling();
fabric.loadSVGFromString(svgString, function (objects, options) {
var shapeObject = fabric.util.groupSVGElements(objects, options);
shapeObject.scaleX = 0.5;
shapeObject.scaleY = 0.5;
shapeObject.set('id', 'shape');
shapeObject.scaleToWidth(clippingRect.getWidth());
shapeObject.setCoords();
shapeObject.clipTo = function (ctx) {
ctx.save();
ctx.setTransform(retinaScalling, 0, 0, retinaScalling, 0, 0);
clippingRect.render(ctx);
ctx.restore();
};
shapeObject.center();
shapeObject.setCoords();
canvas.setActiveObject(shapeObject);
canvas.add(shapeObject);
canvas.renderAll();
});
/**
* loading image
*/
document.getElementById('image').onchange = function (e) {
var reader = new FileReader();
var clippingAreaShape = canvas.getActiveObject();
reader.onload = function (event) {
var img = new Image();
img.onload = function () {
var shapeImageObject = new fabric.Image(img, {
objectCaching: false,
hasControls: true,
selectable: true
});
shapeImageObject.scaleToHeight(clippingAreaShape.getWidth());
shapeImageObject.set('id', 'shape-image');
shapeImageObject.set({
left: clippingAreaShape.left,
top: clippingAreaShape.top
});
shapeImageObject.clipTo = function (ctx) {
ctx.save();
ctx.setTransform(retinaScalling, 0, 0, retinaScalling, 0, 0);
clippingAreaShape.render(ctx);
ctx.restore();
};
// shapeImageObject.globalCompositeOperation = 'source-atop';
canvas.add(shapeImageObject);
canvas.renderAll();
canvas.setActiveObject(shapeImageObject);
shapeImageObject.setCoords();
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
</script>
答案 0 :(得分:1)
我通过将SVG形状组合成一条路径(没有任何其他svg对象的任何多边形)解决了我的问题,然后我将svg coords传递给fabircJS路径。有效的SVG坐标看起来像“M0,0H63.7V63.7H0Z”
fabric.loadSVGFromURL('object.svg', function (objects, options) {
let img1 = new fabric.Path(objects[0].d, {
fill: '#333',
opacity: 1,
hasBorders: true,
hasControls: true,
hasRotatingPoint: true,
selectable: true,
preserveObjectStacking: true,
objectCaching: false,
});
}
我希望它会帮助别人:)