Я использую Fabri cJS для создания многоугольника с 6 точками
var polygon = new fabric.Polygon([
new fabric.Point(150, 50),
new fabric.Point(250, 50),
new fabric.Point(250, 150),
new fabric.Point(150, 150),
new fabric.Point(50, 250),
]);
В каждой точке мне нужна линия, поэтому я перебираю точки и успешно добавляю линии:
return new fabric.Line([p.x, p.y, fromX, fromY], {
stroke: colors[i],
strokeWidth: 10,
hasBorders: true,
strokeDashArray: [20, 5]
});
этот код успешно генерирует многоугольник с моей желаемой цветной линией:
Теперь проблема в том, что я хочу настроить положение линий, например, красный линия Мне нужно быть липкой поверх многоугольника, зеленая мне нужна половина внутри многоугольника, синяя 5% от многоугольника и т. д. c.
При поиске я обнаружил, Проверить если точка находится внутри многоугольника и пробовала те функции, которые дают разные результаты, поэтому у меня есть две функции, isinPolygonFirst
и isinPolygonSecond
, которые в основном проверяют, находится ли моя точка внутри многоугольника. Я подумал: если бы я мог знать, что если мои точки находятся внутри многоугольника, я могу добавить какое-то значение, например, если точка была [20,20, а если она находится внутри многоугольника, я могу увеличить до [21,21] и перепроверить, если это так. Я публикую отладочную информацию (во фрагменте ниже необходимо переместить многоугольник, чтобы увидеть сообщения отладки):
// function to check if line exists in polygon
function isinPolygonFirst(points, longitude_x, latitude_y) {
vertices_y = new Array();
vertices_x = new Array();
var r = 0;
var i = 0;
var j = 0;
var c = 0;
var point = 0;
for (r = 0; r < points.length; r++) {
vertices_y.push(points[r].y);
vertices_x.push(points[r].x);
}
points_polygon = vertices_x.length;
for (i = 0, j = points_polygon; i < points_polygon; j = i++) {
point = i;
if (point == points_polygon)
point = 0;
if (((vertices_y[point] > latitude_y != (vertices_y[j] > latitude_y)) && (longitude_x < (vertices_x[j] - vertices_x[point]) * (latitude_y - vertices_y[point]) / (vertices_y[j] - vertices_y[point]) + vertices_x[point])))
c = !c;
}
return c;
}
// other function to check if line exist in polygon
function isinPolygonSecond(points, x, y) {
cornersX = new Array();
cornersY = new Array();
for (r = 0; r < points.length; r++) {
cornersX.push(points[r].x);
cornersY.push(points[r].y);
}
var i, j = cornersX.length - 1;
var odd = false;
var pX = cornersX;
var pY = cornersY;
for (i = 0; i < cornersX.length; i++) {
if ((pY[i] < y && pY[j] >= y || pY[j] < y && pY[i] >= y) &&
(pX[i] <= x || pX[j] <= x)) {
odd ^= (pX[i] + (y - pY[i]) * (pX[j] - pX[i]) / (pY[j] - pY[i])) < x;
}
j = i;
}
return odd;
}
var canvas = new fabric.Canvas("c", {
selection: false
});
var points = [];
var polygon = new fabric.Polygon([
new fabric.Point(150, 50),
new fabric.Point(250, 50),
new fabric.Point(250, 150),
new fabric.Point(150, 150),
new fabric.Point(50, 250),
]);
polygon.on("modified", function() {
//document.getElementById("p").innerHTML = JSON.stringify(this)+ "<br>";
var matrix = this.calcTransformMatrix();
var transformedPoints = this.get("points")
.map(function(p) {
return new fabric.Point(
p.x - polygon.pathOffset.x,
p.y - polygon.pathOffset.y);
})
.map(function(p) {
return fabric.util.transformPoint(p, matrix);
});
var circles = transformedPoints.map(function(p) {
return new fabric.Circle({
left: p.x,
top: p.y,
radius: 3,
fill: "red",
originX: "center",
originY: "center",
hasControls: false,
hasBorders: false,
selectable: false
});
});
//Lines Colors
var colors = ['red', 'green', 'blue', 'violet', 'teal', 'brown'];
//I need these distances from the polygon, where is negative value it should go inside polygon
var LinesDistances = [10, -5, -20, 0, 20, 40];
var lines = transformedPoints.map(function(p, i) {
var po = (i < polygon.points.length) ? i + 1 : 0;
if (typeof transformedPoints[po] === 'undefined')
po = 0;
var fromX = transformedPoints[po].x;
var fromY = transformedPoints[po].y;
var isinPolygon = isinPolygonFirst(transformedPoints, fromX, fromY);
var isinPolygon2 = isinPolygonSecond(transformedPoints, fromX, fromY);
var debug = '';
debug += 'fromX:' + fromX;
debug += ' ,fromY :' + fromY;
debug += ' ,isinPolygon:' + isinPolygon;
debug += ' ,isinPolygonSecond:' + isinPolygon2;
document.getElementById("p").innerHTML += '<p style="color:#fff;background:' + colors[i] + '"> ' + debug + "</p>";
return new fabric.Line([p.x, p.y, fromX, fromY], {
stroke: colors[i],
strokeWidth: 10,
hasBorders: true,
strokeDashArray: [20, 5]
});
});
this.canvas.clear().add(this).add.apply(this.canvas, lines).add.apply(this.canvas, circles).setActiveObject(this).renderAll();
polygon.set({
opacity: 0.5
});
polygon.sendToBack();
});
canvas.add(polygon).renderAll();
canvas {
border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.min.js"></script>
<div id="p"></div>
<canvas id="c" width="600" height="400"></canvas>
Я не уверен, что это правильный подход, к которому я двигаюсь, я хочу динамически расставить линии вокруг многоугольника так, как это потребуется.
Мне нужны эти расстояния от многоугольника, где должно быть отрицательное значение go внутри многоугольника
var LinesDistances = [10, -5, -20, 0, 20, 40];
Вот скрипка и код. на https://jsfiddle.net/DivMaster/0e34Lnyx/211/
Любая помощь? Спасибо <3 </p>