svelte-plots-basic 1.1.3 → 2.0.1
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/README.md +54 -69
- package/package.json +28 -33
- package/src/2d/Area.svelte +61 -0
- package/src/2d/Axes.svelte +500 -0
- package/src/2d/Axis.svelte +50 -0
- package/src/2d/AxisLines.svelte +54 -0
- package/src/2d/AxisTickLabels.svelte +82 -0
- package/src/2d/Bars.svelte +65 -0
- package/src/2d/Box.svelte +50 -0
- package/src/2d/ColorLegend.svelte +36 -0
- package/src/2d/Legend.svelte +148 -0
- package/src/2d/Lines.svelte +49 -0
- package/src/2d/Multilines.svelte +67 -0
- package/src/2d/Points.svelte +79 -0
- package/src/2d/Rectangles.svelte +74 -0
- package/src/2d/Segments.svelte +65 -0
- package/src/2d/TextLabels.svelte +107 -0
- package/src/2d/TextLegend.svelte +53 -0
- package/src/2d/XAxis.svelte +99 -0
- package/src/2d/YAxis.svelte +99 -0
- package/src/{index.js → 2d/index.js} +10 -6
- package/src/3d/Axes.svelte +445 -0
- package/src/3d/Axis.svelte +64 -0
- package/src/3d/AxisLines.svelte +50 -0
- package/src/3d/AxisTickLabels.svelte +54 -0
- package/src/3d/Lines.svelte +49 -0
- package/src/3d/Mesh.svelte +188 -0
- package/src/3d/Points.svelte +61 -0
- package/src/3d/Segments.svelte +69 -0
- package/src/3d/TextLabels.svelte +79 -0
- package/src/3d/XAxis.svelte +123 -0
- package/src/3d/YAxis.svelte +123 -0
- package/src/3d/ZAxis.svelte +123 -0
- package/src/3d/index.js +13 -0
- package/src/Colors.js +36 -1
- package/src/Utils.js +205 -0
- package/dist/index.js +0 -4209
- package/dist/index.mjs +0 -4187
- package/src/AreaSeries.svelte +0 -53
- package/src/Axes.svelte +0 -538
- package/src/BarSeries.svelte +0 -78
- package/src/Box.svelte +0 -35
- package/src/LineSeries.svelte +0 -50
- package/src/Rectangles.svelte +0 -64
- package/src/ScatterSeries.svelte +0 -85
- package/src/Segments.svelte +0 -48
- package/src/TextLabels.svelte +0 -78
- package/src/TextLegend.svelte +0 -38
- package/src/XAxis.svelte +0 -69
- package/src/YAxis.svelte +0 -72
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/****************************************************
|
|
3
|
+
* Axes for 3D plots *
|
|
4
|
+
* -------------------- *
|
|
5
|
+
* root item for any plot *
|
|
6
|
+
*****************************************************/
|
|
7
|
+
|
|
8
|
+
import { setContext, onMount, onDestroy } from 'svelte';
|
|
9
|
+
import { writable } from 'svelte/store';
|
|
10
|
+
import { cbind, matrix, Matrix, Vector } from 'mdatools/arrays';
|
|
11
|
+
import { getScale, roundCoords } from '../Utils.js';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/*****************************************/
|
|
15
|
+
/* Input parameters */
|
|
16
|
+
/*****************************************/
|
|
17
|
+
|
|
18
|
+
export let limX; // limits for x-axis (in plot units) [min, max]
|
|
19
|
+
export let limY; // limits for y-axis (in plot units) [min, max]
|
|
20
|
+
export let limZ; // limits for z-axis (in plot units) [min, max]
|
|
21
|
+
export let theta = -10;
|
|
22
|
+
export let phi = -10;
|
|
23
|
+
export let zoom = 0.5;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/*****************************************/
|
|
27
|
+
/* Constants */
|
|
28
|
+
/*****************************************/
|
|
29
|
+
|
|
30
|
+
// number of ticks along each axis
|
|
31
|
+
const TICK_NUM = {
|
|
32
|
+
"small": 5,
|
|
33
|
+
"medium": 8,
|
|
34
|
+
"large": 12,
|
|
35
|
+
"xlarge": 15
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// margin between plot series elements and data labels
|
|
39
|
+
const LABELS_MARGIN = {
|
|
40
|
+
"small": 5,
|
|
41
|
+
"medium": 10,
|
|
42
|
+
"large": 15,
|
|
43
|
+
"xlarge": 20
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// line styles for different scales and types
|
|
47
|
+
const LINE_STYLES = {
|
|
48
|
+
small: ["0", "3,3", "1,1", "3,1"],
|
|
49
|
+
medium: ["0", "5,5", "2,2", "5,2"],
|
|
50
|
+
large: ["0", "7,7", "3,3", "7,3"],
|
|
51
|
+
xlarge: ["0", "9,9", "5,5", "9,5"],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// translation matrix to move points to center of a unit cube
|
|
55
|
+
const T1 = matrix([
|
|
56
|
+
1, 0, 0, 0,
|
|
57
|
+
0, 1, 0, 0,
|
|
58
|
+
0, 0, 1, 0,
|
|
59
|
+
0.5, 0.5, 0.5, 1
|
|
60
|
+
], 4, 4);
|
|
61
|
+
|
|
62
|
+
// inverse translation matrix for T1
|
|
63
|
+
const T2 = matrix([
|
|
64
|
+
1, 0, 0, 0,
|
|
65
|
+
0, 1, 0, 0,
|
|
66
|
+
0, 0, 1, 0,
|
|
67
|
+
-0.5, -0.5, -0.5, 1
|
|
68
|
+
], 4, 4);
|
|
69
|
+
|
|
70
|
+
// constant to make clip path ID unique
|
|
71
|
+
const clipPathID = "plottingArea" + Math.round(Math.random() * 10000);
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
/*****************************************/
|
|
75
|
+
/* Variable parameters for internal use */
|
|
76
|
+
/*****************************************/
|
|
77
|
+
|
|
78
|
+
// bindings to plot DOM elements
|
|
79
|
+
let plotElement;
|
|
80
|
+
let axesElement;
|
|
81
|
+
let width, height = 100;
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
/*****************************************/
|
|
85
|
+
/* Helper functions */
|
|
86
|
+
/*****************************************/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Transforms world coordinates to 2D scene pixels by applying the transformation matrix 'tM'.
|
|
90
|
+
*
|
|
91
|
+
* @param {Matrix} coords - matrix with coordinates [X, Y, Z]
|
|
92
|
+
* @param {Matrix} tM - transformation matrix
|
|
93
|
+
*
|
|
94
|
+
* @returns {Array} array with transformed coordinates as two vectors [x, y].
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
97
|
+
const transform = function(coords, tM) {
|
|
98
|
+
// const coords2D = cbind(coords, Vector.ones(coords.nrows)).dot(tM);
|
|
99
|
+
// const coords2D = tcrossprod(tM, cbind(coords, Vector.ones(coords.nrows))).t();
|
|
100
|
+
const coords2D = cbind(coords, Vector.ones(coords.nrows)).dot(tM);
|
|
101
|
+
return [coords2D.getcolref(1).map(v => roundCoords(v)), coords2D.getcolref(2).map(v => roundCoords(v))];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
/*****************************************/
|
|
106
|
+
/* Storage to share with children */
|
|
107
|
+
/*****************************************/
|
|
108
|
+
|
|
109
|
+
const tM = writable(Matrix.eye(4)); // transformation matrix
|
|
110
|
+
const scale = writable('medium'); // plot scale (small/medium/large)
|
|
111
|
+
const xLim = writable(limX); // x-axis limits in 3D (before projection)
|
|
112
|
+
const yLim = writable(limY); // y-axis limits in 3D (before projection)
|
|
113
|
+
const zLim = writable(limZ); // z-axis limits in 3D (before projection)
|
|
114
|
+
const isOk = writable(false); // indicator that axes works fine
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
/*****************************************/
|
|
118
|
+
/* Axes context */
|
|
119
|
+
/*****************************************/
|
|
120
|
+
|
|
121
|
+
let context = {
|
|
122
|
+
|
|
123
|
+
// methods
|
|
124
|
+
transform: transform,
|
|
125
|
+
|
|
126
|
+
// state proporties
|
|
127
|
+
scale: scale,
|
|
128
|
+
isOk: isOk,
|
|
129
|
+
xLim: xLim,
|
|
130
|
+
yLim: yLim,
|
|
131
|
+
zLim: zLim,
|
|
132
|
+
tM: tM,
|
|
133
|
+
|
|
134
|
+
// constants
|
|
135
|
+
LINE_STYLES: LINE_STYLES,
|
|
136
|
+
LABELS_MARGIN: LABELS_MARGIN,
|
|
137
|
+
TICK_NUM: TICK_NUM
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
setContext('axes', context);
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
/*****************************************/
|
|
144
|
+
/* Reactive updates of the parameters */
|
|
145
|
+
/*****************************************/
|
|
146
|
+
|
|
147
|
+
// update limits if necessary
|
|
148
|
+
$: xLim.update(v => limX);
|
|
149
|
+
$: yLim.update(v => limY);
|
|
150
|
+
$: zLim.update(v => limZ);
|
|
151
|
+
|
|
152
|
+
// projection matrix (step 1)
|
|
153
|
+
$: P2 = matrix([
|
|
154
|
+
1, 0, 0, 0,
|
|
155
|
+
0, Math.cos(theta), Math.sin(theta), 0,
|
|
156
|
+
0, -Math.sin(theta), Math.cos(theta), 0,
|
|
157
|
+
0, 0, 0, 1,
|
|
158
|
+
], 4, 4);
|
|
159
|
+
|
|
160
|
+
// projection matrix (step 2)
|
|
161
|
+
$: P1 = matrix([
|
|
162
|
+
Math.cos(phi), 0, -Math.sin(phi), 0,
|
|
163
|
+
0, 1, 0, 0,
|
|
164
|
+
Math.sin(phi), 0, Math.cos(phi), 0,
|
|
165
|
+
0, 0, 0, 1
|
|
166
|
+
], 4, 4);
|
|
167
|
+
|
|
168
|
+
// zoom matrix
|
|
169
|
+
$: Z = matrix([
|
|
170
|
+
zoom, 0, 0, 0,
|
|
171
|
+
0, zoom, 0, 0,
|
|
172
|
+
0, 0, zoom, 0,
|
|
173
|
+
0, 0, 0, 1
|
|
174
|
+
], 4, 4);
|
|
175
|
+
|
|
176
|
+
// matrix for projection and zooming
|
|
177
|
+
// we shift [0, 1] cube to center, project, zoom, and then shift back
|
|
178
|
+
$: P = T1.dot(Z.dot(P2.dot(P1.dot(T2))))
|
|
179
|
+
|
|
180
|
+
// update transformation matrix if angles of the norm vectors are changed
|
|
181
|
+
$: {
|
|
182
|
+
if ($isOk) {
|
|
183
|
+
// translate
|
|
184
|
+
const TT1 = matrix([
|
|
185
|
+
1, 0, 0, 0,
|
|
186
|
+
0, 1, 0, 0,
|
|
187
|
+
0, 0, 1, 0,
|
|
188
|
+
-$xLim[0], -$yLim[0], -$zLim[0], 1
|
|
189
|
+
], 4, 4);
|
|
190
|
+
|
|
191
|
+
// scale the whole cube to [0, 1] limits
|
|
192
|
+
const SS1 = matrix([
|
|
193
|
+
1 / ($xLim[1] - $xLim[0]) , 0, 0, 0,
|
|
194
|
+
0, 1 / ($yLim[1] - $yLim[0]), 0, 0,
|
|
195
|
+
0, 0, 1 / ($zLim[1] - $zLim[0]), 0,
|
|
196
|
+
0, 0, 0, 1
|
|
197
|
+
], 4, 4);
|
|
198
|
+
|
|
199
|
+
// scale to screen coordinates
|
|
200
|
+
const SS2 = matrix([
|
|
201
|
+
width, 0, 0, 0,
|
|
202
|
+
0, height, 0, 0,
|
|
203
|
+
0, 0, 1, 0,
|
|
204
|
+
0, 0, 0, 1
|
|
205
|
+
], 4, 4);
|
|
206
|
+
|
|
207
|
+
tM.update(x => SS2.dot(P.dot(SS1.dot(TT1))).t());
|
|
208
|
+
} else {
|
|
209
|
+
tM.update(x => Matrix.eye(4));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
/*****************************************/
|
|
215
|
+
/* Events observers */
|
|
216
|
+
/*****************************************/
|
|
217
|
+
|
|
218
|
+
// observer for the plot area size — to update scale
|
|
219
|
+
const ro1 = new ResizeObserver(entries => {
|
|
220
|
+
for (let entry of entries) {
|
|
221
|
+
const pcr = plotElement.getBoundingClientRect();
|
|
222
|
+
scale.update(x => getScale(pcr.width, pcr.height));
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// observer for the axes area size - to update size of axes
|
|
227
|
+
const ro2 = new ResizeObserver(entries => {
|
|
228
|
+
for (let entry of entries) {
|
|
229
|
+
const acr = axesElement.getBoundingClientRect();
|
|
230
|
+
width = acr.width;
|
|
231
|
+
height = acr.height;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
onMount(() => {
|
|
236
|
+
ro1.observe(plotElement);
|
|
237
|
+
ro2.observe(plotElement);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
onDestroy(() => {
|
|
241
|
+
ro1.unobserve(plotElement);
|
|
242
|
+
ro2.unobserve(plotElement);
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
// check if everything is ok regarding the axis limits
|
|
246
|
+
$: isOk.update(v =>
|
|
247
|
+
!$yLim.some(v => v === undefined) &&
|
|
248
|
+
!$xLim.some(v => v === undefined) &&
|
|
249
|
+
!$zLim.some(v => v === undefined) &&
|
|
250
|
+
!$yLim.some(v => isNaN(v)) &&
|
|
251
|
+
!$xLim.some(v => isNaN(v)) &&
|
|
252
|
+
!$zLim.some(v => isNaN(v))
|
|
253
|
+
)
|
|
254
|
+
</script>
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
<div class="plot {'plot_' + $scale}" bind:this={plotElement} class:plot_error={!$isOk}>
|
|
258
|
+
|
|
259
|
+
<!-- axes (coordinate system) -->
|
|
260
|
+
<div class="axes-wrapper" bind:this={axesElement} >
|
|
261
|
+
<slot name="title"></slot>
|
|
262
|
+
|
|
263
|
+
<svg vector-effect="non-scaling-stroke" preserveAspectRatio="none" class="axes">
|
|
264
|
+
|
|
265
|
+
<!-- axis and box -->
|
|
266
|
+
<slot name="xaxis"></slot>
|
|
267
|
+
<slot name="yaxis"></slot>
|
|
268
|
+
<slot name="zaxis"></slot>
|
|
269
|
+
|
|
270
|
+
<!-- main plot content -->
|
|
271
|
+
<g class="axes-content" >
|
|
272
|
+
<slot></slot>
|
|
273
|
+
</g>
|
|
274
|
+
|
|
275
|
+
<!-- axis and box -->
|
|
276
|
+
<slot name="box"></slot>
|
|
277
|
+
</svg>
|
|
278
|
+
|
|
279
|
+
{#if !$isOk}
|
|
280
|
+
<p class="message_error">
|
|
281
|
+
Axes component was not properly initialized. <br />
|
|
282
|
+
Add plot series (check that coordinates are numeric) or define axes limits manually.
|
|
283
|
+
</p>
|
|
284
|
+
{/if}
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<style>
|
|
291
|
+
|
|
292
|
+
/* Plot (main container) */
|
|
293
|
+
.plot {
|
|
294
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
295
|
+
|
|
296
|
+
display: grid;
|
|
297
|
+
grid-template-columns: min-content auto;
|
|
298
|
+
grid-template-rows: min-content auto min-content;
|
|
299
|
+
grid-template-areas:
|
|
300
|
+
". title"
|
|
301
|
+
"ylab axes"
|
|
302
|
+
". xlab";
|
|
303
|
+
|
|
304
|
+
box-sizing: border-box;
|
|
305
|
+
min-width: 100px;
|
|
306
|
+
min-height: 50px;
|
|
307
|
+
width: 100%;
|
|
308
|
+
height: 100%;
|
|
309
|
+
padding: 0;
|
|
310
|
+
margin: 0;
|
|
311
|
+
background-color: white;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
:global(.plot_small) {
|
|
315
|
+
font-size: 11px;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
:global(.plot_medium) {
|
|
319
|
+
font-size: 13px;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
:global(.plot_large) {
|
|
323
|
+
font-size: 16px;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
:global(.plot_error) {
|
|
327
|
+
display: flex;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
:global(.plot_error > .axes-wrapper) {
|
|
331
|
+
display: none;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.message_error {
|
|
335
|
+
font-size: 1.2em;
|
|
336
|
+
color: crimson;
|
|
337
|
+
padding: 20px;
|
|
338
|
+
text-align: center;
|
|
339
|
+
width: 100%;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* Axes (coordinate system) */
|
|
343
|
+
.axes-wrapper {
|
|
344
|
+
grid-area: axes;
|
|
345
|
+
position:relative;
|
|
346
|
+
box-sizing: border-box;
|
|
347
|
+
display: flex;
|
|
348
|
+
width: 100%;
|
|
349
|
+
height: 100%;
|
|
350
|
+
padding: 0;
|
|
351
|
+
margin: 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.axes {
|
|
355
|
+
display: block;
|
|
356
|
+
box-sizing: border-box;
|
|
357
|
+
position:absolute;
|
|
358
|
+
user-select: none;
|
|
359
|
+
cursor: default;
|
|
360
|
+
padding: 0;
|
|
361
|
+
margin: 0;
|
|
362
|
+
height: 100%;
|
|
363
|
+
width: 100%;
|
|
364
|
+
max-height: 100%;
|
|
365
|
+
max-width: 100%;
|
|
366
|
+
min-height: 100%;
|
|
367
|
+
min-width: 100%;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.axes :global(text) {
|
|
371
|
+
-webkit-user-select: none;
|
|
372
|
+
user-select: none;
|
|
373
|
+
cursor: default;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
:global(.axes-content) {
|
|
377
|
+
padding: 0;
|
|
378
|
+
margin: 0;
|
|
379
|
+
height: 100%;
|
|
380
|
+
width: 100%;
|
|
381
|
+
max-height: 100%;
|
|
382
|
+
max-width: 100%;
|
|
383
|
+
min-height: 100%;
|
|
384
|
+
min-width: 100%;
|
|
385
|
+
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
:global(.axes__xlabel) {
|
|
389
|
+
grid-area: xlab;
|
|
390
|
+
font-size: 1.0em;
|
|
391
|
+
font-weight: 600;
|
|
392
|
+
padding: 0.25em;
|
|
393
|
+
text-align: center;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
:global(.axes__ylabel) {
|
|
398
|
+
grid-area: ylab;
|
|
399
|
+
font-size: 1.0em;
|
|
400
|
+
font-weight: 600;
|
|
401
|
+
padding: 0.25em;
|
|
402
|
+
text-align: center;
|
|
403
|
+
vertical-align: middle;
|
|
404
|
+
display: flex;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
:global(.axes__ylabel > span) {
|
|
408
|
+
width: 1.5em;
|
|
409
|
+
line-height: 1.5em;
|
|
410
|
+
display: inline-block;
|
|
411
|
+
writing-mode: vertical-rl;
|
|
412
|
+
transform: rotate(180deg);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
:global(.axes__title) {
|
|
417
|
+
background: transparent;
|
|
418
|
+
grid-area: title;
|
|
419
|
+
|
|
420
|
+
font-size: 1.3em;
|
|
421
|
+
font-weight: bold;
|
|
422
|
+
line-height: 1.2em;
|
|
423
|
+
padding: 0.5em 0;
|
|
424
|
+
text-align: center;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Axis */
|
|
428
|
+
:global(.axis-labels) {
|
|
429
|
+
fill: #303030;
|
|
430
|
+
font-size: 0.95em;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/* Data labels */
|
|
434
|
+
:global(.labels) {
|
|
435
|
+
fill: #606060;
|
|
436
|
+
font-size: 0.90em;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
:global(.labels) {
|
|
440
|
+
visibility: hidden;
|
|
441
|
+
transition:visibility 0.25s linear, opacity 0.25s linear;
|
|
442
|
+
opacity: 0;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/****************************************************
|
|
3
|
+
* Axis for 3D plots *
|
|
4
|
+
* -------------------- *
|
|
5
|
+
* shows main elements for axis (ticks, grid, etc.) *
|
|
6
|
+
*****************************************************/
|
|
7
|
+
|
|
8
|
+
import { Colors } from '../Colors';
|
|
9
|
+
import AxisLines from './AxisLines.svelte';
|
|
10
|
+
import TextLabels from './TextLabels.svelte';
|
|
11
|
+
import AxisTickLabels from './AxisTickLabels.svelte';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/*****************************************/
|
|
15
|
+
/* Input parameters */
|
|
16
|
+
/*****************************************/
|
|
17
|
+
|
|
18
|
+
export let tickLabels = []; // vector with labels for each tick
|
|
19
|
+
export let showGrid = false; // logical, show or not grid lines
|
|
20
|
+
export let title = ''; // axis title
|
|
21
|
+
|
|
22
|
+
export let className = '';
|
|
23
|
+
export let grid1 = [];
|
|
24
|
+
export let grid2 = [];
|
|
25
|
+
export let axisLine = [];
|
|
26
|
+
export let tickCoords = [];
|
|
27
|
+
export let titleCoords = [];
|
|
28
|
+
|
|
29
|
+
export let lineColor = Colors.DARKGRAY;
|
|
30
|
+
export let gridColor = Colors.MIDDLEGRAY;
|
|
31
|
+
export let textColor = Colors.DARKGRAY;
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<g class="mdaplot__axis {className}">
|
|
35
|
+
|
|
36
|
+
<!-- grid -->
|
|
37
|
+
{#if showGrid }
|
|
38
|
+
<AxisLines lineCoords={grid1} lineColor={gridColor} lineType={3} />
|
|
39
|
+
<AxisLines lineCoords={grid2} lineColor={gridColor} lineType={3} />
|
|
40
|
+
{/if}
|
|
41
|
+
|
|
42
|
+
<!-- main axis line -->
|
|
43
|
+
<AxisLines lineCoords={axisLine} lineColor={lineColor} lineType={1} />
|
|
44
|
+
|
|
45
|
+
<!-- ticks-->
|
|
46
|
+
<AxisLines lineCoords={[tickCoords[0], tickCoords[1]]} lineColor={lineColor} lineType={1} />
|
|
47
|
+
<AxisLines lineCoords={[tickCoords[0], tickCoords[2]]} lineColor={lineColor} lineType={1} />
|
|
48
|
+
<!-- <AxisLines lineCoords={[tickCoords[0], tickCoords[3]]} lineColor={lineColor} lineType={1} /> -->
|
|
49
|
+
|
|
50
|
+
<!-- labels -->
|
|
51
|
+
{#if tickCoords !== undefined }
|
|
52
|
+
<AxisTickLabels tickCoords={tickCoords[4]} {textColor} {tickLabels} />
|
|
53
|
+
{/if}
|
|
54
|
+
|
|
55
|
+
<!-- title -->
|
|
56
|
+
{#if titleCoords !== undefined && title !== ''}
|
|
57
|
+
<TextLabels
|
|
58
|
+
xValues={titleCoords[0]} yValues={titleCoords[1]} zValues={titleCoords[2]}
|
|
59
|
+
faceColor={textColor}
|
|
60
|
+
labels={title}
|
|
61
|
+
/>
|
|
62
|
+
{/if}
|
|
63
|
+
</g>
|
|
64
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/****************************************************
|
|
3
|
+
* Axis lines for 3D plot *
|
|
4
|
+
* ---------------------- *
|
|
5
|
+
* shows lines for axis (main, grid, etc) *
|
|
6
|
+
*****************************************************/
|
|
7
|
+
|
|
8
|
+
import { getContext } from 'svelte';
|
|
9
|
+
import { Colors } from '../Colors';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/*****************************************/
|
|
13
|
+
/* Input parameters */
|
|
14
|
+
/*****************************************/
|
|
15
|
+
|
|
16
|
+
export let lineCoords = [];
|
|
17
|
+
export let lineColor = Colors.DARKGRAY;
|
|
18
|
+
export let lineType = 1;
|
|
19
|
+
export let lineWidth = 1;
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
/*****************************************/
|
|
23
|
+
/* Component code */
|
|
24
|
+
/*****************************************/
|
|
25
|
+
|
|
26
|
+
// get axes context and reactive variables needed to compute coordinates
|
|
27
|
+
const axes = getContext('axes');
|
|
28
|
+
const scale = axes.scale;
|
|
29
|
+
const tM = axes.tM;
|
|
30
|
+
const isOk = axes.isOk;
|
|
31
|
+
|
|
32
|
+
// compute coordinates of start and end points for each line
|
|
33
|
+
let x1, x2, y1, y2, lineStyleStr = undefined;
|
|
34
|
+
$: if (lineCoords.length == 2) {
|
|
35
|
+
[x1, y1] = axes.transform(lineCoords[0], $tM);
|
|
36
|
+
[x2, y2] = axes.transform(lineCoords[1], $tM);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// line style
|
|
40
|
+
$: lineStyleStr = `stroke:${lineColor};stroke-width: ${lineWidth}px;stroke-dasharray:${axes.LINE_STYLES[$scale][lineType-1]}`;
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{#if $isOk && x1 !== undefined && y1 !== undefined && x2 !== undefined && y2 !== undefined}
|
|
44
|
+
<g class="axis__grid">
|
|
45
|
+
{#each x1 as v, i}
|
|
46
|
+
<line vector-effect="non-scaling-stroke" x1={x1[i]} x2={x2[i]} y1={y1[i]} y2={y2[i]} style={lineStyleStr} />
|
|
47
|
+
{/each}
|
|
48
|
+
</g>
|
|
49
|
+
{/if}
|
|
50
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/****************************************************
|
|
3
|
+
* AxisTickLabels for 3D plots *
|
|
4
|
+
* ---------------------------- *
|
|
5
|
+
* shows a series of tick labels along an axis *
|
|
6
|
+
*****************************************************/
|
|
7
|
+
|
|
8
|
+
import { getContext } from 'svelte';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/*****************************************/
|
|
12
|
+
/* Input parameters */
|
|
13
|
+
/*****************************************/
|
|
14
|
+
|
|
15
|
+
export let tickCoords;
|
|
16
|
+
export let textColor;
|
|
17
|
+
export let tickLabels;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/*****************************************/
|
|
21
|
+
/* Component code */
|
|
22
|
+
/*****************************************/
|
|
23
|
+
|
|
24
|
+
// get axes context and reactive variables needed to compute coordinates
|
|
25
|
+
const axes = getContext('axes');
|
|
26
|
+
const isOk = axes.isOk;
|
|
27
|
+
const tM = axes.tM;
|
|
28
|
+
|
|
29
|
+
let x, y = undefined;
|
|
30
|
+
|
|
31
|
+
// reactive calculations triggered by changes in coordinates and plot parameters
|
|
32
|
+
$: if ($isOk) {
|
|
33
|
+
[x, y] = axes.transform(tickCoords, $tM);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// styles for the elements
|
|
37
|
+
$: textStyleStr = `dominant-baseline:middle;fill:${textColor};font-size:0.85em; text-anchor:middle;`;
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
{#if x !== undefined && y !== undefined}
|
|
41
|
+
<g class="tick_labels" style={textStyleStr} >
|
|
42
|
+
{#each x as v, i}
|
|
43
|
+
<text data-id={i} x={x[i]} y={y[i]} dx={0} dy={0}>{@html tickLabels[i]}</text>
|
|
44
|
+
{/each}
|
|
45
|
+
</g>
|
|
46
|
+
{/if}
|
|
47
|
+
|
|
48
|
+
<style>
|
|
49
|
+
text, text > :global(tspan) {
|
|
50
|
+
cursor: default;
|
|
51
|
+
user-select: none;
|
|
52
|
+
dominant-baseline: middle;
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/****************************************************
|
|
3
|
+
* LineSeries *
|
|
4
|
+
* -------------------- *
|
|
5
|
+
* shows series of lines/curves *
|
|
6
|
+
*****************************************************/
|
|
7
|
+
|
|
8
|
+
import { getContext } from 'svelte';
|
|
9
|
+
import { Colors } from '../Colors';
|
|
10
|
+
import { val2p3d } from '../Utils';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/*****************************************/
|
|
14
|
+
/* Input parameters */
|
|
15
|
+
/*****************************************/
|
|
16
|
+
|
|
17
|
+
export let xValues;
|
|
18
|
+
export let yValues;
|
|
19
|
+
export let zValues;
|
|
20
|
+
export let title = '';
|
|
21
|
+
export let lineWidth = 1;
|
|
22
|
+
export let lineColor = Colors.PRIMARY;
|
|
23
|
+
export let lineType = 1;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/*****************************************/
|
|
27
|
+
/* Component code */
|
|
28
|
+
/*****************************************/
|
|
29
|
+
|
|
30
|
+
// get axes context
|
|
31
|
+
const axes = getContext('axes');
|
|
32
|
+
|
|
33
|
+
const scale = axes.scale;
|
|
34
|
+
const isOk = axes.isOk;
|
|
35
|
+
const tM = axes.tM;
|
|
36
|
+
|
|
37
|
+
// compute polynomial coordinates as string
|
|
38
|
+
$: p = $isOk ? val2p3d(xValues, yValues, zValues, $tM, axes) : undefined;
|
|
39
|
+
|
|
40
|
+
// reactive variables for coordinates of data points in pixels
|
|
41
|
+
$: lineStyleStr = `fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px; stroke-dasharray:${axes.LINE_STYLES[$scale][lineType-1]}`;
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#if $isOk && p !== undefined}
|
|
45
|
+
<g class="series series_line" style={lineStyleStr} title={title}>
|
|
46
|
+
<polyline class="line" points={p}/>
|
|
47
|
+
</g>
|
|
48
|
+
{/if}
|
|
49
|
+
|