@teachinglab/omd 0.4.1 → 0.4.3
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/canvas/index.js +1 -0
- package/index.js +3 -0
- package/package.json +1 -2
- package/jsvg/jsvg.js +0 -898
- package/jsvg/jsvgComponents.js +0 -359
package/canvas/index.js
CHANGED
package/index.js
CHANGED
|
@@ -17,6 +17,9 @@ export * from './canvas/index.js';
|
|
|
17
17
|
// Export everything from the visualization components
|
|
18
18
|
export * from './src/index.js';
|
|
19
19
|
|
|
20
|
+
// Explicitly export canvas components to ensure proper resolution
|
|
21
|
+
export { omdCanvas } from './canvas/core/omdCanvas.js';
|
|
22
|
+
export { createCanvas } from './canvas/index.js';
|
|
20
23
|
// Re-export canvas helpers/events so package consumers can import them from the package root
|
|
21
24
|
export { EventManager } from './canvas/events/eventManager.js';
|
|
22
25
|
|
package/package.json
CHANGED
package/jsvg/jsvg.js
DELETED
|
@@ -1,898 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// ================ jsvgObject ================================= //
|
|
4
|
-
|
|
5
|
-
export class jsvgObject
|
|
6
|
-
{
|
|
7
|
-
constructor()
|
|
8
|
-
{
|
|
9
|
-
this.name = "";
|
|
10
|
-
this.xpos = 0;
|
|
11
|
-
this.scale = 1.0;
|
|
12
|
-
this.rotation = 0.0;
|
|
13
|
-
this.ypos = 0;
|
|
14
|
-
this.width = 0;
|
|
15
|
-
this.height = 0;
|
|
16
|
-
this.opacity = 1.0;
|
|
17
|
-
this.visible = true;
|
|
18
|
-
this.svgObject = null;
|
|
19
|
-
this.childList = [];
|
|
20
|
-
this.parent = null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// set properties
|
|
24
|
-
|
|
25
|
-
setName( N )
|
|
26
|
-
{
|
|
27
|
-
this.name = N;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
setPosition( x, y )
|
|
31
|
-
{
|
|
32
|
-
this.xpos = x;
|
|
33
|
-
this.ypos = y;
|
|
34
|
-
this.updateTransform();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
setScale( s )
|
|
38
|
-
{
|
|
39
|
-
this.scale = s;
|
|
40
|
-
this.updateTransform();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
setRotation( r )
|
|
44
|
-
{
|
|
45
|
-
this.rotation = r;
|
|
46
|
-
this.updateTransform();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
updateTransform()
|
|
50
|
-
{
|
|
51
|
-
// Ensure xpos and ypos are valid numbers
|
|
52
|
-
const x = isNaN(this.xpos) ? 0 : this.xpos;
|
|
53
|
-
const y = isNaN(this.ypos) ? 0 : this.ypos;
|
|
54
|
-
|
|
55
|
-
var transformParams = " translate(" + x.toString() + "," + y.toString() + ") "
|
|
56
|
-
if ( this.scale != 1.0 )
|
|
57
|
-
transformParams += " scale(" + this.scale.toString() + ")";
|
|
58
|
-
if ( this.rotation != 0.0 )
|
|
59
|
-
transformParams += " rotate(" + this.rotation + ")";
|
|
60
|
-
this.svgObject.setAttribute("transform", transformParams );
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
setWidth( w )
|
|
64
|
-
{
|
|
65
|
-
this.width = w;
|
|
66
|
-
this.svgObject.setAttribute("width", this.width.toString() );
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
setHeight( h )
|
|
70
|
-
{
|
|
71
|
-
this.height = h;
|
|
72
|
-
this.svgObject.setAttribute("height", this.height.toString() );
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
setWidthAndHeight( w,h )
|
|
76
|
-
{
|
|
77
|
-
this.setWidth( w );
|
|
78
|
-
this.setHeight( h );
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
setFillColor( color )
|
|
82
|
-
{
|
|
83
|
-
this.svgObject.setAttribute( "fill", color );
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
setStrokeColor( color )
|
|
87
|
-
{
|
|
88
|
-
this.svgObject.setAttribute( "stroke", color );
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
setStrokeWidth( sW )
|
|
92
|
-
{
|
|
93
|
-
this.svgObject.setAttribute( "stroke-width", sW.toString() );
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
setOpacity( opacity )
|
|
97
|
-
{
|
|
98
|
-
this.opacity = opacity;
|
|
99
|
-
this.svgObject.style.opacity = opacity;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
setDropShadow()
|
|
103
|
-
{
|
|
104
|
-
// this is a generic dropshadow
|
|
105
|
-
this.svgObject.style.filter = "drop-shadow(0px 3px 6px rgba(0, 0, 0, 0.4))";
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
show()
|
|
109
|
-
{
|
|
110
|
-
this.visible = true;
|
|
111
|
-
this.svgObject.style.display = "";
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
hide()
|
|
115
|
-
{
|
|
116
|
-
this.visible = false;
|
|
117
|
-
this.svgObject.style.display = "none";
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// update
|
|
121
|
-
|
|
122
|
-
update()
|
|
123
|
-
{
|
|
124
|
-
if ( ! this.visible )
|
|
125
|
-
return;
|
|
126
|
-
|
|
127
|
-
for( var C of this.childList )
|
|
128
|
-
{
|
|
129
|
-
C.update();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// child stuff
|
|
134
|
-
|
|
135
|
-
addChild( child )
|
|
136
|
-
{
|
|
137
|
-
if ( this.svgObject && child.svgObject )
|
|
138
|
-
{
|
|
139
|
-
this.childList.push( child );
|
|
140
|
-
this.svgObject.appendChild( child.svgObject );
|
|
141
|
-
child.parent = this;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
getChild( index )
|
|
146
|
-
{
|
|
147
|
-
return this.childList[index];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
replaceChild( newChild, oldChild )
|
|
151
|
-
{
|
|
152
|
-
// replace the node
|
|
153
|
-
this.svgObject.replaceChild( newChild.svgObject, oldChild.svgObject );
|
|
154
|
-
|
|
155
|
-
// replace in childList
|
|
156
|
-
for ( var i=0; i<this.childList.length; i++ )
|
|
157
|
-
{
|
|
158
|
-
if ( this.childList[i] == oldChild )
|
|
159
|
-
{
|
|
160
|
-
this.childList[i] = newChild;
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
oldChild.parent = null;
|
|
166
|
-
newChild.parent = this;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
getNumberOfChildren()
|
|
170
|
-
{
|
|
171
|
-
return this.childList.length;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
removeChild( C )
|
|
175
|
-
{
|
|
176
|
-
const index = this.childList.indexOf(C);
|
|
177
|
-
this.removeChildByIndex( index );
|
|
178
|
-
C.parent = null;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
removeChildByIndex( index )
|
|
182
|
-
{
|
|
183
|
-
if (index >= 0)
|
|
184
|
-
{
|
|
185
|
-
var C = this.childList[index];
|
|
186
|
-
this.childList.splice(index, 1);
|
|
187
|
-
this.svgObject.removeChild( C.svgObject );
|
|
188
|
-
C.parent = null;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
removeAllChildren()
|
|
193
|
-
{
|
|
194
|
-
while( this.svgObject.firstChild )
|
|
195
|
-
{
|
|
196
|
-
this.svgObject.removeChild( this.svgObject.lastChild );
|
|
197
|
-
}
|
|
198
|
-
this.childList = [];
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
sortChildren( sortFunction )
|
|
202
|
-
{
|
|
203
|
-
this.childList.sort( sortFunction );
|
|
204
|
-
|
|
205
|
-
// If the child is a reference to an existing node in the document, appendChild() moves it from its current position to the new positio
|
|
206
|
-
this.childList.forEach(child => this.svgObject.appendChild( child.svgObject ));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// set up events
|
|
210
|
-
setClickCallback( callback )
|
|
211
|
-
{
|
|
212
|
-
if ( this.svgObject )
|
|
213
|
-
{
|
|
214
|
-
var outerThis = this;
|
|
215
|
-
this.svgObject.onclick = function() { callback(outerThis) };
|
|
216
|
-
this.svgObject.style.cursor = "pointer";
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
enableDragging()
|
|
221
|
-
{
|
|
222
|
-
this.svgObject.style.cursor = "pointer";
|
|
223
|
-
|
|
224
|
-
// on mouse down
|
|
225
|
-
var outerThis = this;
|
|
226
|
-
this.svgObject.onmousedown = function(E)
|
|
227
|
-
{
|
|
228
|
-
// console.log("mouse down");
|
|
229
|
-
outerThis.lastX = E.clientX;
|
|
230
|
-
outerThis.lastY = E.clientY;
|
|
231
|
-
|
|
232
|
-
// register on mouse move function (unregister on mouseup)
|
|
233
|
-
window.onmousemove = function(E)
|
|
234
|
-
{
|
|
235
|
-
// console.log("mouse move");
|
|
236
|
-
var dX = E.clientX - outerThis.lastX; // this method works if there's no scaling or rotation
|
|
237
|
-
var dY = E.clientY - outerThis.lastY;
|
|
238
|
-
outerThis.lastX = E.clientX;
|
|
239
|
-
outerThis.lastY = E.clientY;
|
|
240
|
-
outerThis.setPosition( outerThis.xpos+dX, outerThis.ypos+dY );
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// on mouse up
|
|
244
|
-
window.onmouseup = function()
|
|
245
|
-
{
|
|
246
|
-
// console.log("mouse up");
|
|
247
|
-
window.onmousemove = null;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// ================ jsvgContainer ================================= //
|
|
255
|
-
|
|
256
|
-
export class jsvgContainer extends jsvgObject
|
|
257
|
-
{
|
|
258
|
-
constructor()
|
|
259
|
-
{
|
|
260
|
-
super();
|
|
261
|
-
|
|
262
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
263
|
-
this.svgObject = document.createElementNS(svgNS, "svg");
|
|
264
|
-
this.svgObject.setAttribute("x", "0");
|
|
265
|
-
this.svgObject.setAttribute("y", "0");
|
|
266
|
-
this.svgObject.setAttribute("width", "500");
|
|
267
|
-
this.svgObject.setAttribute("height", "500");
|
|
268
|
-
this.svgObject.setAttribute("backgroundColor", "blue");
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
setViewbox( w, h )
|
|
272
|
-
{
|
|
273
|
-
this.setWidth(w);
|
|
274
|
-
this.setHeight(h);
|
|
275
|
-
var viewBoxParams = "0 0 " + w.toString() + " " + h.toString();
|
|
276
|
-
this.svgObject.setAttribute("viewBox", viewBoxParams );
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// ================ jsvgGroup ================================= //
|
|
281
|
-
|
|
282
|
-
export class jsvgGroup extends jsvgObject
|
|
283
|
-
{
|
|
284
|
-
constructor()
|
|
285
|
-
{
|
|
286
|
-
super();
|
|
287
|
-
|
|
288
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
289
|
-
this.svgObject = document.createElementNS(svgNS, "g");
|
|
290
|
-
this.svgObject.setAttribute("x", "0");
|
|
291
|
-
this.svgObject.setAttribute("y", "0");
|
|
292
|
-
this.svgObject.setAttribute("width", "500");
|
|
293
|
-
this.svgObject.setAttribute("height", "500");
|
|
294
|
-
this.svgObject.setAttribute("viewBox", "0 0 500 500");
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// ================ jsvgLine ================================= //
|
|
299
|
-
|
|
300
|
-
export class jsvgLine extends jsvgObject
|
|
301
|
-
{
|
|
302
|
-
constructor()
|
|
303
|
-
{
|
|
304
|
-
super();
|
|
305
|
-
|
|
306
|
-
this.x1 = 0;
|
|
307
|
-
this.y1 = 0;
|
|
308
|
-
this.x2 = 100;
|
|
309
|
-
this.y2 = 100;
|
|
310
|
-
|
|
311
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
312
|
-
this.svgObject = document.createElementNS(svgNS, "line");
|
|
313
|
-
this.svgObject.setAttribute("x1", "0");
|
|
314
|
-
this.svgObject.setAttribute("y1", "0");
|
|
315
|
-
this.svgObject.setAttribute("x2", "100");
|
|
316
|
-
this.svgObject.setAttribute("y2", "100");
|
|
317
|
-
|
|
318
|
-
this.setStrokeColor("black");
|
|
319
|
-
this.setStrokeWidth( 1 );
|
|
320
|
-
|
|
321
|
-
this.setEndpointA( this.x1, this.y1 );
|
|
322
|
-
this.setEndpointB( this.x2, this.y2 );
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
setEndpointA( x, y )
|
|
326
|
-
{
|
|
327
|
-
this.x1 = x;
|
|
328
|
-
this.y1 = y;
|
|
329
|
-
this.svgObject.setAttribute("x1", x.toString() );
|
|
330
|
-
this.svgObject.setAttribute("y1", y.toString() );
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
setEndpointB( x, y )
|
|
334
|
-
{
|
|
335
|
-
this.x2 = x;
|
|
336
|
-
this.y2 = y;
|
|
337
|
-
this.svgObject.setAttribute("x2", x.toString() );
|
|
338
|
-
this.svgObject.setAttribute("y2", y.toString() );
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
setEndpoints( x1,y1, x2,y2 )
|
|
342
|
-
{
|
|
343
|
-
this.setEndpointA( x1,y1 );
|
|
344
|
-
this.setEndpointB( x2,y2 );
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// ================ jsvgRect ================================= //
|
|
349
|
-
|
|
350
|
-
export class jsvgRect extends jsvgObject
|
|
351
|
-
{
|
|
352
|
-
constructor()
|
|
353
|
-
{
|
|
354
|
-
super();
|
|
355
|
-
|
|
356
|
-
this.cornerRadius = 0;
|
|
357
|
-
|
|
358
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
359
|
-
this.svgObject = document.createElementNS(svgNS, "rect");
|
|
360
|
-
this.setWidthAndHeight( 100,100 );
|
|
361
|
-
this.setFillColor( "white" );
|
|
362
|
-
this.setStrokeColor( "black" );
|
|
363
|
-
this.setStrokeWidth( 0 );
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
setCornerRadius( r )
|
|
367
|
-
{
|
|
368
|
-
this.cornerRadius = r;
|
|
369
|
-
this.svgObject.setAttribute( "rx", r.toString() );
|
|
370
|
-
this.svgObject.setAttribute( "ry", r.toString() );
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// ================ jsvgEllipse ================================= //
|
|
375
|
-
|
|
376
|
-
export class jsvgEllipse extends jsvgObject
|
|
377
|
-
{
|
|
378
|
-
constructor()
|
|
379
|
-
{
|
|
380
|
-
super();
|
|
381
|
-
|
|
382
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
383
|
-
this.svgObject = document.createElementNS(svgNS, "ellipse");
|
|
384
|
-
|
|
385
|
-
this.setPosition( 0,0 );
|
|
386
|
-
this.setWidthAndHeight( 100,100 );
|
|
387
|
-
this.setFillColor( "white" );
|
|
388
|
-
this.setStrokeColor( "black" );
|
|
389
|
-
this.setStrokeWidth( 0 );
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
setWidth( w )
|
|
393
|
-
{
|
|
394
|
-
this.width = w;
|
|
395
|
-
this.svgObject.setAttribute("rx", (this.width/2).toString() );
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
setHeight( h )
|
|
399
|
-
{
|
|
400
|
-
this.height = h;
|
|
401
|
-
this.svgObject.setAttribute("ry", (this.height/2).toString() );
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
// ================ jsvgArc ================================= //
|
|
407
|
-
|
|
408
|
-
export class jsvgArc extends jsvgObject
|
|
409
|
-
{
|
|
410
|
-
constructor()
|
|
411
|
-
{
|
|
412
|
-
super();
|
|
413
|
-
|
|
414
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
415
|
-
this.svgObject = document.createElementNS(svgNS, "path");
|
|
416
|
-
|
|
417
|
-
this.setFillColor("white");
|
|
418
|
-
this.setStrokeColor("black");
|
|
419
|
-
this.setStrokeWidth(0);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
createPieSlice(radius, startAngle, endAngle)
|
|
423
|
-
{
|
|
424
|
-
// Convert polar coordinates to Cartesian for SVG arc
|
|
425
|
-
function polarToCartesian(radius, angleInDegrees)
|
|
426
|
-
{
|
|
427
|
-
const angleInRadians = (angleInDegrees - 90) * Math.PI / 180;
|
|
428
|
-
return {
|
|
429
|
-
x: (radius * Math.cos(angleInRadians)),
|
|
430
|
-
y: (radius * Math.sin(angleInRadians))
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
const start = polarToCartesian(radius, endAngle);
|
|
435
|
-
const end = polarToCartesian(radius, startAngle);
|
|
436
|
-
|
|
437
|
-
const largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
|
|
438
|
-
|
|
439
|
-
const d = [
|
|
440
|
-
`M ${0} ${0}`, // Move to center
|
|
441
|
-
`L ${start.x} ${start.y}`, // Draw line to start of arc
|
|
442
|
-
`A ${radius} ${radius} 0 ${largeArcFlag} 0 ${end.x} ${end.y}`, // Draw arc
|
|
443
|
-
`Z` // Close path to center
|
|
444
|
-
].join(" ");
|
|
445
|
-
|
|
446
|
-
this.svgObject.setAttribute("d", d);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// ================ jsvgPath ================================= //
|
|
451
|
-
|
|
452
|
-
export class jsvgPath extends jsvgObject
|
|
453
|
-
{
|
|
454
|
-
constructor()
|
|
455
|
-
{
|
|
456
|
-
super();
|
|
457
|
-
|
|
458
|
-
// Create the path element and add it to the SVG element
|
|
459
|
-
this.path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
460
|
-
this.path.setAttribute("fill", "none"); // Default fill is none
|
|
461
|
-
this.path.setAttribute("stroke", "black"); // Default stroke is black
|
|
462
|
-
this.path.setAttribute("stroke-width", "2"); // Default stroke width
|
|
463
|
-
// this.svgElement.appendChild(this.path);
|
|
464
|
-
|
|
465
|
-
this.svgObject = this.path;
|
|
466
|
-
|
|
467
|
-
// Initialize the points array
|
|
468
|
-
this.points = [];
|
|
469
|
-
|
|
470
|
-
// Update the path's 'd' attribute
|
|
471
|
-
this.updatePath();
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
addPoint(x, y)
|
|
475
|
-
{
|
|
476
|
-
if (typeof x !== "number" || typeof y !== "number")
|
|
477
|
-
{
|
|
478
|
-
throw new Error("Coordinates must be numbers.");
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
this.points.push({ x:x, y:y });
|
|
482
|
-
|
|
483
|
-
// must call updatePath to see new points
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
updatePath()
|
|
487
|
-
{
|
|
488
|
-
if (this.points.length === 0)
|
|
489
|
-
{
|
|
490
|
-
this.path.setAttribute("d", "");
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// Create the 'd' attribute for the path
|
|
495
|
-
const d = this.points
|
|
496
|
-
.map((point, index) => (index === 0 ? `M ${point.x},${point.y}` : `L ${point.x},${point.y}`))
|
|
497
|
-
.join(" ");
|
|
498
|
-
|
|
499
|
-
// Close the polygon if it has at least three points
|
|
500
|
-
const pathData = d;
|
|
501
|
-
|
|
502
|
-
this.path.setAttribute("d", pathData);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
clearPoints()
|
|
506
|
-
{
|
|
507
|
-
this.points = [];
|
|
508
|
-
this.updatePath();
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
// ================ jsvgClipMask ================================= //
|
|
514
|
-
|
|
515
|
-
export class jsvgClipMask extends jsvgObject
|
|
516
|
-
{
|
|
517
|
-
constructor( width=300, height=300, cornerRadius=10 )
|
|
518
|
-
{
|
|
519
|
-
super();
|
|
520
|
-
|
|
521
|
-
// make a new svg group
|
|
522
|
-
const svgNamespace = "http://www.w3.org/2000/svg";
|
|
523
|
-
const svg = document.createElementNS(svgNamespace, "g");
|
|
524
|
-
this.svgObject = svg;
|
|
525
|
-
|
|
526
|
-
this.width = width;
|
|
527
|
-
this.height = height;
|
|
528
|
-
this.cornerRadius = cornerRadius;
|
|
529
|
-
|
|
530
|
-
this.maskID = "clipMaskID" + Math.random();
|
|
531
|
-
|
|
532
|
-
svg.setAttribute("width", this.width);
|
|
533
|
-
svg.setAttribute("height", this.height);
|
|
534
|
-
svg.setAttribute("viewBox", `0 0 ${this.width} ${this.height}`);
|
|
535
|
-
|
|
536
|
-
// Create a clipPath to apply rounded corners
|
|
537
|
-
const clipPath = document.createElementNS(svgNamespace, "clipPath");
|
|
538
|
-
clipPath.setAttribute("id", this.maskID );
|
|
539
|
-
|
|
540
|
-
this.clipRect = document.createElementNS(svgNamespace, "rect");
|
|
541
|
-
this.clipRect.setAttribute("x", 0);
|
|
542
|
-
this.clipRect.setAttribute("y", 0);
|
|
543
|
-
this.clipRect.setAttribute("width", this.width);
|
|
544
|
-
this.clipRect.setAttribute("height", this.height);
|
|
545
|
-
this.clipRect.setAttribute("rx", this.cornerRadius); // Rounded corner radius
|
|
546
|
-
this.clipRect.setAttribute("ry", this.cornerRadius);
|
|
547
|
-
|
|
548
|
-
clipPath.appendChild(this.clipRect);
|
|
549
|
-
svg.appendChild(clipPath);
|
|
550
|
-
|
|
551
|
-
// we create an inner group that gets masked
|
|
552
|
-
// all children get added this group
|
|
553
|
-
this.clipGroup = new jsvgGroup();
|
|
554
|
-
this.clipGroup.svgObject.setAttribute("clip-path", `url(#${this.maskID})`);
|
|
555
|
-
super.addChild( this.clipGroup ); // use super to avoid recursion
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
setWidth( width )
|
|
559
|
-
{
|
|
560
|
-
this.width = width;
|
|
561
|
-
|
|
562
|
-
this.svgObject.setAttribute("width", this.width);
|
|
563
|
-
this.svgObject.setAttribute("viewBox", `0 0 ${this.width} ${this.height}`);
|
|
564
|
-
this.clipRect.setAttribute("width", this.width);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
setHeight( height )
|
|
568
|
-
{
|
|
569
|
-
this.height = height;
|
|
570
|
-
|
|
571
|
-
this.svgObject.setAttribute("height", this.height);
|
|
572
|
-
this.svgObject.setAttribute("viewBox", `0 0 ${this.width} ${this.height}`);
|
|
573
|
-
this.clipRect.setAttribute("height", this.height);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// setWidthAndHeight( width, height )
|
|
577
|
-
// {
|
|
578
|
-
// this.width = width;
|
|
579
|
-
// this.height = height;
|
|
580
|
-
|
|
581
|
-
// this.svgObject.setAttribute("width", this.width);
|
|
582
|
-
// this.svgObject.setAttribute("height", this.height);
|
|
583
|
-
// this.svgObject.setAttribute("viewBox", `0 0 ${this.width} ${this.height}`);
|
|
584
|
-
|
|
585
|
-
// this.clipRect.setAttribute("width", this.width);
|
|
586
|
-
// this.clipRect.setAttribute("height", this.height);
|
|
587
|
-
// }
|
|
588
|
-
|
|
589
|
-
setCornerRadius( cornerRadius )
|
|
590
|
-
{
|
|
591
|
-
this.cornerRadius = cornerRadius;
|
|
592
|
-
this.clipRect.setAttribute("rx", this.cornerRadius); // Rounded corner radius
|
|
593
|
-
this.clipRect.setAttribute("ry", this.cornerRadius);
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
addChild( obj )
|
|
597
|
-
{
|
|
598
|
-
// add to masked clip group
|
|
599
|
-
this.clipGroup.addChild( obj );
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
// ================ jsvgImage ================================= //
|
|
607
|
-
|
|
608
|
-
export class jsvgImage extends jsvgObject
|
|
609
|
-
{
|
|
610
|
-
constructor()
|
|
611
|
-
{
|
|
612
|
-
super();
|
|
613
|
-
|
|
614
|
-
this.preserveAspectRatio = true;
|
|
615
|
-
|
|
616
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
617
|
-
this.svgObject = document.createElementNS(svgNS, "image");
|
|
618
|
-
this.setWidthAndHeight( 100,100 );
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
setImageURL( newURL )
|
|
622
|
-
{
|
|
623
|
-
this.svgObject.setAttribute("href", newURL );
|
|
624
|
-
this.imageURL = newURL;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
setAspectRatio( svgAspectRatio )
|
|
628
|
-
{
|
|
629
|
-
// to fill the whole space use "xMidYMid slice"
|
|
630
|
-
this.svgObject.setAttribute("preserveAspectRatio", svgAspectRatio );
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
applyRoundedCorners( cornerRadius, svgAspectRatio = 0 )
|
|
634
|
-
{
|
|
635
|
-
// remove the original image
|
|
636
|
-
if ( this.svgObject )
|
|
637
|
-
this.svgObject.remove();
|
|
638
|
-
|
|
639
|
-
// make a new svg image
|
|
640
|
-
const svgNamespace = "http://www.w3.org/2000/svg";
|
|
641
|
-
const svg = document.createElementNS(svgNamespace, "g");
|
|
642
|
-
this.svgObject = svg;
|
|
643
|
-
|
|
644
|
-
svg.setAttribute("width", this.width);
|
|
645
|
-
svg.setAttribute("height", this.height);
|
|
646
|
-
svg.setAttribute("viewBox", `0 0 ${this.width} ${this.height}`);
|
|
647
|
-
|
|
648
|
-
// Create a clipPath to apply rounded corners
|
|
649
|
-
const clipPath = document.createElementNS(svgNamespace, "clipPath");
|
|
650
|
-
clipPath.setAttribute("id", "rounded-corners");
|
|
651
|
-
|
|
652
|
-
const rect = document.createElementNS(svgNamespace, "rect");
|
|
653
|
-
rect.setAttribute("x", 0);
|
|
654
|
-
rect.setAttribute("y", 0);
|
|
655
|
-
rect.setAttribute("width", this.width);
|
|
656
|
-
rect.setAttribute("height", this.height);
|
|
657
|
-
rect.setAttribute("rx", cornerRadius); // Rounded corner radius
|
|
658
|
-
rect.setAttribute("ry", cornerRadius);
|
|
659
|
-
|
|
660
|
-
clipPath.appendChild(rect);
|
|
661
|
-
svg.appendChild(clipPath);
|
|
662
|
-
|
|
663
|
-
// Create the image element
|
|
664
|
-
const image = document.createElementNS(svgNamespace, "image");
|
|
665
|
-
image.setAttribute("href", this.imageURL );
|
|
666
|
-
image.setAttribute("width", this.width);
|
|
667
|
-
image.setAttribute("height", this.height);
|
|
668
|
-
image.setAttribute("clip-path", "url(#rounded-corners)");
|
|
669
|
-
if ( svgAspectRatio )
|
|
670
|
-
image.setAttribute("preserveAspectRatio", svgAspectRatio );
|
|
671
|
-
|
|
672
|
-
svg.appendChild(image);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
// ================ jsvgTextLine ================================= //
|
|
678
|
-
|
|
679
|
-
export class jsvgTextLine extends jsvgObject
|
|
680
|
-
{
|
|
681
|
-
constructor()
|
|
682
|
-
{
|
|
683
|
-
super();
|
|
684
|
-
|
|
685
|
-
this.text = "";
|
|
686
|
-
|
|
687
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
688
|
-
this.svgObject = document.createElementNS(svgNS, "text");
|
|
689
|
-
this.svgObject.textContent = "hello world";
|
|
690
|
-
this.svgObject.setAttribute("x", "0"); // x-coordinate of the rectangle
|
|
691
|
-
this.svgObject.setAttribute("y", "0"); // y-coordinate of the rectangle
|
|
692
|
-
this.svgObject.setAttribute("fill", "black"); // fill color of the rectangle
|
|
693
|
-
this.svgObject.style.fontFamily = "Arial, Helvetica, sans-serif;";
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
setText( text ) { this.text = text; this.svgObject.textContent = text; }
|
|
697
|
-
getText() { return this.text; }
|
|
698
|
-
|
|
699
|
-
setFontSize( S ) { this.svgObject.style.fontSize = S.toString() + 'px'; }
|
|
700
|
-
|
|
701
|
-
setFontFamily( F ) { this.svgObject.style.fontFamily = F; }
|
|
702
|
-
|
|
703
|
-
setFontColor( C ) { this.svgObject.style.fill = C; }
|
|
704
|
-
|
|
705
|
-
setTextAnchor( A )
|
|
706
|
-
{
|
|
707
|
-
// left, middle or right
|
|
708
|
-
this.svgObject.setAttribute("text-anchor", A ); // fill color of the rectangle
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
setAlignment( A )
|
|
712
|
-
{
|
|
713
|
-
this.alignment = A;
|
|
714
|
-
if ( A == 'left' )
|
|
715
|
-
this.setTextAnchor( 'start' );
|
|
716
|
-
if ( A == 'center' )
|
|
717
|
-
this.setTextAnchor( 'middle' );
|
|
718
|
-
if ( A == 'right' )
|
|
719
|
-
this.setTextAnchor( 'end' );
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
setFontWeight( W ) {
|
|
723
|
-
this.svgObject.style.fontWeight = W.toString();
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
// ================ jsvgTextBox (Div) ================================= //
|
|
729
|
-
|
|
730
|
-
export class jsvgTextBox extends jsvgGroup
|
|
731
|
-
{
|
|
732
|
-
constructor()
|
|
733
|
-
{
|
|
734
|
-
super();
|
|
735
|
-
|
|
736
|
-
this.text = "";
|
|
737
|
-
|
|
738
|
-
var ns = 'http://www.w3.org/2000/svg';
|
|
739
|
-
this.foreignObject = document.createElementNS( ns, 'foreignObject');
|
|
740
|
-
|
|
741
|
-
this.foreignObject.style.backgroundColor = 'none';
|
|
742
|
-
this.svgObject.appendChild( this.foreignObject );
|
|
743
|
-
|
|
744
|
-
this.div = document.createElement('div');
|
|
745
|
-
this.foreignObject.appendChild( this.div );
|
|
746
|
-
|
|
747
|
-
this.setWidthAndHeight( 200,100 );
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
setText( T ) { this.text = T; this.div.innerHTML = T; }
|
|
751
|
-
|
|
752
|
-
getText() { return this.text; }
|
|
753
|
-
|
|
754
|
-
setStyle( S ) // for style setting with CSS
|
|
755
|
-
{
|
|
756
|
-
this.div.className = S;
|
|
757
|
-
this.div.style.position = 'fixed'; // for safari
|
|
758
|
-
};
|
|
759
|
-
|
|
760
|
-
setFontFamily( F ) { this.div.style.fontFamily = F; }
|
|
761
|
-
|
|
762
|
-
setFontSize( S ) { this.div.style.fontSize = S.toString() + "px"; }
|
|
763
|
-
|
|
764
|
-
setLineHeight( H ) { this.div.style.lineHeight = H + 'px'; }
|
|
765
|
-
|
|
766
|
-
setFontWeight( W ) { this.div.style.fontWeight = W; }
|
|
767
|
-
|
|
768
|
-
setFontColor( C ) { this.div.style.color = C; }
|
|
769
|
-
|
|
770
|
-
setAlignment( A ) { this.div.style.textAlign = A; }
|
|
771
|
-
|
|
772
|
-
setVerticalCentering()
|
|
773
|
-
{
|
|
774
|
-
this.div.style.display = "flex";
|
|
775
|
-
this.div.style.flexFlow = "column"
|
|
776
|
-
this.div.style.justifyContent = "center";
|
|
777
|
-
this.div.style.alignItems = "center";
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
makeEditable()
|
|
781
|
-
{
|
|
782
|
-
this.div.style.contentEditable = 'true';
|
|
783
|
-
this.div.onclick = function() { console.log("here"); this.focus(); };
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
setBorderWidthAndColor( width, color ) { this.div.style.border = width + "px solid " + color; }
|
|
787
|
-
|
|
788
|
-
setWidth( W )
|
|
789
|
-
{
|
|
790
|
-
this.width = W;
|
|
791
|
-
if ( this.div )
|
|
792
|
-
this.div.style.width = W + 'px'
|
|
793
|
-
|
|
794
|
-
if ( this.foreignObject )
|
|
795
|
-
this.foreignObject.setAttribute('width', W );
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
setHeight( H )
|
|
799
|
-
{
|
|
800
|
-
this.height = H;
|
|
801
|
-
if ( this.div )
|
|
802
|
-
this.div.style.height = H + 'px'
|
|
803
|
-
|
|
804
|
-
if ( this.foreignObject )
|
|
805
|
-
this.foreignObject.setAttribute('height', H );
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
// ================ jsvgTextInput ================================= //
|
|
812
|
-
|
|
813
|
-
export class jsvgTextInput extends jsvgTextBox
|
|
814
|
-
{
|
|
815
|
-
constructor()
|
|
816
|
-
{
|
|
817
|
-
super();
|
|
818
|
-
|
|
819
|
-
this.callback = null;
|
|
820
|
-
|
|
821
|
-
// remove the generic div before replacing it
|
|
822
|
-
this.foreignObject.removeChild( this.div );
|
|
823
|
-
|
|
824
|
-
this.div = document.createElement('input');
|
|
825
|
-
this.div.contentEditable = true;
|
|
826
|
-
|
|
827
|
-
this.div.onkeyup = this.handleInput.bind(this);
|
|
828
|
-
this.foreignObject.appendChild( this.div );
|
|
829
|
-
|
|
830
|
-
this.setWidthAndHeight( 200,30 );
|
|
831
|
-
this.setPlaceholderText("placeholder");
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
setStyle( S ) // for style setting with CSS
|
|
835
|
-
{
|
|
836
|
-
this.div.className = S;
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
setPlaceholderText( T ) { this.div.placeholder = T }
|
|
840
|
-
|
|
841
|
-
setText( T ) { this.div.value = T; }
|
|
842
|
-
|
|
843
|
-
getText() { return this.div.value; }
|
|
844
|
-
|
|
845
|
-
setInputCallback( callback ) { this.callback = callback; } // the callback is a function which receives text
|
|
846
|
-
|
|
847
|
-
handleInput( event )
|
|
848
|
-
{
|
|
849
|
-
if ( event.key == 'Enter' || event.keyCode==13 )
|
|
850
|
-
{
|
|
851
|
-
if ( this.callback )
|
|
852
|
-
this.callback( this.div.value )
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
// ================ jsvgTextArea ================================= //
|
|
859
|
-
|
|
860
|
-
export class jsvgTextArea extends jsvgTextBox
|
|
861
|
-
{
|
|
862
|
-
constructor()
|
|
863
|
-
{
|
|
864
|
-
super();
|
|
865
|
-
|
|
866
|
-
this.callback = null;
|
|
867
|
-
|
|
868
|
-
// remove the generic div before replacing it
|
|
869
|
-
this.foreignObject.removeChild( this.div );
|
|
870
|
-
|
|
871
|
-
this.div = document.createElement('textarea');
|
|
872
|
-
|
|
873
|
-
this.div.onkeyup = this.handleInput.bind(this);
|
|
874
|
-
this.foreignObject.appendChild( this.div );
|
|
875
|
-
|
|
876
|
-
this.setWidthAndHeight( 200,30 );
|
|
877
|
-
this.setPlaceholderText("placeholder");
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
setText( T ) { this.div.value = T; }
|
|
881
|
-
getText() { return this.div.value; }
|
|
882
|
-
|
|
883
|
-
setStyle( S ) // for style setting with CSS
|
|
884
|
-
{
|
|
885
|
-
this.div.className = S;
|
|
886
|
-
};
|
|
887
|
-
|
|
888
|
-
handleInput( event )
|
|
889
|
-
{
|
|
890
|
-
if ( this.callback )
|
|
891
|
-
this.callback( this );
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
setPlaceholderText( T ) { this.div.placeholder = T }
|
|
895
|
-
|
|
896
|
-
setInputCallback( callback ) { this.callback = callback; } // the callback is a function which receives text
|
|
897
|
-
|
|
898
|
-
}
|
package/jsvg/jsvgComponents.js
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// ================ jsvgButton ================================= //
|
|
5
|
-
|
|
6
|
-
export class jsvgButton extends jsvgGroup
|
|
7
|
-
{
|
|
8
|
-
constructor()
|
|
9
|
-
{
|
|
10
|
-
super();
|
|
11
|
-
|
|
12
|
-
this.callback = null;
|
|
13
|
-
this.fontSize = 12;
|
|
14
|
-
this.text = 'button';
|
|
15
|
-
|
|
16
|
-
// add rect
|
|
17
|
-
this.backRect = new jsvgRect();
|
|
18
|
-
this.backRect.setWidthAndHeight( 100,30 );
|
|
19
|
-
this.backRect.setFillColor( "white" );
|
|
20
|
-
this.backRect.setStrokeWidth(0);
|
|
21
|
-
this.backRect.setCornerRadius( 15 );
|
|
22
|
-
this.backRect.svgObject.style.cursor = "pointer";
|
|
23
|
-
this.addChild( this.backRect );
|
|
24
|
-
|
|
25
|
-
// add text
|
|
26
|
-
this.buttonText = new jsvgTextLine();
|
|
27
|
-
this.buttonText.setPosition(50,20);
|
|
28
|
-
this.buttonText.setFontFamily( "Arial" );
|
|
29
|
-
this.buttonText.setFontSize( 12 );
|
|
30
|
-
this.buttonText.setText("button");
|
|
31
|
-
this.buttonText.setTextAnchor("middle");
|
|
32
|
-
this.buttonText.svgObject.style.cursor = "pointer";
|
|
33
|
-
|
|
34
|
-
this.addChild( this.buttonText );
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
setText( T ) { this.text = T; this.buttonText.setText(T) }
|
|
38
|
-
setFontFamily( F ) { this.buttonText.setFontFamily(F) }
|
|
39
|
-
setFontSize( S ) { this.fontSize=S; this.buttonText.setFontSize(S) }
|
|
40
|
-
setFontColor( C ) { this.buttonText.setFontColor(C) }
|
|
41
|
-
setFillColor( C ) { this.backRect.setFillColor( C ) };
|
|
42
|
-
setStrokeColor( C ) { this.backRect.setStrokeColor( C ) };
|
|
43
|
-
setStrokeWidth( C ) { this.backRect.setStrokeWidth( C ) };
|
|
44
|
-
setCornerRadius( R ) { this.backRect.setCornerRadius( R ) };
|
|
45
|
-
|
|
46
|
-
addImage( imageURL, imageWidth=30, imageHeight=30 )
|
|
47
|
-
{
|
|
48
|
-
this.image = new jsvgImage();
|
|
49
|
-
this.image.setImageURL( imageURL );
|
|
50
|
-
this.image.setWidthAndHeight( imageWidth, imageHeight );
|
|
51
|
-
this.image.setPosition( this.backRect.width/2-imageWidth/2, this.backRect.height/2-imageHeight/2 );
|
|
52
|
-
this.image.svgObject.style.cursor = "pointer";
|
|
53
|
-
this.addChild( this.image );
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
setWidthAndHeight( W, H )
|
|
57
|
-
{
|
|
58
|
-
this.width = W;
|
|
59
|
-
this.height = H;
|
|
60
|
-
this.backRect.setWidthAndHeight( W, H );
|
|
61
|
-
this.buttonText.setPosition( W/2, H*0.50+2 + this.fontSize*0.25 );
|
|
62
|
-
if ( this.image )
|
|
63
|
-
{
|
|
64
|
-
this.image.setPosition( this.backRect.width/2-this.image.width/2,
|
|
65
|
-
this.backRect.height/2-this.image.height/2 );
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// ================ jsvgLayoutGroup ================================= //
|
|
72
|
-
|
|
73
|
-
export class jsvgLayoutGroup extends jsvgGroup
|
|
74
|
-
{
|
|
75
|
-
constructor()
|
|
76
|
-
{
|
|
77
|
-
super();
|
|
78
|
-
|
|
79
|
-
this.spacer = 10;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
setSpacer( S )
|
|
83
|
-
{
|
|
84
|
-
this.spacer = S;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
updateLayout()
|
|
88
|
-
{
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
showAll()
|
|
92
|
-
{
|
|
93
|
-
var N = this.getNumberOfChildren();
|
|
94
|
-
for ( var i=0; i<N; i++)
|
|
95
|
-
{
|
|
96
|
-
var C = this.getChild(i);
|
|
97
|
-
C.show();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
showOnly( indexToShow )
|
|
102
|
-
{
|
|
103
|
-
var N = this.getNumberOfChildren();
|
|
104
|
-
for ( var i=0; i<N; i++)
|
|
105
|
-
{
|
|
106
|
-
var C = this.getChild(i);
|
|
107
|
-
if ( i == indexToShow )
|
|
108
|
-
C.show();
|
|
109
|
-
else
|
|
110
|
-
C.hide();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
doVerticalLayout()
|
|
115
|
-
{
|
|
116
|
-
var N = this.getNumberOfChildren();
|
|
117
|
-
|
|
118
|
-
// layout children from top to bottom
|
|
119
|
-
var pX = 0;
|
|
120
|
-
var pY = 0;
|
|
121
|
-
var minW = 0;
|
|
122
|
-
for ( var i=0; i<N; i++)
|
|
123
|
-
{
|
|
124
|
-
var C = this.getChild(i);
|
|
125
|
-
if ( ! C.visible )
|
|
126
|
-
continue;
|
|
127
|
-
C.setPosition( pX,pY );
|
|
128
|
-
pY += C.height;
|
|
129
|
-
pY += this.spacer;
|
|
130
|
-
|
|
131
|
-
if ( C.width > minW )
|
|
132
|
-
minW = C.width;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// set width and height
|
|
136
|
-
this.height = pY - this.spacer;
|
|
137
|
-
this.width = minW;
|
|
138
|
-
|
|
139
|
-
// horizontal center all items
|
|
140
|
-
for ( var i=0; i<N; i++)
|
|
141
|
-
{
|
|
142
|
-
var C = this.getChild(i);
|
|
143
|
-
var pX = this.width/2-C.width/2;
|
|
144
|
-
C.setPosition( pX, C.ypos );
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
doHorizontalLayout()
|
|
149
|
-
{
|
|
150
|
-
var N = this.getNumberOfChildren();
|
|
151
|
-
|
|
152
|
-
// layout children from left to right
|
|
153
|
-
var pX = 0;
|
|
154
|
-
var pY = 0;
|
|
155
|
-
var minH = 0;
|
|
156
|
-
for ( var i=0; i<N; i++)
|
|
157
|
-
{
|
|
158
|
-
var C = this.getChild(i);
|
|
159
|
-
if ( ! C.visible )
|
|
160
|
-
continue;
|
|
161
|
-
C.setPosition( pX,pY );
|
|
162
|
-
pX += C.width;
|
|
163
|
-
pX += this.spacer;
|
|
164
|
-
|
|
165
|
-
if ( C.height > minH )
|
|
166
|
-
minH = C.height;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// set width and height
|
|
170
|
-
this.width = pX - this.spacer;
|
|
171
|
-
this.height = minH;
|
|
172
|
-
|
|
173
|
-
// vertically center all items
|
|
174
|
-
for ( var i=0; i<N; i++)
|
|
175
|
-
{
|
|
176
|
-
var C = this.getChild(i);
|
|
177
|
-
var pY = this.height/2-C.height/2;
|
|
178
|
-
C.setPosition( C.xpos, pY );
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// ================ jsvgScrollbox ================================= //
|
|
185
|
-
|
|
186
|
-
export class jsvgScrollbox extends jsvgGroup
|
|
187
|
-
{
|
|
188
|
-
constructor()
|
|
189
|
-
{
|
|
190
|
-
super();
|
|
191
|
-
|
|
192
|
-
this.scrollPercent = 0;
|
|
193
|
-
this.scrollOffset = 0;
|
|
194
|
-
this.contentHeight = 0;
|
|
195
|
-
|
|
196
|
-
this.oldMouseX = 0;
|
|
197
|
-
this.oldMouseY = 0;
|
|
198
|
-
|
|
199
|
-
// make clip mask
|
|
200
|
-
this.clipMask = new jsvgClipMask( 200,400, 10 );
|
|
201
|
-
super.addChild( this.clipMask ); // use super to avoid addChild recursion
|
|
202
|
-
|
|
203
|
-
// make background rect
|
|
204
|
-
this.backRect = new jsvgRect();
|
|
205
|
-
this.backRect.setFillColor("white");
|
|
206
|
-
this.clipMask.addChild( this.backRect );
|
|
207
|
-
|
|
208
|
-
// make scroll group
|
|
209
|
-
this.scrollGroup = new jsvgGroup();
|
|
210
|
-
this.clipMask.addChild( this.scrollGroup );
|
|
211
|
-
|
|
212
|
-
// make scroll bar
|
|
213
|
-
this.scrollBar = new jsvgRect();
|
|
214
|
-
this.scrollBar.setWidthAndHeight( 10,50 );
|
|
215
|
-
this.scrollBar.setCornerRadius( 5 );
|
|
216
|
-
this.scrollBar.setFillColor( "darkgray" );
|
|
217
|
-
this.scrollBar.setPosition( 180, 10 );
|
|
218
|
-
this.scrollBar.svgObject.onmousedown = this.handleMouseDown.bind(this);
|
|
219
|
-
this.scrollBar.svgObject.style.cursor = "pointer";
|
|
220
|
-
this.clipMask.addChild( this.scrollBar );
|
|
221
|
-
|
|
222
|
-
this.setWidthAndHeight( 200,500 );
|
|
223
|
-
|
|
224
|
-
this.updateLayout();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
setWidth( W )
|
|
228
|
-
{
|
|
229
|
-
super.setWidth( W );
|
|
230
|
-
this.clipMask.setWidth( W );
|
|
231
|
-
this.backRect.setWidth( W );
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
setHeight( H )
|
|
235
|
-
{
|
|
236
|
-
super.setWidth( H );
|
|
237
|
-
this.clipMask.setHeight( H );
|
|
238
|
-
this.backRect.setHeight( H );
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
setCornerRadius( R )
|
|
242
|
-
{
|
|
243
|
-
this.clipMask.setCornerRadius( R );
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
addChild( C )
|
|
247
|
-
{
|
|
248
|
-
this.scrollGroup.addChild( C );
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
handleMouseDown( event )
|
|
252
|
-
{
|
|
253
|
-
if ( ! this.visible )
|
|
254
|
-
return;
|
|
255
|
-
|
|
256
|
-
// handle dragging
|
|
257
|
-
function handleMouseMove(event)
|
|
258
|
-
{
|
|
259
|
-
event.preventDefault();
|
|
260
|
-
// console.log("handleMouseMove");
|
|
261
|
-
|
|
262
|
-
// get mouseX and mouseY
|
|
263
|
-
var mouseX, mouseY;
|
|
264
|
-
if ( event.touches && event.touches.length >= 1 )
|
|
265
|
-
{
|
|
266
|
-
mouseX = event.touches[0].clientX;
|
|
267
|
-
mouseY = event.touches[0].clientY;
|
|
268
|
-
}
|
|
269
|
-
else
|
|
270
|
-
{
|
|
271
|
-
mouseX = event.clientX;
|
|
272
|
-
mouseY = event.clientY;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// calculate dX and dY
|
|
276
|
-
if ( this.oldMouseX && this.oldMouseY )
|
|
277
|
-
{
|
|
278
|
-
var dX = mouseX - this.oldMouseX;
|
|
279
|
-
var dY = mouseY - this.oldMouseY;
|
|
280
|
-
|
|
281
|
-
var pY = this.scrollBar.ypos + dY;
|
|
282
|
-
|
|
283
|
-
// enforce slider bounds
|
|
284
|
-
var minY = 10;
|
|
285
|
-
var maxY = this.backRect.height - this.scrollBar.height - 10;
|
|
286
|
-
if ( pY < minY )
|
|
287
|
-
pY = minY;
|
|
288
|
-
if ( pY > maxY )
|
|
289
|
-
pY = maxY;
|
|
290
|
-
|
|
291
|
-
// move the circle
|
|
292
|
-
this.scrollBar.setPosition( this.scrollBar.xpos, pY );
|
|
293
|
-
|
|
294
|
-
this.scrollPercent = (pY-minY) / (maxY-minY);
|
|
295
|
-
// console.log( this.scrollPercent.toFixed(2) );
|
|
296
|
-
|
|
297
|
-
// update layout
|
|
298
|
-
this.updateLayout();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// set oldMouseX and oldMouseY
|
|
302
|
-
this.oldMouseX = mouseX;
|
|
303
|
-
this.oldMouseY = mouseY;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// on mouse up
|
|
307
|
-
function handleMouseUp(event)
|
|
308
|
-
{
|
|
309
|
-
// console.log("handleMouseUp");
|
|
310
|
-
this.activeBubble = null;
|
|
311
|
-
window.onmousemove = null;
|
|
312
|
-
window.ontouchmove = null;
|
|
313
|
-
window.onmouseup = null;
|
|
314
|
-
window.ontouchend = null;
|
|
315
|
-
this.oldMouseX = 0;
|
|
316
|
-
this.oldMouseY = 0;
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// set up events
|
|
321
|
-
window.onmousemove = handleMouseMove.bind(this);
|
|
322
|
-
window.ontouchmove = handleMouseMove.bind(this);;
|
|
323
|
-
window.onmouseup = handleMouseUp.bind(this);
|
|
324
|
-
window.ontouchend = handleMouseUp.bind(this);;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
computeContentBounds()
|
|
328
|
-
{
|
|
329
|
-
var maxY = 0;
|
|
330
|
-
var N = this.scrollGroup.getNumberOfChildren();
|
|
331
|
-
|
|
332
|
-
// find bottom most point of all child objects
|
|
333
|
-
for ( var i=0; i<N; i++ )
|
|
334
|
-
{
|
|
335
|
-
var C = this.scrollGroup.getChild(i);
|
|
336
|
-
var bottomY = C.ypos + C.height;
|
|
337
|
-
if ( bottomY > maxY )
|
|
338
|
-
maxY = bottomY;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
this.contentHeight = maxY;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
updateLayout()
|
|
345
|
-
{
|
|
346
|
-
var W = this.backRect.width;
|
|
347
|
-
var H = this.backRect.height;
|
|
348
|
-
|
|
349
|
-
this.computeContentBounds();
|
|
350
|
-
|
|
351
|
-
if ( this.contentHeight > this.backRect.height )
|
|
352
|
-
{
|
|
353
|
-
var maxShift = this.contentHeight - this.backRect.height;
|
|
354
|
-
var scrollOffset = -1.0 * this.scrollPercent * maxShift;
|
|
355
|
-
this.scrollGroup.setPosition( 0, scrollOffset );
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
}
|