fabricjs 中的图案填充使渲染变慢

pattern fill in fabricjs makes render slow

我是想在大图上做剪辑蒙版效果 我所做的是使用图片作为图案并将其设置为支持形状的 svg 路径。

在这里查看 jsfiddle(可能有点慢)

http://jsfiddle.net/minzojian/xwurbwvn/

请检查上面的代码

结果还可以,但是当你拖动形状时,你会发现它不平滑,这是为什么?

如果pattern不是最好的解决方案,那么如何制作不规则的clip mask效果呢?

使用较小的图案会使速度更快。如果您在代码中更改此设置:

     patternSourceCanvas.setDimensions({
         width: img.getWidth()*0.6,
         height: img.getHeight()*0.6
     });

你会发现它更流畅了。

1 使用较小的图案

检查更新 fiddle。 http://jsfiddle.net/xwurbwvn/3/

 patternSourceCanvas.setDimensions({
     width: obj.width + 55,
     height: obj.height + 55
 });

一件事是将用于创建图案的 staticCanvas 塑造为您要填充的对象的尺寸。 如您所见,有一个 "plus something" 可以添加到 canvas。 这是因为图案填充移动了路径的一半宽度并再次移动回来(这是为了适应居中变换),所以如果你没有那些额外的宽度,你会看到白色。

有了这个解决方案,它更平滑,不是超级平滑,只是更平滑。

 var canvas = new fabric.Canvas('canvas');

 fabric.loadSVGFromURL('http://sharepage.lunastudio.cn/flower.svg', function (objects, options) {
 var obj = fabric.util.groupSVGElements(objects, options);
 fabric.Image.fromURL('http://sharepage.lunastudio.cn/Penguins.jpg', function (img) {
     var patternSourceCanvas = new fabric.StaticCanvas();
     patternSourceCanvas.setDimensions({
         width: obj.width + 55,
         height: obj.height + 55
     });
     patternSourceCanvas.add(img);

     var s = patternSourceCanvas.getElement();
     var pattern = new fabric.Pattern({
         source: s,
         repeat: 'no-repeat'
     });
     obj.paths.forEach(function(item) {
         item.fill = pattern;
     });
     canvas.add(obj);
 });
 });
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id='canvas' width="400" height="400" style="border:#000 1px solid;"></canvas>

2 在单一形状上使用较小的图案

为了获得更流畅的体验,请像这样优化您的 svg fiddle: http://jsfiddle.net/xwurbwvn/4/

var canvas = new fabric.Canvas('canvas');

 fabric.loadSVGFromURL('data:image/svg+xml;utf8,<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"  width="345.657px" height="345.657px" viewBox="0 0 345.657 345.657" enable-background="new 0 0 345.657 345.657" xml:space="preserve"><g><path fill="#25A296" d="M111.14,35.006c16.891,16.892,0.734,52.632,13.953,88.862c-37.21-12.24-71.971,2.938-88.862-13.953 C21.787,95.472,23.012,78.091,34.272,66.83c6.854-6.854,18.359-7.834,27.907-5.875c-1.959-9.548-0.979-20.809,5.875-27.907 C79.315,21.787,96.696,20.563,111.14,35.006z M31.824,118.973c23.99,0,37.699,36.72,72.705,52.877c-35.006,17.625-48.96,52.877-72.705,52.877 C11.261,224.727,0,211.752,0,195.595c0-9.792,7.344-18.604,15.423-23.745C7.344,166.464,0,157.896,0,148.104 C0,131.947,11.261,118.973,31.824,118.973z M35.007,234.519c16.891-16.892,52.632-0.734,88.862-13.954c-12.24,37.21,2.938,71.972-13.954,88.862 c-14.443,14.443-31.824,13.22-43.085,1.959c-6.854-6.854-7.833-18.36-5.875-27.907c-9.547,1.958-20.808,0.979-27.907-5.875 C21.787,266.342,20.563,248.961,35.007,234.519z M118.973,313.833c0-23.99,36.72-37.699,52.877-72.705c17.625,35.006,52.877,48.96,52.877,72.705 c0,20.563-12.975,31.824-29.132,31.824c-9.792,0-18.604-7.344-23.745-15.422c-5.386,8.078-13.953,15.422-23.745,15.422 C131.947,345.657,118.973,334.396,118.973,313.833z M234.519,310.651c-16.892-16.892-0.734-52.633-13.954-88.862c37.21,12.239,71.972-2.938,88.862,13.953 c14.443,14.443,13.22,31.824,1.959,43.085c-6.854,6.854-18.36,7.833-27.907,5.875c1.958,9.547,0.979,20.808-5.875,27.907 C266.342,323.87,248.962,325.094,234.519,310.651z M313.833,226.685c-23.99,0-37.699-36.72-72.705-52.877c35.006-17.626,48.96-52.877,72.705-52.877 c20.563,0,31.824,12.975,31.824,29.131c0,9.792-7.344,18.605-15.422,23.746c8.078,5.386,15.422,13.953,15.422,23.745 C345.657,213.71,334.396,226.685,313.833,226.685z M310.651,111.139c-16.892,16.892-52.633,0.734-88.862,13.954c12.239-37.21-2.938-71.972,13.953-88.862 c14.443-14.443,31.824-13.22,43.085-1.959c6.854,6.854,7.833,18.36,5.875,27.907c9.547-1.958,20.808-0.979,27.907,5.875 C323.87,79.314,325.094,96.695,310.651,111.139z M120.687,31.823c0,23.991,36.72,39.413,52.877,74.42c17.625-35.007,52.876-50.674,52.876-74.42 C226.439,11.261,213.466,0,197.309,0c-9.792,0-18.604,7.344-23.745,15.422C168.178,7.344,159.609,0,149.817,0 C133.661,0,120.687,11.261,120.687,31.823z" /></g></svg>', function (objects, options) {
 var obj = fabric.util.groupSVGElements(objects, options);
 fabric.Image.fromURL('http://sharepage.lunastudio.cn/Penguins.jpg', function (img) {
     var patternSourceCanvas = new fabric.StaticCanvas();
     patternSourceCanvas.add(img);
     patternSourceCanvas.renderAll();
     patternSourceCanvas.setDimensions({
         width: obj.getWidth() * 1.5,
         height: obj.getHeight() * 1.5
     });
     var s = patternSourceCanvas.getElement();

     var pattern = new fabric.Pattern({
         source: s,
         repeat: 'no-repeat'
     });
     obj.paths.forEach(function (item) {
         item.fill = pattern;
     });
     canvas.add(obj);
     canvas.renderAll();
 });

 });
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id='canvas' width="400" height="400" style="border:#000 1px solid;"></canvas>

