在fabric.js中删除矩形边缘的度数

时间:2017-11-09 21:20:01

标签: canvas html5-canvas fabricjs



//(function() {

function rotate(cx, cy, x, y, angle) {
  var radians = (Math.PI / 180) * angle,
    cos = Math.cos(radians),
    sin = Math.sin(radians),
    nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
    ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
  return [nx, ny];
}


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

// create a path with a fill and a different color stroke
var result1 = rotate(0, 0, 50, 0, -45);
var xv = Math.round(result1[0]);
var yv = Math.round(result1[1]);
//alert("" + xv + " " + yv);
var result2 = rotate(50, 200, 0, 200, -45);
var xf = Math.round(result2[0]);
var yf = Math.round(result2[1]);
//alert("" + xf + " " + yf);
//alert("M 0 0 L 0 0 " + xv + " " + yv + "" + " 50 200 " + xf + " " + yf + "" + " z");
//var rect = new fabric.Path("M 0 0 L 0 0 "+xv+" "+yv+""+" 50 200 0 200 z");
var rect = new fabric.Path("M 0 0 L 0 0 " + xv + " " + yv + "" + " 50 200 " + xf + " " + yf + "" + " z");
rect.set({
  fill: 'rgba(255,127,39,1)',
  //stroke: 'rgba(34,177,76,1)',
  //strokeWidth: 5
  angle: 45
});
canvas.add(rect);
canvas.renderAll();
//})();

<canvas id="canvas" width="800" height="600"></canvas>

<script src="https://github.com/kangax/fabric.js/blob/master/dist/fabric.min.js"></script>
&#13;
&#13;
&#13;

我的设计是让矩形有边缘,边缘需要在某个角度或度数上移除或缩小。我添加了图像here。矩形旋转 - 或+45度和顶部边缘和底部需要切割90度。 任何人都可以告诉我该怎么做。

1 个答案:

答案 0 :(得分:2)

如何剪裁多边形

该问题的通用解决方案是使用裁剪算法。

多边形是一组连接点,剪切它意味着使用一条线去除多边形的一部分,沿剪切线创建新点。

图像有助于可视化过程。

enter image description here

我们从一个有6个边和6个顶点[1,2,3,4,5,6]的多边形开始。然后我们定义一条剪切线A,B。这条线实际上是无限长的,但是我们需要两个点来定义它,这些点可以在线上的任何地方,但方向很重要。我们删除了正确的行,并保留剩下的内容。

一些辅助函数

创建点,线和多边形的函数

 function point(x = 0, y = 0) { return {x,y} }
 function line(p1 = point(), p2 = point()) { return {p1, p2} }
 function polygon(...points) { return {points : [...points]} }

现在我们可以创建一个多边形

const poly1 = polygon(point(10,100), point(40,50), point(100,50), point(150,90), point(80,200), point(30,160));

沿着

剪辑的一​​条线
const clipLine = line(point(100,0), point(150,220));

剪辑

要剪切多边形,我们首先创建一个包含剪裁多边形的空多边形。

const clippedPoly = polygon();

行的左侧还是右侧

然后我们从第一个点开始,检查点是否在剪切线的左侧或右侧,如果是,则将该点添加到新的多边形。

我们需要一个函数来检查一个点是否在一条线的左边或右边。

function isPointLeftOfLine(point, line){
    const x1 = line.p2.x - line.p1.x;
    const y1 = line.p2.y - line.p1.y;
    const x2 = point.x - line.p1.x;
    const y2 = point.y - line.p1.y;
    return x1 * y2 - y1 * x2 > 0;  // if the cross product is positive then left of line
 }

我们一直踩着多边形点,为新的多边形添加点,直到我们找到一条直线的点。

两条线交叉的点

当我们发现这一点时,我们知道在沿着该线的某个点处,该线被剪切线切割。所以我们需要找到这一点。

function lineLineIntercept(l1, l2, p = point()){
    const x1 = l1.p2.x - l1.p1.x;
    const y1 = l1.p2.y - l1.p1.y;
    const x2 = l2.p2.x - l2.p1.x;
    const y2 = l2.p2.y - l2.p1.y;
    const cross = x1 * y2 - y1 * x2;
    const u = (x2 * (l1.p1.y - l2.p1.y) - y2 * (l1.p1.x - l2.p1.x)) / cross;
    p.x = l1.p1.x + x1 * u;
    p.y = l1.p1.y + y1 * u;
    return p;
}

我们将新点添加到新的poly并继续检查点。我们发现的每个点都在我们忽略的行的右边,然后继续下一行。

当我们再次找到该线左侧的点时,我们知道我们有另一个由剪辑切割的多边形线。所以我们找到截距并将其添加到新的poly。

我们继续这个过程,直到没有更多的积分。生成的多边形已被剪切到线A,B

到矩形

因此,对于OP,您可以将矩形创建为一组四个点。然后以您想要的角度和位置创建第一个剪切线。使用上面的过程剪辑矩形。然后以您想要的角度和位置创建第二个剪切线,并剪切上一个剪辑的结果。

