代码之家  ›  专栏  ›  技术社区  ›  Observer

织物js fillRule-偶数(减去形状)

  •  0
  • Observer  · 技术社区  · 8 年前

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

    globalCompositeOperation不适用于我,因为我需要查看多边形孔中的形状 like this

    这是我的代码: fiddle

    有两个例子:

    • 原生html5画布2多边形(作品)

    当我为织物设置fillRule:evenodd时。js polygon,它将进入fabric函数,并将上下文填充设置为“eveneodd”

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

    请告诉我如何使用'enevodd'如果fabric.js

    1 回复  |  直到 7 年前
        1
  •  2
  •   Observer    7 年前

    这个 “偶数” 填充规则适用于一个织物对象。即使使用组对象,也不能对单独的对象使用此规则并将它们组合在一起。在组渲染中,形状单独发生,这意味着每个对象调用:

    context.fill(); 
    

    context.fill('evenodd')
    

    使用 “偶数” Fabric.js中缺少多个对象的规则功能。

    步骤:

    1. 查找相减多边形中与主题多边形的最后一点最近的点。
    2. 按最近索引对相减多边形数组排序
    3. 将主题和减去的多边形合并为一个。

    这是一个 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;
    }
    <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>