Skip to content

Commit 79042f7

Browse files
authored
Merge pull request #13636 from jonobr1/13478-svg-loader
SVGLoader Additions
2 parents f10400e + a38e937 commit 79042f7

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed

examples/js/loaders/SVGLoader.js

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,26 @@ THREE.SVGLoader.prototype = {
5858
paths.push( parseRectNode( node ) );
5959
break;
6060

61+
case 'polygon':
62+
paths.push( parsePolygonNode( node ) );
63+
break;
64+
65+
case 'polyline':
66+
paths.push( parsePolylineNode( node ) );
67+
break;
68+
69+
case 'circle':
70+
paths.push( parseCircleNode( node ) );
71+
break;
72+
73+
case 'ellipse':
74+
paths.push( parseEllipseNode( node ) );
75+
break;
76+
77+
case 'line':
78+
paths.push( parseLineNode( node ) );
79+
break;
80+
6181
default:
6282
console.log( node );
6383

@@ -71,6 +91,7 @@ THREE.SVGLoader.prototype = {
7191

7292
var path = new THREE.ShapePath();
7393
var point = new THREE.Vector2();
94+
var control = new THREE.Vector2();
7495

7596
var d = node.getAttribute( 'd' );
7697

@@ -90,25 +111,33 @@ THREE.SVGLoader.prototype = {
90111
case 'M':
91112
var numbers = parseFloats( data );
92113
point.fromArray( numbers );
114+
control.x = point.x;
115+
control.y = point.y;
93116
path.moveTo( point.x, point.y );
94117
break;
95118

96119
case 'H':
97120
var numbers = parseFloats( data );
98121
point.x = numbers[ 0 ];
122+
control.x = point.x;
123+
control.y = point.y;
99124
path.lineTo( point.x, point.y );
100125
break;
101126

102127
case 'V':
103128
var numbers = parseFloats( data );
104129
point.y = numbers[ 0 ];
130+
control.x = point.x;
131+
control.y = point.y;
105132
path.lineTo( point.x, point.y );
106133
break;
107134

108135
case 'L':
109136
var numbers = parseFloats( data );
110137
point.x = numbers[ 0 ];
111138
point.y = numbers[ 1 ];
139+
control.x = point.x;
140+
control.y = point.y;
112141
path.lineTo( point.x, point.y );
113142
break;
114143

@@ -122,26 +151,93 @@ THREE.SVGLoader.prototype = {
122151
numbers[ 4 ],
123152
numbers[ 5 ],
124153
);
154+
control.x = numbers[ 2 ];
155+
control.y = numbers[ 3 ];
125156
point.x = numbers[ 4 ];
126157
point.y = numbers[ 5 ];
127158
break;
128159

160+
case 'S':
161+
var numbers = parseFloats( data );
162+
path.bezierCurveTo(
163+
getReflection( point.x, control.x ),
164+
getReflection( point.y, control.y ),
165+
numbers[ 0 ],
166+
numbers[ 1 ],
167+
numbers[ 2 ],
168+
numbers[ 3 ]
169+
);
170+
control.x = numbers[ 0 ];
171+
control.y = numbers[ 1 ];
172+
point.x = numbers[ 2 ];
173+
point.y = numbers[ 3 ];
174+
break;
175+
176+
case 'Q':
177+
var numbers = parseFloats( data );
178+
path.quadraticCurveTo(
179+
numbers[ 0 ],
180+
numbers[ 1 ],
181+
numbers[ 2 ],
182+
numbers[ 3 ]
183+
);
184+
control.x = numbers[ 0 ];
185+
control.y = numbers[ 1 ];
186+
point.x = numbers[ 2 ];
187+
point.y = numbers[ 3 ];
188+
break;
189+
190+
case 'T':
191+
var numbers = parseFloats( data );
192+
var rx = getReflection( point.x, control.x );
193+
var ry = getReflection( point.y, control.y );
194+
path.quadraticCurveTo(
195+
rx,
196+
ry,
197+
numbers[ 0 ],
198+
numbers[ 1 ]
199+
);
200+
control.x = rx;
201+
control.y = ry;
202+
point.x = numbers[ 0 ];
203+
point.y = numbers[ 1 ];
204+
break;
205+
206+
case 'A':
207+
// TODO:
208+
break;
209+
210+
case 'm':
211+
var numbers = parseFloats( data );
212+
point.x += numbers[ 0 ];
213+
point.y += numbers[ 1 ];
214+
control.x = point.x;
215+
control.y = point.y;
216+
path.moveTo( point.x, point.y );
217+
break;
218+
129219
case 'h':
130220
var numbers = parseFloats( data );
131221
point.x += numbers[ 0 ];
222+
control.x = point.x;
223+
control.y = point.y;
132224
path.lineTo( point.x, point.y );
133225
break;
134226

135227
case 'v':
136228
var numbers = parseFloats( data );
137229
point.y += numbers[ 0 ];
230+
control.x = point.x;
231+
control.y = point.y;
138232
path.lineTo( point.x, point.y );
139233
break;
140234

141235
case 'l':
142236
var numbers = parseFloats( data );
143237
point.x += numbers[ 0 ];
144238
point.y += numbers[ 1 ];
239+
control.x = point.x;
240+
control.y = point.y;
145241
path.lineTo( point.x, point.y );
146242
break;
147243

@@ -159,6 +255,58 @@ THREE.SVGLoader.prototype = {
159255
point.y += numbers[ 5 ];
160256
break;
161257

258+
case 's':
259+
var numbers = parseFloats( data );
260+
path.bezierCurveTo(
261+
// TODO: Not sure if point needs
262+
// to be added to reflection...
263+
getReflection( point.x, control.x ),
264+
getReflection( point.y, control.y ),
265+
point.x + numbers[ 0 ],
266+
point.y + numbers[ 1 ],
267+
point.x + numbers[ 2 ],
268+
point.y + numbers[ 3 ]
269+
);
270+
control.x = point.x + numbers[ 0 ];
271+
control.y = point.y + numbers[ 1 ];
272+
point.x += numbers[ 2 ];
273+
point.y += numbers[ 3 ];
274+
break;
275+
276+
case 'q':
277+
var numbers = parseFloats( data );
278+
path.quadraticCurveTo(
279+
point.x + numbers[ 0 ],
280+
point.y + numbers[ 1 ],
281+
point.x + numbers[ 2 ],
282+
point.y + numbers[ 3 ]
283+
);
284+
control.x = point.x + numbers[ 0 ];
285+
control.y = point.y + numbers[ 1 ];
286+
point.x += numbers[ 2 ];
287+
point.y += numbers[ 3 ];
288+
break;
289+
290+
case 't':
291+
var numbers = parseFloats( data );
292+
var rx = getReflection( point.x, control.x );
293+
var ry = getReflection( point.y, control.y );
294+
path.quadraticCurveTo(
295+
rx,
296+
ry,
297+
point.x + numbers[ 0 ],
298+
point.y + numbers[ 1 ]
299+
);
300+
control.x = rx;
301+
control.y = ry;
302+
point.x = point.x + numbers[ 0 ];
303+
point.y = point.y + numbers[ 1 ];
304+
break;
305+
306+
case 'a':
307+
// TODO:
308+
break;
309+
162310
case 'Z':
163311
case 'z':
164312
path.currentPath.autoClose = true;
@@ -191,6 +339,117 @@ THREE.SVGLoader.prototype = {
191339

192340
}
193341

342+
function parsePolygonNode( node ) {
343+
344+
function iterator( match, a, b ) {
345+
346+
var x = parseFloat( a );
347+
var y = parseFloat( b );
348+
349+
if ( index === 0 ) {
350+
path.moveTo( x, y );
351+
} else {
352+
path.lineTo( x, y );
353+
}
354+
355+
index++;
356+
357+
}
358+
359+
var regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
360+
var path = new THREE.ShapePath();
361+
var index = 0;
362+
363+
node.getAttribute( 'points' ).replace(regex, iterator);
364+
365+
path.currentPath.autoClose = true;
366+
367+
return path;
368+
369+
}
370+
371+
function parsePolylineNode( node ) {
372+
373+
function iterator( match, a, b ) {
374+
375+
var x = parseFloat( a );
376+
var y = parseFloat( b );
377+
378+
if ( index === 0 ) {
379+
path.moveTo( x, y );
380+
} else {
381+
path.lineTo( x, y );
382+
}
383+
384+
index++;
385+
386+
}
387+
388+
var regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
389+
var path = new THREE.ShapePath();
390+
var index = 0;
391+
392+
node.getAttribute( 'points' ).replace(regex, iterator);
393+
394+
path.currentPath.autoClose = false;
395+
396+
return path;
397+
398+
}
399+
400+
function parseCircleNode( node ) {
401+
402+
var x = parseFloat( node.getAttribute( 'cx' ) );
403+
var y = parseFloat( node.getAttribute( 'cy' ) );
404+
var r = parseFloat( node.getAttribute( 'r' ) );
405+
406+
var path = new THREE.ShapePath();
407+
408+
path.currentPath.absarc( x, y, r, 0, Math.PI * 2 );
409+
410+
return path;
411+
412+
}
413+
414+
function parseEllipseNode( node ) {
415+
416+
var x = parseFloat( node.getAttribute( 'cx' ) );
417+
var y = parseFloat( node.getAttribute( 'cy' ) );
418+
var rx parseFloat( node.getAttribute( 'rx' ) );
419+
var ry = parseFloat( node.getAttribute( 'ry' ) );
420+
421+
var path = new THREE.ShapePath();
422+
423+
path.currentPath.absellipse( x, y, rx, ry, 0, Math.PI * 2 );
424+
425+
return path;
426+
427+
}
428+
429+
function parseLineNode( node ) {
430+
431+
var x1 = parseFloat( node.getAttribute( 'x1' ) );
432+
var y1 = parseFloat( node.getAttribute( 'y1' ) );
433+
var x2 = parseFloat( node.getAttribute( 'x2' ) );
434+
var y2 = parseFloat( node.getAttribute( 'y2' ) );
435+
436+
var path = new THREE.ShapePath();
437+
path.moveTo( x1, y1 );
438+
path.lineTo( x2, y2 );
439+
path.currentPath.autoClose = false;
440+
441+
return path;
442+
443+
}
444+
445+
// http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
446+
447+
function getReflection( a, b ) {
448+
449+
return 2 * a - ( b - a );
450+
451+
}
452+
194453
function parseFloats( string ) {
195454

196455
var array = string.split( /[\s,]+|(?=\s?[+\-])/ );

0 commit comments

Comments
 (0)