请记住剪切线的方向很重要。在您的情况下,第二个剪切线必须与第一个剪切线的方向相反。

裁剪多边形的示例。

使用上述方法进行多边形裁剪的交互式示例。

canvas.width = 300;
canvas.height = 300;
const ctx = canvas.getContext("2d");



function point(x = 0, y = 0) { return { x, y } }
function line(p1 = point(), p2 = point()) { return { p1, p2 } }
function polygon(...points) { return { points : [...points] } }

function isPointLeftOfLine(point, line) {
  const x1 = line.p2.x - line.p1.x;
  const y1 = line.p2.y - line.p1.y;
  const x2 = point.x - line.p1.x;
  const y2 = point.y - line.p1.y;
  return x1 * y2 - y1 * x2 > 0; // if the cross product is positive then left of line
}

function lineLineIntercept(l1, l2, p = point()) {
  const x1 = l1.p2.x - l1.p1.x;
  const y1 = l1.p2.y - l1.p1.y;
  const x2 = l2.p2.x - l2.p1.x;
  const y2 = l2.p2.y - l2.p1.y;
  const cross = x1 * y2 - y1 * x2;
  const u = (x2 * (l1.p1.y - l2.p1.y) - y2 * (l1.p1.x - l2.p1.x)) / cross;
  p.x = l1.p1.x + x1 * u;
  p.y = l1.p1.y + y1 * u;
  return p;
}




function clipPolygon(poly, cLine, result = polygon()) {
  poly.points.push(poly.points[0]); // make copy of last point to simplify code
  result.points.length = 0;
  var lastPointLeft = true;
  poly.points.forEach((point, index) => {
    if (isPointLeftOfLine(point,cLine)) {
      if (!lastPointLeft) {
        result.points.push(lineLineIntercept(line(poly.points[index - 1], point), cLine));
      }
      if (index < poly.points.length - 1) {
        result.points.push(point);
      }
      lastPointLeft = true;
    } else {
      if (index > 0 && lastPointLeft) {
        result.points.push(lineLineIntercept(line(poly.points[index - 1], point), cLine));
      }
      lastPointLeft = false;
    }
  });
  poly.points.pop(); // remove last point
  return result;
}



const poly1 = polygon(
  point(10, 100),
  point(40, 50), 
  point(100, 50), 
  point(150, 90), 
  point(250, 20), 
  point(200, 120), 
  point(100, 120), 
  point(250, 220), 
  point(80, 200), 
  point(30, 160)
);

const clipLine = line(point(150, 0), point(150, 220));
const clipLine2 = line(point(50, 300), point(50, 0));
var clippedPoly = polygon();
var clippedPoly2 = polygon();
const mouse = clipLine.p2;

function mouseEvents(e) {
  const m = mouse;
  const bounds = canvas.getBoundingClientRect();
  m.x = e.pageX - bounds.left - scrollX;
  m.y = e.pageY - bounds.top - scrollY;
}
document.addEventListener("mousemove", mouseEvents);

function drawLine(line) {
  ctx.beginPath();
  ctx.lineTo(line.p1.x, line.p1.y);
  ctx.lineTo(line.p2.x, line.p2.y);
  ctx.stroke();
}

function drawPoint(point) {
  ctx.fillRect(point.x - 3, point.y - 3, 6, 6);
}

function drawPoly(polygon) {
  ctx.beginPath();
  var i = 0;
  while (i < polygon.points.length) {
    ctx.lineTo(polygon.points[i].x, polygon.points[i++].y);
  }
  ctx.closePath();
  ctx.stroke();
}

function drawPolyPoints(polygon) {
  var i = 0;
  while (i < polygon.points.length) {
    drawPoint(polygon.points[i++]);
  }
}
var w = canvas.width;
var h = canvas.height;
ctx.fillStyle = "black";
ctx.lineJoin = "round";
ctx.lineWidth = 2;

function update() {
  ctx.clearRect(0, 0, w, h);
  ctx.strokeStyle = "#FAA";
  drawPoly(poly1);
  ctx.strokeStyle = "blue";
  drawLine(clipLine);
  drawPoint(clipLine.p1);
  drawPoint(clipLine.p2);
  drawLine(clipLine2);
  drawPoint(clipLine2.p1);
  drawPoint(clipLine2.p2);

  clippedPoly2 = clipPolygon(poly1, clipLine, clippedPoly2);
  if(clippedPoly2.points.length > 0){
    clippedPoly = clipPolygon(clippedPoly2, clipLine2, clippedPoly);
    ctx.strokeStyle = "#F00";  
    drawPoly(clippedPoly);
    ctx.fillStyle = "#D62";
    ctx.globalAlpha = 0.2;
    ctx.fill();
    ctx.globalAlpha = 1;
    ctx.fillStyle = "black";
    drawPolyPoints(clippedPoly);
  }
  
  requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas {
  border: 2px solid black;
}
<canvas id="canvas"></canvas>