Fabric.js fillRule - evenodd (subtract shapes)

梦想与她 提交于 2019-12-12 01:56:17

问题


I am trying to do hole in the polygon using fillRule = 'evenodd' in fabric.js

globalCompositeOperation won't work for me, because I need to see shape in the polygon hole like this

Here is my code: fiddle

There are 2 examples:

  • Fabric.js 2 polygons (doesn't work)
  • native html5 canvas 2 polygons (works)

When I set fillRule: 'evenodd' for fabric.js polygon, it is going to the fabric function and it's setting context fill to 'eveneodd'

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

But still it doesn't work. Please, give my some idea how to use 'enevodd' if fabric.js


回答1:


The 'evenodd' fill rule works fine with one fabric object. You cannot use this rule for separate objects and combine them together, even if you are using a group object. In a group rendering for the shapes happening separately, which means every object calls:

context.fill(); 

or

context.fill('evenodd')

Using 'evenodd' rule for multiple objects is missing feature in the Fabric.js.

Here is some workaround how to use 'evenodd' rule for one subjects polygon and multiple subtracted polygons.

Steps:

  1. Find closest point of the subtracted polygon to the last point of the subject polygon.
  2. Sort subtracted polygon arrays by closest index
  3. Combine Subject and subtracted polygons into one.

Here is a fiddle.

This code needs to be improved. It gives an idea how to make holes in the polygon using 'evenodd' rule.

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>


来源:https://stackoverflow.com/questions/40492679/fabric-js-fillrule-evenodd-subtract-shapes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!