151 lines
5.5 KiB
JavaScript
151 lines
5.5 KiB
JavaScript
|
|
/**
|
|
* Draws a path.
|
|
* @param {number[]|PIXI.IPointData[]|PIXI.Polygon|...number|...PIXI.IPointData} path The polygon or points.
|
|
* @returns {this} This Graphics instance.
|
|
*/
|
|
PIXI.Graphics.prototype.drawPath = function(...path) {
|
|
let closeStroke = false;
|
|
let polygon = path[0];
|
|
let points;
|
|
if ( polygon.points ) {
|
|
closeStroke = polygon.closeStroke;
|
|
points = polygon.points;
|
|
} else if ( Array.isArray(path[0]) ) {
|
|
points = path[0];
|
|
} else {
|
|
points = path;
|
|
}
|
|
polygon = new PIXI.Polygon(points);
|
|
polygon.closeStroke = closeStroke;
|
|
return this.drawShape(polygon);
|
|
};
|
|
PIXI.LegacyGraphics.prototype.drawPath = PIXI.Graphics.prototype.drawPath;
|
|
PIXI.smooth.SmoothGraphics.prototype.drawPath = PIXI.Graphics.prototype.drawPath;
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Draws a smoothed polygon.
|
|
* @param {number[]|PIXI.IPointData[]|PIXI.Polygon|...number|...PIXI.IPointData} path The polygon or points.
|
|
* @param {number} [smoothing=0] The smoothness in the range [0, 1]. 0: no smoothing; 1: maximum smoothing.
|
|
* @returns {this} This Graphics instance.
|
|
*/
|
|
PIXI.Graphics.prototype.drawSmoothedPolygon = function(...path) {
|
|
let closeStroke = true;
|
|
let polygon = path[0];
|
|
let points;
|
|
let factor;
|
|
if ( polygon.points ) {
|
|
closeStroke = polygon.closeStroke;
|
|
points = polygon.points;
|
|
factor = path[1];
|
|
} else if ( Array.isArray(path[0]) ) {
|
|
points = path[0];
|
|
factor = path[1];
|
|
} else if ( typeof path[0] === "number" ) {
|
|
points = path;
|
|
factor = path.length % 2 ? path.at(-1) : 0;
|
|
} else {
|
|
const n = path.length - (typeof path.at(-1) !== "object" ? 1 : 0);
|
|
points = [];
|
|
for ( let i = 0; i < n; i++ ) points.push(path[i].x, path[i].y);
|
|
factor = path.at(n);
|
|
}
|
|
factor ??= 0;
|
|
if ( (points.length < 6) || (factor <= 0) ) {
|
|
polygon = new PIXI.Polygon(points.slice(0, points.length - (points.length % 2)));
|
|
polygon.closeStroke = closeStroke;
|
|
return this.drawShape(polygon);
|
|
}
|
|
const dedupedPoints = [points[0], points[1]];
|
|
for ( let i = 2; i < points.length - 1; i += 2 ) {
|
|
const x = points[i];
|
|
const y = points[i + 1];
|
|
if ( (x === points[i - 2]) && (y === points[i - 1]) ) continue;
|
|
dedupedPoints.push(x, y);
|
|
}
|
|
points = dedupedPoints;
|
|
if ( closeStroke && (points[0] === points.at(-2)) && (points[1] === points.at(-1)) ) points.length -= 2;
|
|
if ( points.length < 6 ) {
|
|
polygon = new PIXI.Polygon(points);
|
|
polygon.closeStroke = closeStroke;
|
|
return this.drawShape(polygon);
|
|
}
|
|
const getBezierControlPoints = (fromX, fromY, toX, toY, nextX, nextY) => {
|
|
const vectorX = nextX - fromX;
|
|
const vectorY = nextY - fromY;
|
|
const preDistance = Math.hypot(toX - fromX, toY - fromY);
|
|
const postDistance = Math.hypot(nextX - toX, nextY - toY);
|
|
const totalDistance = preDistance + postDistance;
|
|
const cp0d = 0.5 * factor * (preDistance / totalDistance);
|
|
const cp1d = 0.5 * factor * (postDistance / totalDistance);
|
|
return [
|
|
toX - (vectorX * cp0d),
|
|
toY - (vectorY * cp0d),
|
|
toX + (vectorX * cp1d),
|
|
toY + (vectorY * cp1d)
|
|
];
|
|
};
|
|
let [fromX, fromY, toX, toY] = points;
|
|
let [cpX, cpY, cpXNext, cpYNext] = getBezierControlPoints(points.at(-2), points.at(-1), fromX, fromY, toX, toY);
|
|
this.moveTo(fromX, fromY);
|
|
for ( let i = 2, n = points.length + (closeStroke ? 2 : 0); i < n; i += 2 ) {
|
|
const nextX = points[(i + 2) % points.length];
|
|
const nextY = points[(i + 3) % points.length];
|
|
cpX = cpXNext;
|
|
cpY = cpYNext;
|
|
let cpX2;
|
|
let cpY2;
|
|
[cpX2, cpY2, cpXNext, cpYNext] = getBezierControlPoints(fromX, fromY, toX, toY, nextX, nextY);
|
|
if ( !closeStroke && (i === 2) ) this.quadraticCurveTo(cpX2, cpY2, toX, toY);
|
|
else if ( !closeStroke && (i === points.length - 2) ) this.quadraticCurveTo(cpX, cpY, toX, toY);
|
|
else this.bezierCurveTo(cpX, cpY, cpX2, cpY2, toX, toY);
|
|
fromX = toX;
|
|
fromY = toY;
|
|
toX = nextX;
|
|
toY = nextY;
|
|
}
|
|
if ( closeStroke ) this.closePath();
|
|
this.finishPoly();
|
|
return this;
|
|
};
|
|
PIXI.LegacyGraphics.prototype.drawSmoothedPolygon = PIXI.Graphics.prototype.drawSmoothedPolygon;
|
|
PIXI.smooth.SmoothGraphics.prototype.drawSmoothedPolygon = PIXI.Graphics.prototype.drawSmoothedPolygon;
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Draws a smoothed path.
|
|
* @param {number[]|PIXI.IPointData[]|PIXI.Polygon|...number|...PIXI.IPointData} path The polygon or points.
|
|
* @param {number} [smoothing=0] The smoothness in the range [0, 1]. 0: no smoothing; 1: maximum smoothing.
|
|
* @returns {this} This Graphics instance.
|
|
*/
|
|
PIXI.Graphics.prototype.drawSmoothedPath = function(...path) {
|
|
let closeStroke = false;
|
|
let polygon = path[0];
|
|
let points;
|
|
let factor;
|
|
if ( polygon.points ) {
|
|
closeStroke = polygon.closeStroke;
|
|
points = polygon.points;
|
|
factor = path[1];
|
|
} else if ( Array.isArray(path[0]) ) {
|
|
points = path[0];
|
|
factor = path[1];
|
|
} else if ( typeof path[0] === "number" ) {
|
|
points = path;
|
|
factor = path.length % 2 ? path.at(-1) : 0;
|
|
} else {
|
|
const n = path.length - (typeof path.at(-1) !== "object" ? 1 : 0);
|
|
points = [];
|
|
for ( let i = 0; i < n; i++ ) points.push(path[i].x, path[i].y);
|
|
factor = path.at(n);
|
|
}
|
|
polygon = new PIXI.Polygon(points);
|
|
polygon.closeStroke = closeStroke;
|
|
return this.drawSmoothedPolygon(polygon, factor);
|
|
};
|
|
PIXI.LegacyGraphics.prototype.drawSmoothedPath = PIXI.Graphics.prototype.drawSmoothedPath;
|
|
PIXI.smooth.SmoothGraphics.prototype.drawSmoothedPath = PIXI.Graphics.prototype.drawSmoothedPath;
|