//(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;
我的设计是让矩形有边缘,边缘需要在某个角度或度数上移除或缩小。我添加了图像here。矩形旋转 - 或+45度和顶部边缘和底部需要切割90度。 任何人都可以告诉我该怎么做。
答案 0 :(得分:2)
该问题的通用解决方案是使用裁剪算法。
多边形是一组连接点,剪切它意味着使用一条线去除多边形的一部分,沿剪切线创建新点。
图像有助于可视化过程。
我们从一个有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>