Fabric.js fillRule - evenodd(减去形状)

时间:2016-11-08 17:09:54

标签: canvas polygon fabricjs fill

我正在尝试使用fillRule =' evenodd'在多边形中打洞。在fabric.js中

globalCompositeOperation对我来说不起作用,因为我需要在多边形孔中看到形状 like this

这是我的代码:fiddle

有两个例子:

  • Fabric.js 2个多边形(不起作用)
  • 原生html5 canvas 2多边形(作品)

当我设置fillRule:' evenodd'对于fabric.js多边形,它将转到结构功能,它将上下文填充到“eveneodd”

_renderFill: function(ctx) {
   ...
      if (this.fillRule === 'evenodd') {
        ctx.fill('evenodd');
      }
      ...
      ctx.restore();
    },

但它仍然没有用。 请,让我知道如何使用' enevodd' if fabric.js

1 个答案:

答案 0 :(得分:1)

' evenodd' 填充规则适用于一个结构对象。即使使用组对象,也不能将此规则用于单独的对象并将它们组合在一起。在单独渲染形状的组中,这意味着每个对象都会调用:

context.fill(); 

context.fill('evenodd')

对于多个对象使用' evenodd' 规则是Fabric.js中缺少的功能。

以下是一些解决方法,如何使用' evenodd'一个主题多边形和多个减去多边形的规则。

步骤:

  1. 将减去的多边形的最近点找到主题多边形的最后一个点。
  2. 按最近索引
  3. 对减去的多边形数组进行排序
  4. 将主题和减去的多边形合并为一个。
  5. 这是fiddle

    此代码需要改进。它给出了如何使用“偶数”在多边形上打孔的想法。规则。

    
    
    var canvas = new fabric.Canvas('c', { selection: false });
    var polygons = [];
    
    var subjectPoly = [{x:30,y:10}, {x:300,y:50}, {x:20,y:290}];
    var subtractPoly1 = [{x:50,y:50}, {x:200,y:140}, {x:220,y:40}];
    var subtractPoly2 = [{x:10,y:10}, {x:300,y:200}, {x:60,y:150}];
    var subtractPoly = [];
    subtractPoly.push(subtractPoly1);
    subtractPoly.push(subtractPoly2);
    
     var result = combinePolygonArrays(subjectPoly,sortPolygonArray(subtractPoly, closetPoint(subjectPoly[0],subtractPoly)));
      var poly1 = new fabric.Polygon(result, {
      	 fillRule: 'evenodd',
         fill: 'green',
         selectable: false      });      
      canvas.add( poly1);
    var c= (new fabric.Circle({
        radius: 50,
        left: 125,
        top: 50,
        fill: 'red'
    }));
    
    canvas.add(c);
    c.sendToBack();
      
    function closetPoint(subjPolyPoint, subtrPoly){
    	var minIndexes = [];
    	for (var j in subtrPoly){
      	var minLength = Length(subjPolyPoint, subtrPoly[j][0]);
      	var	minIndex = 0;
        for (var i = 1; i < subtrPoly[j].length; i++){
          var newLength = Length(subjPolyPoint, subtrPoly[j][i])
            if (minLength > newLength){
              minLength = newLength;
              minIndex = i;
            }
        }
        minIndexes.push({arrayIndex: j, elementIndex: minIndex});
      }
        return minIndexes;
    }
    
    function Length(point1, point2) {      
        var x1 = point1.x,
            x2 = point2.x,
            y1 = point1.y,
            y2 = point2.y;
    		    return Math.sqrt((x1 -= x2) * x1 + (y1 -= y2) *y1);
    }
    
    function sortPolygonArray(array, indexes){
    var result = [];
    	for (var i in indexes){
      	var newArray = [];
      	var originalLength = array[indexes[i].arrayIndex].length;
      	while (newArray.length != originalLength){
          if (indexes[i].elementIndex == originalLength){
            indexes[i].elementIndex = 0;
          }
       	 newArray.push(array[indexes[i].arrayIndex][indexes[i].elementIndex]);
       	 indexes[i].elementIndex++;
     	 }
       result.push(newArray);
      }
    	
      return result;
    }
    
    function combinePolygonArrays(subjPoly, subtrPoly){
    	var newArray = subjPoly;
      var lastSubjectPoint = subjPoly[subjPoly.length - 1];
      for (var i in subtrPoly){
      	var firstSubtractedPoint = subtrPoly[i][0];
        newArray = newArray.concat(subtrPoly[i]);
      	newArray.push(firstSubtractedPoint);
     		newArray.push(lastSubjectPoint);
      }
      return newArray;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.11/fabric.js"></script>
    <canvas id="c" width="500" height="350" style="border:1px solid #ccc"></canvas>
    &#13;
    &#13;
    &#13;