@btfash/pixi-dashed-line 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/README.md +87 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +412 -0
- package/dist/index.js.map +1 -0
- package/lib/index.ts +561 -0
- package/package.json +45 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2021 David Figatner
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# pixi-dashed-line
|
|
2
|
+
|
|
3
|
+
A pixi.js implementation to support dashed lines in PIXI.Graphics.
|
|
4
|
+
|
|
5
|
+
* Two implementations of a dashed line for pixi.js: lineTo/moveTo w/gaps (preferred), and texture-based (using a dashed-line texture when drawing the line)
|
|
6
|
+
* Dashed support for lineTo, drawCircle, drawEllipse, drawPolygon
|
|
7
|
+
* Dashed lines can be scaled (allows for dashed lines to remain the same size regardless of zoom level)
|
|
8
|
+
|
|
9
|
+
## Live Demo
|
|
10
|
+
|
|
11
|
+
[https://davidfig.github.io/pixi-dashed-line](https://davidfig.github.io/pixi-dashed-line/) ([source code](https://github.com/davidfig/pixi-dashed-line/blob/main/demo/index.ts))
|
|
12
|
+
|
|
13
|
+
## Documentation
|
|
14
|
+
|
|
15
|
+
### class DashLine
|
|
16
|
+
#### constructor(graphics: PIXI.Graphics, options?.DashLineOptions)
|
|
17
|
+
```js
|
|
18
|
+
DashLine.DashLineOptions = {
|
|
19
|
+
useTexture?=false - whether to use a texture or moveTo/lineTo (see notes below in README.md)
|
|
20
|
+
dashes?=[10, 5] - an array holding one or more [dash, gap] entries, eg, [10, 5, 20, 10, ...])
|
|
21
|
+
width?=1 - width of the dashed line
|
|
22
|
+
color?=0xffffff - color of the dashed line
|
|
23
|
+
alpha?=1 - alpha of the dashed line
|
|
24
|
+
options.cap? - add a PIXI.LINE_CAP style to dashed lines (only works for useTexture: false)
|
|
25
|
+
options.join? - add a PIXI.LINE_JOIN style to the dashed lines (only works for useTexture: false)
|
|
26
|
+
options.alignment? - change alignment of lines drawn (0.5 = middle, 1 = outer, 0 = inner)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
#### moveTo(x: number, y: number)
|
|
30
|
+
Moves cursor to location
|
|
31
|
+
|
|
32
|
+
#### lineTo(x: number, y: number, closePath?: boolean)
|
|
33
|
+
Draws a dashed line. If closePath = true, then lineTo will leave a proper gap if its destination is the first point (ie, if this line closes the shape)
|
|
34
|
+
|
|
35
|
+
#### drawCircle(x: number, y: number, radius: number, points=80, matrix?: PIXI.Matrix)
|
|
36
|
+
where x,y is the center of circle, and points are the number of points used to draw the circle; matrix is applied before the draw (this adds a shape-specific transform to pixi's DisplayObject transforms)
|
|
37
|
+
|
|
38
|
+
#### drawEllipse(x: number, y: number, radiusX: number, radiusY: number, points=80, matrix?: PIXI.Matrix)
|
|
39
|
+
where x,y is the center of ellipse, and points are the number of points used to draw the ellipse; matrix is applied before the draw (this adds a shape-specific transform to pixi's DisplayObject transforms)
|
|
40
|
+
|
|
41
|
+
#### drawRect(x: number, y: number, width: number, height: number, matrix?: PIXI.Matrix)
|
|
42
|
+
draws a dashed rectangle; matrix is applied before the draw (this adds a shape-specific transform to pixi's DisplayObject transforms)
|
|
43
|
+
|
|
44
|
+
#### drawPolygon(PIXI.Point[] | number[], matrix?: PIXI.Matrix)
|
|
45
|
+
draws a dashed polygon; matrix is applied before the draw (this adds a shape-specific transform to pixi's DisplayObject transforms)
|
|
46
|
+
|
|
47
|
+
#### setLineStyle()
|
|
48
|
+
changes line style to the proper dashed line style -- this is useful if the graphics element's lineStyle was changed
|
|
49
|
+
|
|
50
|
+
## Simple Example
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
import { DashLine } from 'pixi-dashed-lines'
|
|
54
|
+
|
|
55
|
+
...
|
|
56
|
+
const g = stage.addChild(new PIXI.Graphics())
|
|
57
|
+
|
|
58
|
+
const dash = new DashLine(g, {
|
|
59
|
+
dash: [20, 10],
|
|
60
|
+
width: 5,
|
|
61
|
+
color: 0xff0000,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// draws a dashed triangle
|
|
65
|
+
dash.moveTo(0, 0)
|
|
66
|
+
.lineTo(100, 100)
|
|
67
|
+
.lineTo(0, 100)
|
|
68
|
+
.lineTo(0, 0)
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
## When to use options.useTexture = true
|
|
72
|
+
|
|
73
|
+
For most use-cases, the lineTo/moveTo (`options.useTexture = false`) is better because it provides a more accurate implementation and supports cap and join styles.
|
|
74
|
+
|
|
75
|
+
The texture-based approach (`options.useTexture = true`) is useful when the geometry is very large or very small as PIXI.Graphics does not handle those cases well (see https://www.html5gamedevs.com/topic/24876-weird-lines-when-using-extreme-coordinate-values/). You'll know you need this if zooming in and out on the dashed line causes out of memory errors :)
|
|
76
|
+
|
|
77
|
+
### Technical Notes on options.useTexture = true
|
|
78
|
+
`options.useTexture=true` does not use pixi.js's line joins and caps for connecting lines (see https://mattdesl.svbtle.com/drawing-lines-is-hard): instead it uses `Graphics.lineTextureStyle` to supply a texture to draw the dashed lines. The texture needs a custom matrix to properly rotate the dash based on the angle of the next line (and to translate the texture so it starts properly (see https://www.html5gamedevs.com/topic/45698-begintexturefill/)). Without the matrix, the dash's length will change as the line's angle changes.
|
|
79
|
+
|
|
80
|
+
Regrettably, pixi.js does not provide a mechanism to change the matrix of a texture without breaking the current line with a moveTo command. (This was my key insight that finally got this working. I banged my head many hours trying to figure out why the texture did not rotate properly. The answer was that you have to moveTo before changing the matrix.)
|
|
81
|
+
|
|
82
|
+
### Future work
|
|
83
|
+
Ideally, the dashed line functionality should be built directly into pixi.js's Graphics line drawing module w/logic that separates the triangles of the dashed line to take into account changes in the angle of the line. I thought about adding it, but decided the amount of work was not worth it. (Especially since the use case for useTexture is limited to strange PIXI.Graphics geometries.) Maybe someone does a different calculus and adds this feature directly into pixi.js and makes this library obsolete.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
MIT License
|
|
87
|
+
(c) 2021 [David Figatner](https://yopeyopey.com/)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as PIXI from "pixi.js";
|
|
2
|
+
/** Define the dash: [dash length, gap size, dash size, gap size, ...] */
|
|
3
|
+
export type Dashes = number[];
|
|
4
|
+
export type DashLineOptions = {
|
|
5
|
+
dash?: Dashes;
|
|
6
|
+
width?: number;
|
|
7
|
+
color?: number;
|
|
8
|
+
alpha?: number;
|
|
9
|
+
scale?: number;
|
|
10
|
+
useTexture?: boolean;
|
|
11
|
+
useDots?: boolean;
|
|
12
|
+
cap?: "butt" | "round" | "square";
|
|
13
|
+
join?: "bevel" | "miter" | "round";
|
|
14
|
+
alignment?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare class DashLine {
|
|
17
|
+
graphics: PIXI.Graphics;
|
|
18
|
+
/** current length of the line */
|
|
19
|
+
lineLength: number;
|
|
20
|
+
/** cursor location */
|
|
21
|
+
cursor: PIXI.Point;
|
|
22
|
+
/** desired scale of line */
|
|
23
|
+
scale: number;
|
|
24
|
+
private activeTexture;
|
|
25
|
+
private start;
|
|
26
|
+
private dashSize;
|
|
27
|
+
private dash;
|
|
28
|
+
private useTexture;
|
|
29
|
+
private options;
|
|
30
|
+
static dashTextureCache: Record<string, PIXI.Texture>;
|
|
31
|
+
/**
|
|
32
|
+
* Create a DashLine
|
|
33
|
+
* @param graphics
|
|
34
|
+
* @param [options]
|
|
35
|
+
* @param [options.useTexture=false] - use the texture based render (useful for very large or very small dashed lines)
|
|
36
|
+
* @param [options.dashes=[10,5] - an array holding the dash and gap (eg, [10, 5, 20, 5, ...])
|
|
37
|
+
* @param [options.width=1] - width of the dashed line
|
|
38
|
+
* @param [options.alpha=1] - alpha of the dashed line
|
|
39
|
+
* @param [options.color=0xffffff] - color of the dashed line
|
|
40
|
+
* @param [options.cap] - add a PIXI.LINE_CAP style to dashed lines (only works for useTexture: false)
|
|
41
|
+
* @param [options.join] - add a PIXI.LINE_JOIN style to the dashed lines (only works for useTexture: false)
|
|
42
|
+
* @param [options.alignment] - The alignment of any lines drawn (0.5 = middle, 1 = outer, 0 = inner)
|
|
43
|
+
*/
|
|
44
|
+
constructor(graphics: PIXI.Graphics, options?: DashLineOptions);
|
|
45
|
+
/** resets line style to enable dashed line (useful if lineStyle was changed on graphics element) */
|
|
46
|
+
setStrokeStyle(): void;
|
|
47
|
+
private static distance;
|
|
48
|
+
moveTo(x: number, y: number): this;
|
|
49
|
+
lineTo(x: number, y: number, closePath?: boolean): this;
|
|
50
|
+
closePath(): void;
|
|
51
|
+
circle(x: number, y: number, radius: number, points?: number, matrix?: PIXI.Matrix): this;
|
|
52
|
+
ellipse(x: number, y: number, radiusX: number, radiusY: number, points?: number, matrix?: PIXI.Matrix): this;
|
|
53
|
+
poly(points: PIXI.Point[] | number[], matrix?: PIXI.Matrix): this;
|
|
54
|
+
rect(x: number, y: number, width: number, height: number, matrix?: PIXI.Matrix): this;
|
|
55
|
+
roundRect(x: number, y: number, width: number, height: number, cornerRadius?: number, matrix?: PIXI.Matrix): this;
|
|
56
|
+
private drawDashedArc;
|
|
57
|
+
private adjustStrokeStyle;
|
|
58
|
+
private static getTexture;
|
|
59
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.DashLine = void 0;
|
|
15
|
+
var PIXI = require("pixi.js");
|
|
16
|
+
function getPointOnArc(cx, cy, radius, angle, matrix) {
|
|
17
|
+
var radian = (angle * Math.PI) / 180;
|
|
18
|
+
var x = cx + Math.cos(radian) * radius;
|
|
19
|
+
var y = cy + Math.sin(radian) * radius;
|
|
20
|
+
if (matrix) {
|
|
21
|
+
var p = new PIXI.Point(x, y);
|
|
22
|
+
matrix.apply(p, p);
|
|
23
|
+
return { x: p.x, y: p.y };
|
|
24
|
+
}
|
|
25
|
+
return { x: x, y: y };
|
|
26
|
+
}
|
|
27
|
+
var dashLineOptionsDefault = {
|
|
28
|
+
dash: [10, 5],
|
|
29
|
+
width: 1,
|
|
30
|
+
color: 0xffffff,
|
|
31
|
+
alpha: 1,
|
|
32
|
+
scale: 1,
|
|
33
|
+
useTexture: false,
|
|
34
|
+
alignment: 0.5,
|
|
35
|
+
};
|
|
36
|
+
var DashLine = /** @class */ (function () {
|
|
37
|
+
/**
|
|
38
|
+
* Create a DashLine
|
|
39
|
+
* @param graphics
|
|
40
|
+
* @param [options]
|
|
41
|
+
* @param [options.useTexture=false] - use the texture based render (useful for very large or very small dashed lines)
|
|
42
|
+
* @param [options.dashes=[10,5] - an array holding the dash and gap (eg, [10, 5, 20, 5, ...])
|
|
43
|
+
* @param [options.width=1] - width of the dashed line
|
|
44
|
+
* @param [options.alpha=1] - alpha of the dashed line
|
|
45
|
+
* @param [options.color=0xffffff] - color of the dashed line
|
|
46
|
+
* @param [options.cap] - add a PIXI.LINE_CAP style to dashed lines (only works for useTexture: false)
|
|
47
|
+
* @param [options.join] - add a PIXI.LINE_JOIN style to the dashed lines (only works for useTexture: false)
|
|
48
|
+
* @param [options.alignment] - The alignment of any lines drawn (0.5 = middle, 1 = outer, 0 = inner)
|
|
49
|
+
*/
|
|
50
|
+
function DashLine(graphics, options) {
|
|
51
|
+
if (options === void 0) { options = {}; }
|
|
52
|
+
/** current length of the line */
|
|
53
|
+
this.lineLength = 0;
|
|
54
|
+
/** cursor location */
|
|
55
|
+
this.cursor = new PIXI.Point();
|
|
56
|
+
/** desired scale of line */
|
|
57
|
+
this.scale = 1;
|
|
58
|
+
// sanity check to ensure the lineStyle is still in use
|
|
59
|
+
this.activeTexture = undefined;
|
|
60
|
+
this.start = new PIXI.Point(0, 0);
|
|
61
|
+
this.graphics = graphics;
|
|
62
|
+
var mergedOpts = __assign(__assign({}, dashLineOptionsDefault), options);
|
|
63
|
+
this.dash = mergedOpts.dash;
|
|
64
|
+
this.dashSize = this.dash.reduce(function (a, b) { return a + b; });
|
|
65
|
+
this.useTexture = Boolean(mergedOpts.useTexture);
|
|
66
|
+
this.options = mergedOpts;
|
|
67
|
+
this.setStrokeStyle();
|
|
68
|
+
}
|
|
69
|
+
/** resets line style to enable dashed line (useful if lineStyle was changed on graphics element) */
|
|
70
|
+
DashLine.prototype.setStrokeStyle = function () {
|
|
71
|
+
var options = this.options;
|
|
72
|
+
if (this.useTexture) {
|
|
73
|
+
var texture = DashLine.getTexture(options, this.dashSize);
|
|
74
|
+
this.graphics.stroke({
|
|
75
|
+
width: options.width * options.scale,
|
|
76
|
+
color: options.color,
|
|
77
|
+
alpha: options.alpha,
|
|
78
|
+
texture: texture,
|
|
79
|
+
alignment: options.alignment,
|
|
80
|
+
});
|
|
81
|
+
this.activeTexture = texture;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this.graphics.stroke({
|
|
85
|
+
width: options.width * options.scale,
|
|
86
|
+
color: options.color,
|
|
87
|
+
alpha: options.alpha,
|
|
88
|
+
cap: options.cap,
|
|
89
|
+
join: options.join,
|
|
90
|
+
alignment: options.alignment,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
this.scale = options.scale;
|
|
94
|
+
};
|
|
95
|
+
DashLine.distance = function (x1, y1, x2, y2) {
|
|
96
|
+
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
97
|
+
};
|
|
98
|
+
DashLine.prototype.moveTo = function (x, y) {
|
|
99
|
+
this.lineLength = 0;
|
|
100
|
+
this.cursor.set(x, y);
|
|
101
|
+
this.start = new PIXI.Point(x, y);
|
|
102
|
+
this.graphics.moveTo(this.cursor.x, this.cursor.y);
|
|
103
|
+
return this;
|
|
104
|
+
};
|
|
105
|
+
DashLine.prototype.lineTo = function (x, y, closePath) {
|
|
106
|
+
if (this.lineLength === undefined) {
|
|
107
|
+
this.moveTo(0, 0);
|
|
108
|
+
}
|
|
109
|
+
var length = DashLine.distance(this.cursor.x, this.cursor.y, x, y);
|
|
110
|
+
var angle = Math.atan2(y - this.cursor.y, x - this.cursor.x);
|
|
111
|
+
var closed = closePath && x === this.start.x && y === this.start.y;
|
|
112
|
+
if (this.useTexture) {
|
|
113
|
+
this.graphics.moveTo(this.cursor.x, this.cursor.y);
|
|
114
|
+
this.adjustStrokeStyle(angle);
|
|
115
|
+
if (closed && this.dash.length % 2 === 0) {
|
|
116
|
+
var gap = Math.min(this.dash[this.dash.length - 1], length);
|
|
117
|
+
this.graphics.lineTo(x - Math.cos(angle) * gap, y - Math.sin(angle) * gap);
|
|
118
|
+
this.graphics.closePath();
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
this.graphics.lineTo(x, y);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
var cos = Math.cos(angle);
|
|
126
|
+
var sin = Math.sin(angle);
|
|
127
|
+
var x0 = this.cursor.x;
|
|
128
|
+
var y0 = this.cursor.y;
|
|
129
|
+
// find the first part of the dash for this line
|
|
130
|
+
var place = this.lineLength % (this.dashSize * this.scale);
|
|
131
|
+
var dashIndex = 0;
|
|
132
|
+
var dashStart = 0;
|
|
133
|
+
var dashX = 0;
|
|
134
|
+
for (var i = 0; i < this.dash.length; i++) {
|
|
135
|
+
var dashSize = this.dash[i] * this.scale;
|
|
136
|
+
if (place < dashX + dashSize) {
|
|
137
|
+
dashIndex = i;
|
|
138
|
+
dashStart = place - dashX;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
dashX += dashSize;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
var remaining = length;
|
|
146
|
+
// let count = 0
|
|
147
|
+
while (remaining > 0) {
|
|
148
|
+
// && count++ < 1000) {
|
|
149
|
+
var dashSize = this.dash[dashIndex] * this.scale - dashStart;
|
|
150
|
+
var dist = remaining > dashSize ? dashSize : remaining;
|
|
151
|
+
if (closed) {
|
|
152
|
+
var remainingDistance = DashLine.distance(x0 + cos * dist, y0 + sin * dist, this.start.x, this.start.y);
|
|
153
|
+
if (remainingDistance <= dist) {
|
|
154
|
+
if (dashIndex % 2 === 0) {
|
|
155
|
+
var lastDash = DashLine.distance(x0, y0, this.start.x, this.start.y) -
|
|
156
|
+
this.dash[this.dash.length - 1] * this.scale;
|
|
157
|
+
x0 += cos * lastDash;
|
|
158
|
+
y0 += sin * lastDash;
|
|
159
|
+
this.graphics.lineTo(x0, y0);
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
x0 += cos * dist;
|
|
165
|
+
y0 += sin * dist;
|
|
166
|
+
if (dashIndex % 2) {
|
|
167
|
+
this.graphics.moveTo(x0, y0);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.graphics.lineTo(x0, y0);
|
|
171
|
+
}
|
|
172
|
+
remaining -= dist;
|
|
173
|
+
dashIndex++;
|
|
174
|
+
dashIndex = dashIndex === this.dash.length ? 0 : dashIndex;
|
|
175
|
+
dashStart = 0;
|
|
176
|
+
}
|
|
177
|
+
// if (count >= 1000) console.log('failure', this.scale)
|
|
178
|
+
}
|
|
179
|
+
this.lineLength += length;
|
|
180
|
+
this.cursor.set(x, y);
|
|
181
|
+
return this;
|
|
182
|
+
};
|
|
183
|
+
DashLine.prototype.closePath = function () {
|
|
184
|
+
this.lineTo(this.start.x, this.start.y, true);
|
|
185
|
+
};
|
|
186
|
+
DashLine.prototype.circle = function (x, y, radius, points, matrix) {
|
|
187
|
+
if (points === void 0) { points = 80; }
|
|
188
|
+
var interval = (Math.PI * 2) / points;
|
|
189
|
+
var angle = 0;
|
|
190
|
+
var first;
|
|
191
|
+
if (matrix) {
|
|
192
|
+
first = new PIXI.Point(x + Math.cos(angle) * radius, y + Math.sin(angle) * radius);
|
|
193
|
+
matrix.apply(first, first);
|
|
194
|
+
this.moveTo(first.x, first.y);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
first = new PIXI.Point(x + Math.cos(angle) * radius, y + Math.sin(angle) * radius);
|
|
198
|
+
this.moveTo(first.x, first.y);
|
|
199
|
+
}
|
|
200
|
+
angle += interval;
|
|
201
|
+
for (var i = 1; i < points + 1; i++) {
|
|
202
|
+
var next = i === points
|
|
203
|
+
? first
|
|
204
|
+
: {
|
|
205
|
+
x: x + Math.cos(angle) * radius,
|
|
206
|
+
y: y + Math.sin(angle) * radius,
|
|
207
|
+
};
|
|
208
|
+
this.lineTo(next.x, next.y);
|
|
209
|
+
angle += interval;
|
|
210
|
+
}
|
|
211
|
+
return this;
|
|
212
|
+
};
|
|
213
|
+
DashLine.prototype.ellipse = function (x, y, radiusX, radiusY, points, matrix) {
|
|
214
|
+
if (points === void 0) { points = 80; }
|
|
215
|
+
var interval = (Math.PI * 2) / points;
|
|
216
|
+
var first = { x: 0, y: 0 };
|
|
217
|
+
var point = new PIXI.Point();
|
|
218
|
+
for (var i = 0; i < Math.PI * 2; i += interval) {
|
|
219
|
+
var x0 = x - radiusX * Math.sin(i);
|
|
220
|
+
var y0 = y - radiusY * Math.cos(i);
|
|
221
|
+
if (matrix) {
|
|
222
|
+
point.set(x0, y0);
|
|
223
|
+
matrix.apply(point, point);
|
|
224
|
+
x0 = point.x;
|
|
225
|
+
y0 = point.y;
|
|
226
|
+
}
|
|
227
|
+
if (i === 0) {
|
|
228
|
+
this.moveTo(x0, y0);
|
|
229
|
+
first = { x: x0, y: y0 };
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
this.lineTo(x0, y0);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this.lineTo(first.x, first.y, true);
|
|
236
|
+
return this;
|
|
237
|
+
};
|
|
238
|
+
DashLine.prototype.poly = function (points, matrix) {
|
|
239
|
+
var p = new PIXI.Point();
|
|
240
|
+
if (typeof points[0] === "number") {
|
|
241
|
+
if (matrix) {
|
|
242
|
+
p.set(points[0], points[1]);
|
|
243
|
+
matrix.apply(p, p);
|
|
244
|
+
this.moveTo(p.x, p.y);
|
|
245
|
+
for (var i = 2; i < points.length; i += 2) {
|
|
246
|
+
p.set(points[i], points[i + 1]);
|
|
247
|
+
matrix.apply(p, p);
|
|
248
|
+
this.lineTo(p.x, p.y, i === points.length - 2);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
this.moveTo(points[0], points[1]);
|
|
253
|
+
for (var i = 2; i < points.length; i += 2) {
|
|
254
|
+
this.lineTo(points[i], points[i + 1], i === points.length - 2);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else if (matrix) {
|
|
259
|
+
var point = points[0];
|
|
260
|
+
p.copyFrom(point);
|
|
261
|
+
matrix.apply(p, p);
|
|
262
|
+
this.moveTo(p.x, p.y);
|
|
263
|
+
for (var i = 1; i < points.length; i++) {
|
|
264
|
+
var point_1 = points[i];
|
|
265
|
+
p.copyFrom(point_1);
|
|
266
|
+
matrix.apply(p, p);
|
|
267
|
+
this.lineTo(p.x, p.y, i === points.length - 1);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
var point = points[0];
|
|
272
|
+
this.moveTo(point.x, point.y);
|
|
273
|
+
for (var i = 1; i < points.length; i++) {
|
|
274
|
+
var point_2 = points[i];
|
|
275
|
+
this.lineTo(point_2.x, point_2.y, i === points.length - 1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return this;
|
|
279
|
+
};
|
|
280
|
+
DashLine.prototype.rect = function (x, y, width, height, matrix) {
|
|
281
|
+
if (matrix) {
|
|
282
|
+
var p = new PIXI.Point();
|
|
283
|
+
// moveTo(x, y)
|
|
284
|
+
p.set(x, y);
|
|
285
|
+
matrix.apply(p, p);
|
|
286
|
+
this.moveTo(p.x, p.y);
|
|
287
|
+
// lineTo(x + width, y)
|
|
288
|
+
p.set(x + width, y);
|
|
289
|
+
matrix.apply(p, p);
|
|
290
|
+
this.lineTo(p.x, p.y);
|
|
291
|
+
// lineTo(x + width, y + height)
|
|
292
|
+
p.set(x + width, y + height);
|
|
293
|
+
matrix.apply(p, p);
|
|
294
|
+
this.lineTo(p.x, p.y);
|
|
295
|
+
// lineto(x, y + height)
|
|
296
|
+
p.set(x, y + height);
|
|
297
|
+
matrix.apply(p, p);
|
|
298
|
+
this.lineTo(p.x, p.y);
|
|
299
|
+
// lineTo(x, y, true)
|
|
300
|
+
p.set(x, y);
|
|
301
|
+
matrix.apply(p, p);
|
|
302
|
+
this.lineTo(p.x, p.y, true);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
this.moveTo(x, y)
|
|
306
|
+
.lineTo(x + width, y)
|
|
307
|
+
.lineTo(x + width, y + height)
|
|
308
|
+
.lineTo(x, y + height)
|
|
309
|
+
.lineTo(x, y, true);
|
|
310
|
+
}
|
|
311
|
+
return this;
|
|
312
|
+
};
|
|
313
|
+
DashLine.prototype.roundRect = function (x, y, width, height, cornerRadius, matrix) {
|
|
314
|
+
if (cornerRadius === void 0) { cornerRadius = 10; }
|
|
315
|
+
var minSize = Math.min(width, height);
|
|
316
|
+
cornerRadius = Math.min(cornerRadius, minSize / 2); // Ensure radius is valid
|
|
317
|
+
var p = new PIXI.Point();
|
|
318
|
+
// Helper function to move points using matrix
|
|
319
|
+
var transformPoint = function (px, py) {
|
|
320
|
+
if (matrix) {
|
|
321
|
+
p.set(px, py);
|
|
322
|
+
matrix.apply(p, p);
|
|
323
|
+
return { x: p.x, y: p.y };
|
|
324
|
+
}
|
|
325
|
+
return { x: px, y: py };
|
|
326
|
+
};
|
|
327
|
+
// Start at the top-left corner, moving to the first point
|
|
328
|
+
var start = transformPoint(x + cornerRadius, y);
|
|
329
|
+
this.moveTo(start.x, start.y);
|
|
330
|
+
// Top edge
|
|
331
|
+
var end = transformPoint(x + width - cornerRadius, y);
|
|
332
|
+
this.lineTo(end.x, end.y);
|
|
333
|
+
this.drawDashedArc(x + width - cornerRadius, y + cornerRadius, cornerRadius, -90, 0, matrix);
|
|
334
|
+
// Right edge
|
|
335
|
+
end = transformPoint(x + width, y + height - cornerRadius);
|
|
336
|
+
this.lineTo(end.x, end.y);
|
|
337
|
+
this.drawDashedArc(x + width - cornerRadius, y + height - cornerRadius, cornerRadius, 0, 90, matrix);
|
|
338
|
+
// Bottom edge
|
|
339
|
+
end = transformPoint(x + cornerRadius, y + height);
|
|
340
|
+
this.lineTo(end.x, end.y);
|
|
341
|
+
this.drawDashedArc(x + cornerRadius, y + height - cornerRadius, cornerRadius, 90, 180, matrix);
|
|
342
|
+
// Left edge
|
|
343
|
+
end = transformPoint(x, y + cornerRadius);
|
|
344
|
+
this.lineTo(end.x, end.y);
|
|
345
|
+
this.drawDashedArc(x + cornerRadius, y + cornerRadius, cornerRadius, 180, 270, matrix);
|
|
346
|
+
// Close path
|
|
347
|
+
this.lineTo(start.x, start.y, true);
|
|
348
|
+
return this;
|
|
349
|
+
};
|
|
350
|
+
DashLine.prototype.drawDashedArc = function (cx, cy, radius, startAngle, endAngle, matrix) {
|
|
351
|
+
var segments = 10; // Increase for smoother curves
|
|
352
|
+
var angleStep = (endAngle - startAngle) / segments;
|
|
353
|
+
for (var i = 1; i <= segments; i++) {
|
|
354
|
+
var nextPoint = getPointOnArc(cx, cy, radius, startAngle + i * angleStep, matrix);
|
|
355
|
+
this.lineTo(nextPoint.x, nextPoint.y);
|
|
356
|
+
}
|
|
357
|
+
return this;
|
|
358
|
+
};
|
|
359
|
+
// adjust the matrix for the dashed texture
|
|
360
|
+
DashLine.prototype.adjustStrokeStyle = function (angle) {
|
|
361
|
+
var strokeStyle = this.graphics.strokeStyle;
|
|
362
|
+
strokeStyle.matrix = new PIXI.Matrix();
|
|
363
|
+
if (angle) {
|
|
364
|
+
strokeStyle.matrix.rotate(angle);
|
|
365
|
+
}
|
|
366
|
+
if (this.scale !== 1) {
|
|
367
|
+
strokeStyle.matrix.scale(this.scale, this.scale);
|
|
368
|
+
}
|
|
369
|
+
var textureStart = -this.lineLength;
|
|
370
|
+
strokeStyle.matrix.translate(this.cursor.x + textureStart * Math.cos(angle), this.cursor.y + textureStart * Math.sin(angle));
|
|
371
|
+
this.graphics.stroke(strokeStyle);
|
|
372
|
+
};
|
|
373
|
+
// creates or uses cached texture
|
|
374
|
+
DashLine.getTexture = function (options, dashSize) {
|
|
375
|
+
var key = options.dash.toString();
|
|
376
|
+
if (DashLine.dashTextureCache[key]) {
|
|
377
|
+
return DashLine.dashTextureCache[key];
|
|
378
|
+
}
|
|
379
|
+
var canvas = document.createElement("canvas");
|
|
380
|
+
canvas.width = dashSize;
|
|
381
|
+
canvas.height = Math.ceil(options.width);
|
|
382
|
+
var context = canvas.getContext("2d");
|
|
383
|
+
if (!context) {
|
|
384
|
+
console.warn("Did not get context from canvas");
|
|
385
|
+
return undefined;
|
|
386
|
+
}
|
|
387
|
+
context.strokeStyle = "white";
|
|
388
|
+
context.globalAlpha = options.alpha;
|
|
389
|
+
context.lineWidth = options.width;
|
|
390
|
+
var x = 0;
|
|
391
|
+
var y = options.width / 2;
|
|
392
|
+
context.moveTo(x, y);
|
|
393
|
+
for (var i = 0; i < options.dash.length; i += 2) {
|
|
394
|
+
x += options.dash[i];
|
|
395
|
+
context.lineTo(x, y);
|
|
396
|
+
if (options.dash.length !== i + 1) {
|
|
397
|
+
x += options.dash[i + 1];
|
|
398
|
+
context.moveTo(x, y);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
context.stroke();
|
|
402
|
+
var texture = (DashLine.dashTextureCache[key] =
|
|
403
|
+
PIXI.Texture.from(canvas));
|
|
404
|
+
texture.source.scaleMode = "nearest";
|
|
405
|
+
return texture;
|
|
406
|
+
};
|
|
407
|
+
// cache of PIXI.Textures for dashed lines
|
|
408
|
+
DashLine.dashTextureCache = {};
|
|
409
|
+
return DashLine;
|
|
410
|
+
}());
|
|
411
|
+
exports.DashLine = DashLine;
|
|
412
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"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"}
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import * as PIXI from "pixi.js"
|
|
2
|
+
|
|
3
|
+
/** Define the dash: [dash length, gap size, dash size, gap size, ...] */
|
|
4
|
+
export type Dashes = number[]
|
|
5
|
+
|
|
6
|
+
export type DashLineOptions = {
|
|
7
|
+
dash?: Dashes
|
|
8
|
+
width?: number
|
|
9
|
+
color?: number
|
|
10
|
+
alpha?: number
|
|
11
|
+
scale?: number
|
|
12
|
+
useTexture?: boolean
|
|
13
|
+
useDots?: boolean
|
|
14
|
+
cap?: "butt" | "round" | "square"
|
|
15
|
+
join?: "bevel" | "miter" | "round"
|
|
16
|
+
alignment?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getPointOnArc(
|
|
20
|
+
cx: number,
|
|
21
|
+
cy: number,
|
|
22
|
+
radius: number,
|
|
23
|
+
angle: number,
|
|
24
|
+
matrix?: PIXI.Matrix
|
|
25
|
+
) {
|
|
26
|
+
const radian = (angle * Math.PI) / 180
|
|
27
|
+
const x = cx + Math.cos(radian) * radius
|
|
28
|
+
const y = cy + Math.sin(radian) * radius
|
|
29
|
+
|
|
30
|
+
if (matrix) {
|
|
31
|
+
const p = new PIXI.Point(x, y)
|
|
32
|
+
matrix.apply(p, p)
|
|
33
|
+
return { x: p.x, y: p.y }
|
|
34
|
+
}
|
|
35
|
+
return { x, y }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const dashLineOptionsDefault: Partial<DashLineOptions> = {
|
|
39
|
+
dash: [10, 5],
|
|
40
|
+
width: 1,
|
|
41
|
+
color: 0xffffff,
|
|
42
|
+
alpha: 1,
|
|
43
|
+
scale: 1,
|
|
44
|
+
useTexture: false,
|
|
45
|
+
alignment: 0.5,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class DashLine {
|
|
49
|
+
graphics: PIXI.Graphics
|
|
50
|
+
|
|
51
|
+
/** current length of the line */
|
|
52
|
+
lineLength: number = 0
|
|
53
|
+
|
|
54
|
+
/** cursor location */
|
|
55
|
+
cursor = new PIXI.Point()
|
|
56
|
+
|
|
57
|
+
/** desired scale of line */
|
|
58
|
+
scale = 1
|
|
59
|
+
|
|
60
|
+
// sanity check to ensure the lineStyle is still in use
|
|
61
|
+
private activeTexture: PIXI.Texture | undefined = undefined
|
|
62
|
+
|
|
63
|
+
private start: PIXI.Point = new PIXI.Point(0, 0)
|
|
64
|
+
|
|
65
|
+
private dashSize: number
|
|
66
|
+
private dash: number[]
|
|
67
|
+
|
|
68
|
+
private useTexture: boolean
|
|
69
|
+
private options: Required<DashLineOptions>
|
|
70
|
+
|
|
71
|
+
// cache of PIXI.Textures for dashed lines
|
|
72
|
+
static dashTextureCache: Record<string, PIXI.Texture> = {}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create a DashLine
|
|
76
|
+
* @param graphics
|
|
77
|
+
* @param [options]
|
|
78
|
+
* @param [options.useTexture=false] - use the texture based render (useful for very large or very small dashed lines)
|
|
79
|
+
* @param [options.dashes=[10,5] - an array holding the dash and gap (eg, [10, 5, 20, 5, ...])
|
|
80
|
+
* @param [options.width=1] - width of the dashed line
|
|
81
|
+
* @param [options.alpha=1] - alpha of the dashed line
|
|
82
|
+
* @param [options.color=0xffffff] - color of the dashed line
|
|
83
|
+
* @param [options.cap] - add a PIXI.LINE_CAP style to dashed lines (only works for useTexture: false)
|
|
84
|
+
* @param [options.join] - add a PIXI.LINE_JOIN style to the dashed lines (only works for useTexture: false)
|
|
85
|
+
* @param [options.alignment] - The alignment of any lines drawn (0.5 = middle, 1 = outer, 0 = inner)
|
|
86
|
+
*/
|
|
87
|
+
constructor(graphics: PIXI.Graphics, options: DashLineOptions = {}) {
|
|
88
|
+
this.graphics = graphics
|
|
89
|
+
const mergedOpts = {
|
|
90
|
+
...dashLineOptionsDefault,
|
|
91
|
+
...options,
|
|
92
|
+
} as Required<DashLineOptions>
|
|
93
|
+
this.dash = mergedOpts.dash!
|
|
94
|
+
this.dashSize = this.dash.reduce((a, b) => a + b)
|
|
95
|
+
this.useTexture = Boolean(mergedOpts.useTexture)
|
|
96
|
+
this.options = mergedOpts
|
|
97
|
+
this.setStrokeStyle()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** resets line style to enable dashed line (useful if lineStyle was changed on graphics element) */
|
|
101
|
+
setStrokeStyle() {
|
|
102
|
+
const options = this.options
|
|
103
|
+
if (this.useTexture) {
|
|
104
|
+
const texture = DashLine.getTexture(options, this.dashSize)
|
|
105
|
+
this.graphics.stroke({
|
|
106
|
+
width: options.width * options.scale,
|
|
107
|
+
color: options.color,
|
|
108
|
+
alpha: options.alpha,
|
|
109
|
+
texture,
|
|
110
|
+
alignment: options.alignment,
|
|
111
|
+
})
|
|
112
|
+
this.activeTexture = texture!
|
|
113
|
+
} else {
|
|
114
|
+
this.graphics.stroke({
|
|
115
|
+
width: options.width * options.scale,
|
|
116
|
+
color: options.color,
|
|
117
|
+
alpha: options.alpha,
|
|
118
|
+
cap: options.cap,
|
|
119
|
+
join: options.join,
|
|
120
|
+
alignment: options.alignment,
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
this.scale = options.scale
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private static distance(
|
|
127
|
+
x1: number,
|
|
128
|
+
y1: number,
|
|
129
|
+
x2: number,
|
|
130
|
+
y2: number
|
|
131
|
+
): number {
|
|
132
|
+
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
moveTo(x: number, y: number): this {
|
|
136
|
+
this.lineLength = 0
|
|
137
|
+
this.cursor.set(x, y)
|
|
138
|
+
this.start = new PIXI.Point(x, y)
|
|
139
|
+
this.graphics.moveTo(this.cursor.x, this.cursor.y)
|
|
140
|
+
return this
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
lineTo(x: number, y: number, closePath?: boolean): this {
|
|
144
|
+
if (this.lineLength === undefined) {
|
|
145
|
+
this.moveTo(0, 0)
|
|
146
|
+
}
|
|
147
|
+
const length = DashLine.distance(this.cursor.x, this.cursor.y, x, y)
|
|
148
|
+
const angle = Math.atan2(y - this.cursor.y, x - this.cursor.x)
|
|
149
|
+
const closed = closePath && x === this.start.x && y === this.start.y
|
|
150
|
+
if (this.useTexture) {
|
|
151
|
+
this.graphics.moveTo(this.cursor.x, this.cursor.y)
|
|
152
|
+
this.adjustStrokeStyle(angle)
|
|
153
|
+
if (closed && this.dash.length % 2 === 0) {
|
|
154
|
+
const gap = Math.min(this.dash[this.dash.length - 1], length)
|
|
155
|
+
this.graphics.lineTo(
|
|
156
|
+
x - Math.cos(angle) * gap,
|
|
157
|
+
y - Math.sin(angle) * gap
|
|
158
|
+
)
|
|
159
|
+
this.graphics.closePath()
|
|
160
|
+
} else {
|
|
161
|
+
this.graphics.lineTo(x, y)
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
const cos = Math.cos(angle)
|
|
165
|
+
const sin = Math.sin(angle)
|
|
166
|
+
let x0 = this.cursor.x
|
|
167
|
+
let y0 = this.cursor.y
|
|
168
|
+
|
|
169
|
+
// find the first part of the dash for this line
|
|
170
|
+
const place = this.lineLength % (this.dashSize * this.scale)
|
|
171
|
+
let dashIndex: number = 0
|
|
172
|
+
let dashStart: number = 0
|
|
173
|
+
let dashX = 0
|
|
174
|
+
for (let i = 0; i < this.dash.length; i++) {
|
|
175
|
+
const dashSize = this.dash[i] * this.scale
|
|
176
|
+
if (place < dashX + dashSize) {
|
|
177
|
+
dashIndex = i
|
|
178
|
+
dashStart = place - dashX
|
|
179
|
+
break
|
|
180
|
+
} else {
|
|
181
|
+
dashX += dashSize
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let remaining = length
|
|
186
|
+
// let count = 0
|
|
187
|
+
while (remaining > 0) {
|
|
188
|
+
// && count++ < 1000) {
|
|
189
|
+
const dashSize = this.dash[dashIndex] * this.scale - dashStart
|
|
190
|
+
const dist = remaining > dashSize ? dashSize : remaining
|
|
191
|
+
if (closed) {
|
|
192
|
+
const remainingDistance = DashLine.distance(
|
|
193
|
+
x0 + cos * dist,
|
|
194
|
+
y0 + sin * dist,
|
|
195
|
+
this.start.x,
|
|
196
|
+
this.start.y
|
|
197
|
+
)
|
|
198
|
+
if (remainingDistance <= dist) {
|
|
199
|
+
if (dashIndex % 2 === 0) {
|
|
200
|
+
const lastDash =
|
|
201
|
+
DashLine.distance(
|
|
202
|
+
x0,
|
|
203
|
+
y0,
|
|
204
|
+
this.start.x,
|
|
205
|
+
this.start.y
|
|
206
|
+
) -
|
|
207
|
+
this.dash[this.dash.length - 1] * this.scale
|
|
208
|
+
x0 += cos * lastDash
|
|
209
|
+
y0 += sin * lastDash
|
|
210
|
+
this.graphics.lineTo(x0, y0)
|
|
211
|
+
}
|
|
212
|
+
break
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
x0 += cos * dist
|
|
217
|
+
y0 += sin * dist
|
|
218
|
+
if (dashIndex % 2) {
|
|
219
|
+
this.graphics.moveTo(x0, y0)
|
|
220
|
+
} else {
|
|
221
|
+
this.graphics.lineTo(x0, y0)
|
|
222
|
+
}
|
|
223
|
+
remaining -= dist
|
|
224
|
+
|
|
225
|
+
dashIndex++
|
|
226
|
+
dashIndex = dashIndex === this.dash.length ? 0 : dashIndex
|
|
227
|
+
dashStart = 0
|
|
228
|
+
}
|
|
229
|
+
// if (count >= 1000) console.log('failure', this.scale)
|
|
230
|
+
}
|
|
231
|
+
this.lineLength += length
|
|
232
|
+
this.cursor.set(x, y)
|
|
233
|
+
return this
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
closePath() {
|
|
237
|
+
this.lineTo(this.start.x, this.start.y, true)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
circle(
|
|
241
|
+
x: number,
|
|
242
|
+
y: number,
|
|
243
|
+
radius: number,
|
|
244
|
+
points = 80,
|
|
245
|
+
matrix?: PIXI.Matrix
|
|
246
|
+
): this {
|
|
247
|
+
const interval = (Math.PI * 2) / points
|
|
248
|
+
let angle = 0
|
|
249
|
+
let first: PIXI.Point
|
|
250
|
+
if (matrix) {
|
|
251
|
+
first = new PIXI.Point(
|
|
252
|
+
x + Math.cos(angle) * radius,
|
|
253
|
+
y + Math.sin(angle) * radius
|
|
254
|
+
)
|
|
255
|
+
matrix.apply(first, first)
|
|
256
|
+
this.moveTo(first.x, first.y)
|
|
257
|
+
} else {
|
|
258
|
+
first = new PIXI.Point(
|
|
259
|
+
x + Math.cos(angle) * radius,
|
|
260
|
+
y + Math.sin(angle) * radius
|
|
261
|
+
)
|
|
262
|
+
this.moveTo(first.x, first.y)
|
|
263
|
+
}
|
|
264
|
+
angle += interval
|
|
265
|
+
for (let i = 1; i < points + 1; i++) {
|
|
266
|
+
const next =
|
|
267
|
+
i === points
|
|
268
|
+
? first
|
|
269
|
+
: {
|
|
270
|
+
x: x + Math.cos(angle) * radius,
|
|
271
|
+
y: y + Math.sin(angle) * radius,
|
|
272
|
+
}
|
|
273
|
+
this.lineTo(next.x, next.y)
|
|
274
|
+
angle += interval
|
|
275
|
+
}
|
|
276
|
+
return this
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
ellipse(
|
|
280
|
+
x: number,
|
|
281
|
+
y: number,
|
|
282
|
+
radiusX: number,
|
|
283
|
+
radiusY: number,
|
|
284
|
+
points = 80,
|
|
285
|
+
matrix?: PIXI.Matrix
|
|
286
|
+
): this {
|
|
287
|
+
const interval = (Math.PI * 2) / points
|
|
288
|
+
let first: { x: number; y: number } = { x: 0, y: 0 }
|
|
289
|
+
|
|
290
|
+
const point = new PIXI.Point()
|
|
291
|
+
for (let i = 0; i < Math.PI * 2; i += interval) {
|
|
292
|
+
let x0 = x - radiusX * Math.sin(i)
|
|
293
|
+
let y0 = y - radiusY * Math.cos(i)
|
|
294
|
+
if (matrix) {
|
|
295
|
+
point.set(x0, y0)
|
|
296
|
+
matrix.apply(point, point)
|
|
297
|
+
x0 = point.x
|
|
298
|
+
y0 = point.y
|
|
299
|
+
}
|
|
300
|
+
if (i === 0) {
|
|
301
|
+
this.moveTo(x0, y0)
|
|
302
|
+
first = { x: x0, y: y0 }
|
|
303
|
+
} else {
|
|
304
|
+
this.lineTo(x0, y0)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
this.lineTo(first.x, first.y, true)
|
|
308
|
+
return this
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
poly(points: PIXI.Point[] | number[], matrix?: PIXI.Matrix): this {
|
|
312
|
+
const p = new PIXI.Point()
|
|
313
|
+
if (typeof points[0] === "number") {
|
|
314
|
+
if (matrix) {
|
|
315
|
+
p.set(points[0] as number, points[1] as number)
|
|
316
|
+
matrix.apply(p, p)
|
|
317
|
+
this.moveTo(p.x, p.y)
|
|
318
|
+
for (let i = 2; i < points.length; i += 2) {
|
|
319
|
+
p.set(points[i] as number, points[i + 1] as number)
|
|
320
|
+
matrix.apply(p, p)
|
|
321
|
+
this.lineTo(p.x, p.y, i === points.length - 2)
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
this.moveTo(points[0] as number, points[1] as number)
|
|
325
|
+
for (let i = 2; i < points.length; i += 2) {
|
|
326
|
+
this.lineTo(
|
|
327
|
+
points[i] as number,
|
|
328
|
+
points[i + 1] as number,
|
|
329
|
+
i === points.length - 2
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
} else if (matrix) {
|
|
334
|
+
const point = points[0] as PIXI.Point
|
|
335
|
+
p.copyFrom(point)
|
|
336
|
+
matrix.apply(p, p)
|
|
337
|
+
this.moveTo(p.x, p.y)
|
|
338
|
+
for (let i = 1; i < points.length; i++) {
|
|
339
|
+
const point = points[i] as PIXI.Point
|
|
340
|
+
p.copyFrom(point)
|
|
341
|
+
matrix.apply(p, p)
|
|
342
|
+
this.lineTo(p.x, p.y, i === points.length - 1)
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
const point = points[0] as PIXI.Point
|
|
346
|
+
this.moveTo(point.x, point.y)
|
|
347
|
+
for (let i = 1; i < points.length; i++) {
|
|
348
|
+
const point = points[i] as PIXI.Point
|
|
349
|
+
this.lineTo(point.x, point.y, i === points.length - 1)
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return this
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
rect(
|
|
356
|
+
x: number,
|
|
357
|
+
y: number,
|
|
358
|
+
width: number,
|
|
359
|
+
height: number,
|
|
360
|
+
matrix?: PIXI.Matrix
|
|
361
|
+
): this {
|
|
362
|
+
if (matrix) {
|
|
363
|
+
const p = new PIXI.Point()
|
|
364
|
+
|
|
365
|
+
// moveTo(x, y)
|
|
366
|
+
p.set(x, y)
|
|
367
|
+
matrix.apply(p, p)
|
|
368
|
+
this.moveTo(p.x, p.y)
|
|
369
|
+
|
|
370
|
+
// lineTo(x + width, y)
|
|
371
|
+
p.set(x + width, y)
|
|
372
|
+
matrix.apply(p, p)
|
|
373
|
+
this.lineTo(p.x, p.y)
|
|
374
|
+
|
|
375
|
+
// lineTo(x + width, y + height)
|
|
376
|
+
p.set(x + width, y + height)
|
|
377
|
+
matrix.apply(p, p)
|
|
378
|
+
this.lineTo(p.x, p.y)
|
|
379
|
+
|
|
380
|
+
// lineto(x, y + height)
|
|
381
|
+
p.set(x, y + height)
|
|
382
|
+
matrix.apply(p, p)
|
|
383
|
+
this.lineTo(p.x, p.y)
|
|
384
|
+
|
|
385
|
+
// lineTo(x, y, true)
|
|
386
|
+
p.set(x, y)
|
|
387
|
+
matrix.apply(p, p)
|
|
388
|
+
this.lineTo(p.x, p.y, true)
|
|
389
|
+
} else {
|
|
390
|
+
this.moveTo(x, y)
|
|
391
|
+
.lineTo(x + width, y)
|
|
392
|
+
.lineTo(x + width, y + height)
|
|
393
|
+
.lineTo(x, y + height)
|
|
394
|
+
.lineTo(x, y, true)
|
|
395
|
+
}
|
|
396
|
+
return this
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
roundRect(
|
|
400
|
+
x: number,
|
|
401
|
+
y: number,
|
|
402
|
+
width: number,
|
|
403
|
+
height: number,
|
|
404
|
+
cornerRadius: number = 10,
|
|
405
|
+
matrix?: PIXI.Matrix
|
|
406
|
+
): this {
|
|
407
|
+
const minSize = Math.min(width, height)
|
|
408
|
+
cornerRadius = Math.min(cornerRadius, minSize / 2) // Ensure radius is valid
|
|
409
|
+
|
|
410
|
+
const p = new PIXI.Point()
|
|
411
|
+
|
|
412
|
+
// Helper function to move points using matrix
|
|
413
|
+
const transformPoint = (px: number, py: number) => {
|
|
414
|
+
if (matrix) {
|
|
415
|
+
p.set(px, py)
|
|
416
|
+
matrix.apply(p, p)
|
|
417
|
+
return { x: p.x, y: p.y }
|
|
418
|
+
}
|
|
419
|
+
return { x: px, y: py }
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Start at the top-left corner, moving to the first point
|
|
423
|
+
const start = transformPoint(x + cornerRadius, y)
|
|
424
|
+
this.moveTo(start.x, start.y)
|
|
425
|
+
|
|
426
|
+
// Top edge
|
|
427
|
+
let end = transformPoint(x + width - cornerRadius, y)
|
|
428
|
+
this.lineTo(end.x, end.y)
|
|
429
|
+
this.drawDashedArc(
|
|
430
|
+
x + width - cornerRadius,
|
|
431
|
+
y + cornerRadius,
|
|
432
|
+
cornerRadius,
|
|
433
|
+
-90,
|
|
434
|
+
0,
|
|
435
|
+
matrix
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
// Right edge
|
|
439
|
+
end = transformPoint(x + width, y + height - cornerRadius)
|
|
440
|
+
this.lineTo(end.x, end.y)
|
|
441
|
+
this.drawDashedArc(
|
|
442
|
+
x + width - cornerRadius,
|
|
443
|
+
y + height - cornerRadius,
|
|
444
|
+
cornerRadius,
|
|
445
|
+
0,
|
|
446
|
+
90,
|
|
447
|
+
matrix
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
// Bottom edge
|
|
451
|
+
end = transformPoint(x + cornerRadius, y + height)
|
|
452
|
+
this.lineTo(end.x, end.y)
|
|
453
|
+
this.drawDashedArc(
|
|
454
|
+
x + cornerRadius,
|
|
455
|
+
y + height - cornerRadius,
|
|
456
|
+
cornerRadius,
|
|
457
|
+
90,
|
|
458
|
+
180,
|
|
459
|
+
matrix
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
// Left edge
|
|
463
|
+
end = transformPoint(x, y + cornerRadius)
|
|
464
|
+
this.lineTo(end.x, end.y)
|
|
465
|
+
this.drawDashedArc(
|
|
466
|
+
x + cornerRadius,
|
|
467
|
+
y + cornerRadius,
|
|
468
|
+
cornerRadius,
|
|
469
|
+
180,
|
|
470
|
+
270,
|
|
471
|
+
matrix
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
// Close path
|
|
475
|
+
this.lineTo(start.x, start.y, true)
|
|
476
|
+
|
|
477
|
+
return this
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private drawDashedArc(
|
|
481
|
+
cx: number,
|
|
482
|
+
cy: number,
|
|
483
|
+
radius: number,
|
|
484
|
+
startAngle: number,
|
|
485
|
+
endAngle: number,
|
|
486
|
+
matrix?: PIXI.Matrix
|
|
487
|
+
): this {
|
|
488
|
+
const segments = 10 // Increase for smoother curves
|
|
489
|
+
const angleStep = (endAngle - startAngle) / segments
|
|
490
|
+
|
|
491
|
+
for (let i = 1; i <= segments; i++) {
|
|
492
|
+
const nextPoint = getPointOnArc(
|
|
493
|
+
cx,
|
|
494
|
+
cy,
|
|
495
|
+
radius,
|
|
496
|
+
startAngle + i * angleStep,
|
|
497
|
+
matrix
|
|
498
|
+
)
|
|
499
|
+
this.lineTo(nextPoint.x, nextPoint.y)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return this
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// adjust the matrix for the dashed texture
|
|
506
|
+
private adjustStrokeStyle(angle: number) {
|
|
507
|
+
const strokeStyle = this.graphics.strokeStyle
|
|
508
|
+
strokeStyle.matrix = new PIXI.Matrix()
|
|
509
|
+
if (angle) {
|
|
510
|
+
strokeStyle.matrix.rotate(angle)
|
|
511
|
+
}
|
|
512
|
+
if (this.scale !== 1) {
|
|
513
|
+
strokeStyle.matrix.scale(this.scale, this.scale)
|
|
514
|
+
}
|
|
515
|
+
const textureStart = -this.lineLength
|
|
516
|
+
strokeStyle.matrix.translate(
|
|
517
|
+
this.cursor.x + textureStart * Math.cos(angle),
|
|
518
|
+
this.cursor.y + textureStart * Math.sin(angle)
|
|
519
|
+
)
|
|
520
|
+
this.graphics.stroke(strokeStyle)
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// creates or uses cached texture
|
|
524
|
+
private static getTexture(
|
|
525
|
+
options: Required<DashLineOptions>,
|
|
526
|
+
dashSize: number
|
|
527
|
+
): PIXI.Texture | undefined {
|
|
528
|
+
const key = options.dash.toString()
|
|
529
|
+
if (DashLine.dashTextureCache[key]) {
|
|
530
|
+
return DashLine.dashTextureCache[key]
|
|
531
|
+
}
|
|
532
|
+
const canvas = document.createElement("canvas")
|
|
533
|
+
canvas.width = dashSize
|
|
534
|
+
canvas.height = Math.ceil(options.width)
|
|
535
|
+
const context = canvas.getContext("2d")
|
|
536
|
+
if (!context) {
|
|
537
|
+
console.warn("Did not get context from canvas")
|
|
538
|
+
return undefined
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
context.strokeStyle = "white"
|
|
542
|
+
context.globalAlpha = options.alpha
|
|
543
|
+
context.lineWidth = options.width
|
|
544
|
+
let x = 0
|
|
545
|
+
const y = options.width / 2
|
|
546
|
+
context.moveTo(x, y)
|
|
547
|
+
for (let i = 0; i < options.dash.length; i += 2) {
|
|
548
|
+
x += options.dash[i]
|
|
549
|
+
context.lineTo(x, y)
|
|
550
|
+
if (options.dash.length !== i + 1) {
|
|
551
|
+
x += options.dash[i + 1]
|
|
552
|
+
context.moveTo(x, y)
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
context.stroke()
|
|
556
|
+
const texture = (DashLine.dashTextureCache[key] =
|
|
557
|
+
PIXI.Texture.from(canvas))
|
|
558
|
+
texture.source.scaleMode = "nearest"
|
|
559
|
+
return texture
|
|
560
|
+
}
|
|
561
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@btfash/pixi-dashed-line",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "A pixi.js implementation to support dashed lines in PIXI.Graphics.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"browser": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc lib/index.ts --outDir dist --skipLibCheck --module commonjs --moduleResolution node --declaration --sourceMap",
|
|
10
|
+
"build-demo": "esbuild demo/index.ts --outfile=docs/index.js --bundle",
|
|
11
|
+
"prepublishOnly": "npm run build && npm run build-demo"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/*",
|
|
15
|
+
"lib/*"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/davidfig/pixi-dashed-line.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/davidfig/pixi-dashed-line/issues",
|
|
23
|
+
"email": "david@yopeyopey.com"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/davidfig/pixi-dashed-line#readme",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"dash",
|
|
28
|
+
"dots",
|
|
29
|
+
"pixi.js",
|
|
30
|
+
"dashed line",
|
|
31
|
+
"dotted",
|
|
32
|
+
"PIXI.Graphics"
|
|
33
|
+
],
|
|
34
|
+
"author": "David Figatner <david@yopeyopey.com> (https://yopeyopey.com)",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"pixi.js": "^8.8.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"esbuild": "^0.25.0",
|
|
41
|
+
"pixi-viewport": "^6.0.3",
|
|
42
|
+
"pixi.js": "^8.15.0",
|
|
43
|
+
"typescript": "^5.7.3"
|
|
44
|
+
}
|
|
45
|
+
}
|