此处 SVG 被创建为单一路径,因此 fabric 只需执行一个 patternFill 而不是其中的 8 个(每个壁炉一个)

3 使用替代品

你问的制作剪辑路径的最佳方法是什么。

嗯,这取决于你剪的是什么。

你基本上有3种方式: 形状的图案填充(不是剪裁) 用路径裁剪图像 使用 globalCompositeOperation

要剪辑图像,你必须有一个单一的形状,而不是其中的 8 个,所以基本上是我的第二个例子:

var canvas = new fabric.Canvas('canvas');

 fabric.loadSVGFromURL('data:image/svg+xml;utf8,<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"  width="345.657px" height="345.657px" viewBox="0 0 345.657 345.657" enable-background="new 0 0 345.657 345.657" xml:space="preserve"><g><path fill="#25A296" d="M111.14,35.006c16.891,16.892,0.734,52.632,13.953,88.862c-37.21-12.24-71.971,2.938-88.862-13.953 C21.787,95.472,23.012,78.091,34.272,66.83c6.854-6.854,18.359-7.834,27.907-5.875c-1.959-9.548-0.979-20.809,5.875-27.907 C79.315,21.787,96.696,20.563,111.14,35.006z M31.824,118.973c23.99,0,37.699,36.72,72.705,52.877c-35.006,17.625-48.96,52.877-72.705,52.877 C11.261,224.727,0,211.752,0,195.595c0-9.792,7.344-18.604,15.423-23.745C7.344,166.464,0,157.896,0,148.104 C0,131.947,11.261,118.973,31.824,118.973z M35.007,234.519c16.891-16.892,52.632-0.734,88.862-13.954c-12.24,37.21,2.938,71.972-13.954,88.862 c-14.443,14.443-31.824,13.22-43.085,1.959c-6.854-6.854-7.833-18.36-5.875-27.907c-9.547,1.958-20.808,0.979-27.907-5.875 C21.787,266.342,20.563,248.961,35.007,234.519z M118.973,313.833c0-23.99,36.72-37.699,52.877-72.705c17.625,35.006,52.877,48.96,52.877,72.705 c0,20.563-12.975,31.824-29.132,31.824c-9.792,0-18.604-7.344-23.745-15.422c-5.386,8.078-13.953,15.422-23.745,15.422 C131.947,345.657,118.973,334.396,118.973,313.833z M234.519,310.651c-16.892-16.892-0.734-52.633-13.954-88.862c37.21,12.239,71.972-2.938,88.862,13.953 c14.443,14.443,13.22,31.824,1.959,43.085c-6.854,6.854-18.36,7.833-27.907,5.875c1.958,9.547,0.979,20.808-5.875,27.907 C266.342,323.87,248.962,325.094,234.519,310.651z M313.833,226.685c-23.99,0-37.699-36.72-72.705-52.877c35.006-17.626,48.96-52.877,72.705-52.877 c20.563,0,31.824,12.975,31.824,29.131c0,9.792-7.344,18.605-15.422,23.746c8.078,5.386,15.422,13.953,15.422,23.745 C345.657,213.71,334.396,226.685,313.833,226.685z M310.651,111.139c-16.892,16.892-52.633,0.734-88.862,13.954c12.239-37.21-2.938-71.972,13.953-88.862 c14.443-14.443,31.824-13.22,43.085-1.959c6.854,6.854,7.833,18.36,5.875,27.907c9.547-1.958,20.808-0.979,27.907,5.875 C323.87,79.314,325.094,96.695,310.651,111.139z M120.687,31.823c0,23.991,36.72,39.413,52.877,74.42c17.625-35.007,52.876-50.674,52.876-74.42 C226.439,11.261,213.466,0,197.309,0c-9.792,0-18.604,7.344-23.745,15.422C168.178,7.344,159.609,0,149.817,0 C133.661,0,120.687,11.261,120.687,31.823z" /></g></svg>', function (objects, options) {
 fabric.Image.fromURL('http://sharepage.lunastudio.cn/Penguins.jpg', function (img) {
     img.clipTo = function(ctx) {
       objects[0]._render(ctx);
     }
     img.scale(0.1);
     canvas.add(img);
     canvas.renderAll();
 });

 });
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id='canvas' width="400" height="400" style="border:#000 1px solid;"></canvas>

全局复合操作不同: 您必须在 svg(第一个对象)和图像(第二个对象)之间创建一个组,然后将 svg 的 globalCompositeOperation 设置为 "destination-in".