@@ -47,18 +47,19 @@ export interface RenderOptions {
47
47
48
48
// Option to render guides (points, handles and viewport).
49
49
guides ?: boolean ;
50
+ boundingBox ?: boolean ;
50
51
}
51
52
52
53
// Safe array access at any index using a modulo operation that will always be positive.
53
54
const loopAccess = < T > ( arr : T [ ] ) => ( i : number ) : T => {
54
- return arr [ ( ( i % arr . length ) + arr . length ) % arr . length ] ;
55
+ return arr [ ( ( i % arr . length ) + arr . length ) % arr . length ] ;
55
56
} ;
56
57
57
58
// Translates a point's [x,y] cartesian coordinates into values relative to the viewport.
58
59
// Translates the angle from degrees to radians and moves the start angle a half rotation.
59
60
const cleanupPoint = ( point : Point , opt : RenderOptions ) : InternalPoint => {
60
61
const handles = point . handles || { angle : 0 , out : 0 , in : 0 } ;
61
- handles . angle = Math . PI + ( 2 * Math . PI * handles . angle / 360 ) ;
62
+ handles . angle = Math . PI + ( 2 * Math . PI * handles . angle ) / 360 ;
62
63
return {
63
64
x : point . x ,
64
65
y : opt . height - point . y ,
@@ -71,11 +72,11 @@ const renderClosed = (p: Point[], opt: RenderOptions): string => {
71
72
const points = p . map ( ( point ) => cleanupPoint ( point , opt ) ) ;
72
73
73
74
// Compute guides from input point data.
74
- const handles : { x1 : number , y1 : number , x2 : number , y2 : number } [ ] = [ ] ;
75
+ const handles : { x1 : number ; y1 : number ; x2 : number ; y2 : number } [ ] = [ ] ;
75
76
for ( let i = 0 ; i < points . length ; i ++ ) {
76
77
const { x, y, handles : hands } = loopAccess ( points ) ( i ) ;
77
78
78
- const next = loopAccess ( points ) ( i + 1 ) ;
79
+ const next = loopAccess ( points ) ( i + 1 ) ;
79
80
const nextHandles = next . handles ;
80
81
81
82
if ( hands === undefined ) {
@@ -96,7 +97,7 @@ const renderClosed = (p: Point[], opt: RenderOptions): string => {
96
97
let path = "" ;
97
98
for ( let i = 0 ; i <= points . length ; i ++ ) {
98
99
const point = loopAccess ( points ) ( i ) ;
99
- const hands = loopAccess ( handles ) ( i - 1 ) ;
100
+ const hands = loopAccess ( handles ) ( i - 1 ) ;
100
101
101
102
// Start at the first point's coordinates.
102
103
if ( i === 0 ) {
@@ -111,31 +112,39 @@ const renderClosed = (p: Point[], opt: RenderOptions): string => {
111
112
// Render guides if configured to do so.
112
113
let guides = "" ;
113
114
if ( opt . guides ) {
115
+ const color = opt . stroke || "black" ;
116
+ const size = opt . strokeWidth || 1 ;
117
+
114
118
// Bounding box.
115
- guides += `
116
- <rect x="0" y="0" width="${ opt . width } " height="${ opt . height } "
117
- fill="none" stroke="black" stroke-width="1" stroke-dasharray="2" />` ;
119
+ if ( opt . boundingBox ) {
120
+ guides += `
121
+ <rect x="0" y="0" width="${ opt . width } " height="${ opt . height } " fill="none"
122
+ stroke="${ color } " stroke-width="${ 2 * size } " stroke-dasharray="${ 2 * size } " />` ;
123
+ }
118
124
119
125
// Points and handles.
120
126
for ( let i = 0 ; i < points . length ; i ++ ) {
121
127
const { x, y} = loopAccess ( points ) ( i ) ;
122
128
const hands = loopAccess ( handles ) ( i ) ;
123
- const nextPoint = loopAccess ( points ) ( i + 1 ) ;
129
+ const nextPoint = loopAccess ( points ) ( i + 1 ) ;
124
130
125
131
guides += `
126
132
<line x1="${ x } " y1="${ y } " x2="${ hands . x1 } " y2="${ hands . y1 } "
127
- stroke-width="1 " stroke="black " />
133
+ stroke-width="${ size } " stroke="${ color } " />
128
134
<line x1="${ nextPoint . x } " y1="${ nextPoint . y } " x2="${ hands . x2 } " y2="${ hands . y2 } "
129
- stroke-width="1 " stroke="black " stroke-dasharray="2 " />
130
- <circle cx="${ hands . x1 } " cy="${ hands . y1 } " r="1 "
131
- fill="black " />
132
- <circle cx="${ hands . x2 } " cy="${ hands . y2 } " r="1 "
133
- fill="black " />
134
- <circle cx="${ x } " cy="${ y } " r="2 " fill="black " />` ;
135
+ stroke-width="${ size } " stroke="${ color } " stroke-dasharray="${ 2 * size } " />
136
+ <circle cx="${ hands . x1 } " cy="${ hands . y1 } " r="${ size } "
137
+ fill="${ color } " />
138
+ <circle cx="${ hands . x2 } " cy="${ hands . y2 } " r="${ size } "
139
+ fill="${ color } " />
140
+ <circle cx="${ x } " cy="${ y } " r="${ 2 * size } " fill="${ color } " />` ;
135
141
}
136
142
}
137
143
138
- return ( `
144
+ const stroke = opt . stroke || ( opt . guides ? "black" : "none" ) ;
145
+ const strokeWidth = opt . strokeWidth || ( opt . guides ? 1 : 0 ) ;
146
+
147
+ return `
139
148
<svg
140
149
width="${ opt . width } "
141
150
height="${ opt . height } "
@@ -144,26 +153,32 @@ const renderClosed = (p: Point[], opt: RenderOptions): string => {
144
153
>
145
154
<g transform="${ opt . transform || "" } ">
146
155
<path
147
- stroke="${ opt . stroke || "none" } "
148
- stroke-width="${ opt . strokeWidth || 0 } "
156
+ stroke="${ stroke } "
157
+ stroke-width="${ strokeWidth } "
149
158
fill="${ opt . fill || "none" } "
150
159
d="${ path } "
151
160
/>
152
161
${ guides }
153
162
</g>
154
163
</svg>
155
- ` ) . replace ( / \s + / g, " " ) ;
164
+ ` . replace ( / \s + / g, " " ) ;
156
165
} ;
157
166
158
- console . log ( renderClosed ( [
159
- { x : 700 , y : 200 , handles : { angle : - 135 , out : 80 , in : 80 } } ,
160
- { x : 300 , y : 200 , handles : { angle : 135 , out : 80 , in : 80 } } ,
161
- { x : 300 , y : 600 , handles : { angle : 45 , out : 80 , in : 80 } } ,
162
- { x : 700 , y : 600 , handles : { angle : - 45 , out : 80 , in : 80 } } ,
163
- ] , {
164
- width : 1000 ,
165
- height : 800 ,
166
- stroke : "blue" ,
167
- strokeWidth : 1 ,
168
- guides : true ,
169
- } ) ) ;
167
+ console . log (
168
+ renderClosed (
169
+ [
170
+ { x : 700 , y : 200 , handles : { angle : - 135 , out : 80 , in : 80 } } ,
171
+ { x : 300 , y : 200 , handles : { angle : 135 , out : 80 , in : 80 } } ,
172
+ { x : 300 , y : 600 , handles : { angle : 45 , out : 80 , in : 80 } } ,
173
+ { x : 700 , y : 600 , handles : { angle : - 45 , out : 80 , in : 80 } } ,
174
+ ] ,
175
+ {
176
+ width : 1000 ,
177
+ height : 800 ,
178
+ fill : "pink" ,
179
+ stroke : "red" ,
180
+ strokeWidth : 2 ,
181
+ guides : true ,
182
+ } ,
183
+ ) ,
184
+ ) ;
0 commit comments