svelte-plots-basic 1.1.4 → 2.1.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.
Files changed (51) hide show
  1. package/README.md +59 -67
  2. package/package.json +10 -4
  3. package/src/2d/Area.svelte +61 -0
  4. package/src/2d/Axes.svelte +500 -0
  5. package/src/2d/Axis.svelte +67 -0
  6. package/src/2d/AxisLines.svelte +54 -0
  7. package/src/2d/AxisTickLabels.svelte +82 -0
  8. package/src/2d/Bars.svelte +65 -0
  9. package/src/2d/Box.svelte +50 -0
  10. package/src/2d/ColorLegend.svelte +36 -0
  11. package/src/2d/ColormapLegend.svelte +100 -0
  12. package/src/2d/Heatmap.svelte +109 -0
  13. package/src/2d/Legend.svelte +148 -0
  14. package/src/2d/Lines.svelte +49 -0
  15. package/src/2d/Multilines.svelte +67 -0
  16. package/src/2d/Points.svelte +79 -0
  17. package/src/2d/Rectangles.svelte +74 -0
  18. package/src/2d/Segments.svelte +65 -0
  19. package/src/2d/TextLabels.svelte +107 -0
  20. package/src/2d/TextLegend.svelte +53 -0
  21. package/src/2d/XAxis.svelte +109 -0
  22. package/src/2d/YAxis.svelte +109 -0
  23. package/src/2d/index.js +21 -0
  24. package/src/3d/Axes.svelte +445 -0
  25. package/src/3d/Axis.svelte +64 -0
  26. package/src/3d/AxisLines.svelte +50 -0
  27. package/src/3d/AxisTickLabels.svelte +54 -0
  28. package/src/3d/Lines.svelte +49 -0
  29. package/src/3d/Mesh.svelte +185 -0
  30. package/src/3d/Points.svelte +61 -0
  31. package/src/3d/Segments.svelte +69 -0
  32. package/src/3d/TextLabels.svelte +79 -0
  33. package/src/3d/XAxis.svelte +123 -0
  34. package/src/3d/YAxis.svelte +123 -0
  35. package/src/3d/ZAxis.svelte +123 -0
  36. package/src/3d/index.js +13 -0
  37. package/src/Colors.js +36 -1
  38. package/src/Utils.js +243 -0
  39. package/src/AreaSeries.svelte +0 -53
  40. package/src/Axes.svelte +0 -550
  41. package/src/BarSeries.svelte +0 -68
  42. package/src/Box.svelte +0 -35
  43. package/src/LineSeries.svelte +0 -50
  44. package/src/Rectangles.svelte +0 -64
  45. package/src/ScatterSeries.svelte +0 -69
  46. package/src/Segments.svelte +0 -52
  47. package/src/TextLabels.svelte +0 -88
  48. package/src/TextLegend.svelte +0 -38
  49. package/src/XAxis.svelte +0 -69
  50. package/src/YAxis.svelte +0 -72
  51. package/src/index.js +0 -16
package/src/Axes.svelte DELETED
@@ -1,550 +0,0 @@
1
- <script>
2
- import { setContext, createEventDispatcher, onMount, onDestroy } from 'svelte';
3
- import { writable } from 'svelte/store';
4
-
5
- /* input parameters */
6
- export let limX = [undefined, undefined]; // limits for x-axis (in plot units) [min, max]
7
- export let limY = [undefined, undefined]; // limits for y-axis (in plot units) [min, max]
8
- export let title = ""; // title of the plot
9
- export let xLabel = ""; // label for x-axis
10
- export let yLabel = ""; // label for y-axis
11
- export let multiSeries = true; // is the plot for one series or for many
12
-
13
- // event dispatcher
14
- const dispatch = createEventDispatcher();
15
-
16
- // how big are margins (number of pixels in unit margin value) between axis and plot area if axis are shown
17
- const AXES_MARGIN_FACTORS = {
18
- "small": 30,
19
- "medium": 40,
20
- "large": 50
21
- }
22
-
23
- // number of ticks along each axis
24
- const TICK_NUM = {
25
- "small": 5,
26
- "medium": 8,
27
- "large": 12
28
- };
29
-
30
- // margin between plot series elements and data labels
31
- const LABELS_MARGIN = {
32
- "small": 10,
33
- "medium": 15,
34
- "large": 20
35
- };
36
-
37
-
38
- // line styles for different scales and types
39
- const LINE_STYLES = {
40
- small: ["0", "3,3", "1,1", "3,1"],
41
- medium: ["0", "5,5", "2,2", "5,2"],
42
- large: ["0", "7,7", "3,3", "7,3"],
43
- }
44
-
45
- // constant to make clip path ID unique
46
- const clipPathID = "plottingArea" + Math.round(Math.random() * 10000);
47
-
48
- /* parameters for internal use inside the component */
49
- let plotElement;
50
- let axesElement;
51
- let axesMargins = [0.034, 0.034, 0.034, 0.034]; // initial margins (will be multiplied to FACTORS)
52
-
53
- /* reactive parameters to be shared with children via context */
54
- const width = writable(100); // actual width of plotting area in pixels
55
- const height = writable(100); // actual height of plotting area in pixels
56
- const xLim = writable([undefined, undefined]); // actual limits for x-axis in plot units
57
- const yLim = writable([undefined, undefined]); // actual limits for y-axis in plot units
58
- const scale = writable("medium"); // scale factor (how big the shown plot is)
59
- const isOk = writable(false); // are axes ready for drawing
60
-
61
- /** Adds margins for x-axis (e.g. when x-axis must be shown) */
62
- const addXAxisMargins = function() {
63
- axesMargins[0] = 1;
64
- axesMargins[2] = 0.5;
65
- axesMargins[1] = axesMargins[1] > 0.5 ? axesMargins[1] : 0.5;
66
- axesMargins[3] = axesMargins[3] > 0.5 ? axesMargins[3] : 0.5;
67
- }
68
-
69
- /** Adds margins for y-axis (e.g. when y-axis must be shown) */
70
- const addYAxisMargins = function() {
71
- axesMargins[1] = 1;
72
- axesMargins[3] = 0.5;
73
- axesMargins[0] = axesMargins[0] > 0.5 ? axesMargins[0] : 0.5;
74
- axesMargins[2] = axesMargins[2] > 0.5 ? axesMargins[2] : 0.5;
75
- }
76
-
77
- /** Adjusts limits for x-axis (e.g. when new series is added)
78
- * @param {Array} newLim - vector with new limits (two values)
79
- */
80
- const adjustXAxisLimits = function(newLim) {
81
- if (!limX.some(v => v === undefined)) return;
82
- xLim.update(lim => adjustAxisLimits(lim, newLim));
83
- }
84
-
85
- /** Adjusts limits for y-axis (e.g. when new series is added)
86
- * @param {Array} newLim - vector with new limits (two values)
87
- */
88
- const adjustYAxisLimits = function(newLim) {
89
- if (!limY.some(v => v === undefined)) return;
90
- yLim.update(lim => adjustAxisLimits(lim, newLim));
91
- }
92
-
93
- /** Adjusts x- or y- axis limits (e.g. when new elements are added)
94
- * @param {Array} lim - vector with limits for current axis (two values)
95
- * @param {Array} newLim - vector with new limits (two values)
96
- * @returns {Array} vector with rescaled values
97
- *
98
- * The new limits are set separately for min and max. Either if current value is undefined or
99
- * if new value is outside the current limits (smaller than min or larger than max).
100
- */
101
- const adjustAxisLimits = function(lim, newLim) {
102
-
103
- let adjustedLim = [
104
- (lim[0] !== undefined && multiSeries === true && lim[0] < newLim[0]) ? lim[0] : newLim[0],
105
- (lim[1] !== undefined && multiSeries === true && lim[1] > newLim[1]) ? lim[1] : newLim[1]
106
- ];
107
-
108
- // special case when both limits are zero
109
- if (adjustedLim[0] === 0 && adjustedLim[1] === 0) {
110
- adjustedLim = [-0.1, 0.1];
111
- }
112
-
113
- // special case when limits are equal (add ±5%)
114
- if (adjustedLim[0] === adjustedLim[1]) {
115
- adjustedLim = [adjustedLim[0] * 0.95, adjustedLim[0] * 1.05];
116
- }
117
-
118
- return adjustedLim;
119
- }
120
-
121
- /**
122
- * Rounds coordinate values to single decimal
123
- */
124
- const roundCoords = function(x) {
125
- return Math.round(x * 10) / 10
126
- }
127
-
128
- /** Rescales x-values from plot coordinates to screen (SVG) coordinates
129
- * @param {Array} x - vector with coordinates (or objects size) in original plot coordinates
130
- * @param {Array} xLim - vector with current limits for x-axis in original plot coordinates
131
- * @param {number} width - width of coordinate system in pixels
132
- * @param {boolean} doSizeScreen - scale size of objects (true) or coordinates
133
- * @returns {Array} vector with rescaled values
134
- */
135
- const scaleX = function(x, xLim, width, doSizeScale = false) {
136
- if (!$isOk || x === undefined || !Array.isArray(x)) return undefined;
137
-
138
- if (doSizeScale) {
139
- // scale size of objects instead of coordinates
140
- return x.map(v => roundCoords(v / (xLim[1] - xLim[0]) * (width - margins[1] - margins[3])));
141
- }
142
-
143
- return x.map(v =>
144
- roundCoords((v - xLim[0]) / (xLim[1] - xLim[0]) * (width - margins[1] - margins[3]) + margins[1])
145
- );
146
- }
147
-
148
- /** Rescales x-values from plot coordinates to screen (SVG) coordinates
149
- * @param {Array} x - vector with coordinates (or objects size) in original plot coordinates
150
- * @param {Array} xLim - vector with current limits for x-axis in original plot coordinates
151
- * @param {number} width - width of coordinate system in pixels
152
- * @param {boolean} doSizeScreen - scale size of objects (true) or coordinates
153
- * @returns {Array} vector with rescaled values
154
- */
155
- const scaleY = function(y, yLim, height, doSizeScale = false) {
156
- if (!$isOk || y === undefined || !Array.isArray(y)) return undefined;
157
-
158
- if (doSizeScale) {
159
- // scale size of objects instead of coordinates
160
- return y.map(v => roundCoords(v / (yLim[1] - yLim[0]) * (height - margins[0] - margins[2])));
161
- }
162
-
163
- // for coordinates we also need to invert (flip) the y-axis
164
- return y.map(v =>
165
- roundCoords((yLim[1] - v) / (yLim[1] - yLim[0]) * (height - margins[0] - margins[2]) + margins[2])
166
- );
167
- }
168
-
169
- /** Computes nice tick values for axis
170
- * @param {Array} ticks - vector with ticks if alredy available (if not, new will be computed)
171
- * @param {Array} lim - vector with axis limits tickets must be computed for
172
- * @param {number} maxTickNum - maximum number of ticks to compute
173
- * @param {boolean} round - round or not the fractions when computing nice numbers for the ticks
174
- * @returns {Array} a vector with computed tick positions
175
- */
176
- const getAxisTicks = function(ticks, lim, maxTickNum, round = true) {
177
-
178
- // if ticks are already provided do not recompute them
179
- if (ticks !== undefined) return ticks;
180
-
181
- // check if limits are ok
182
- if (!Array.isArray(lim) || lim[0] === undefined || lim[1] === undefined) return undefined;
183
-
184
- // get range as a nice number and compute min, max and steps for the tick sequence
185
- const range = niceNum(lim[1] - lim[0], round);
186
- const tickSpacing = niceNum(range / (maxTickNum - 1), round);
187
- const tickMin = Math.ceil(lim[0] / tickSpacing) * tickSpacing;
188
- const tickMax = Math.floor(lim[1] / tickSpacing) * tickSpacing;
189
-
190
- // recompute maxTickNum
191
- maxTickNum = Math.round((tickMax - tickMin + 1) / tickSpacing) + 1;
192
-
193
- // create a sequence and return
194
- ticks = [...Array(maxTickNum)].map((x, i) => tickMin + i * tickSpacing);
195
-
196
- // if step is smaller than 1 round values to remove small decimals accidentiall added by JS
197
- if (Math.abs(tickSpacing) < 1) {
198
- const r = Math.pow(10, 1 + Math.round(-Math.log10(tickSpacing)));
199
- ticks = ticks.map(v => Math.round((v + Number.EPSILON) * r) / r)
200
- }
201
-
202
- // make sure the ticks are not aligned with axes limits
203
- return ticks.filter(x => x >= lim[0] & x <= lim[1]);
204
- }
205
-
206
- /** Computes a nice spacing value for a given range
207
- * @param {numeric} localRange - a range (max - min)
208
- * @param {boolean} round - round or not the fractions when computing the number
209
- * @returns {numeric} the computed spacing value
210
- */
211
- function niceNum( localRange, round) {
212
-
213
- const exponent = Math.floor(Math.log10(localRange));
214
- const fraction = localRange / Math.pow(10, exponent);
215
- let niceFraction;
216
-
217
- if (round) {
218
- if (fraction < 1.5)
219
- niceFraction = 1;
220
- else if (fraction < 3)
221
- niceFraction = 2;
222
- else if (fraction < 7)
223
- niceFraction = 5;
224
- else
225
- niceFraction = 10;
226
- } else {
227
- if (fraction <= 1)
228
- niceFraction = 1;
229
- else if (fraction <= 2)
230
- niceFraction = 2;
231
- else if (fraction <= 5)
232
- niceFraction = 5;
233
- else
234
- niceFraction = 10;
235
- }
236
-
237
- return niceFraction * Math.pow(10, exponent);
238
- }
239
-
240
- /** Computes a scale level
241
- * @param {numeric} width - width of plotting area in pixels
242
- * @param {numeric} height - height of plotting area in pixels
243
- * @returns {text} the scale level ("small", "medium" or "large")
244
- */
245
- function getScale(width, height) {
246
- if (height < 300.2 || width < 300.2) return "small";
247
- if (height < 600.2 || width < 600.2) return "medium";
248
- return "large";
249
- }
250
-
251
- /* context with Axes constants, properties and methods to share with children */
252
- let context = {
253
-
254
- // methods
255
- addXAxisMargins: addXAxisMargins,
256
- addYAxisMargins: addYAxisMargins,
257
- adjustXAxisLimits: adjustXAxisLimits,
258
- adjustYAxisLimits: adjustYAxisLimits,
259
- getAxisTicks: getAxisTicks,
260
- scaleX: scaleX,
261
- scaleY: scaleY,
262
-
263
- // variables
264
- isOk: isOk,
265
- scale: scale,
266
- width: width,
267
- height: height,
268
- xLim: xLim,
269
- yLim: yLim,
270
-
271
- // constants
272
- LINE_STYLES: LINE_STYLES,
273
- LABELS_MARGIN: LABELS_MARGIN,
274
- TICK_NUM: TICK_NUM,
275
- }
276
-
277
- setContext('axes', context);
278
-
279
- // handle click on plot elements and dispatch manual events
280
- function dispatchClickEvent(eventName, el) {
281
- dispatch(eventName, {seriesTitle: el.parentNode.getAttribute('title'), elementID: el.dataset.id});
282
- }
283
-
284
- function handleClick(e) {
285
-
286
- // scatter plot markers
287
- if (e.target.tagName === "text" && e.target.parentNode.classList.contains("series_scatter")) {
288
- dispatchClickEvent("markerclick", e.target);
289
- return;
290
- }
291
-
292
- // bar plot bars
293
- if (e.target.tagName === "rect" && e.target.parentNode.classList.contains("series_bar")) {
294
- dispatchClickEvent("barclick", e.target);
295
- return;
296
- }
297
-
298
- // outside any plot element
299
- dispatch("axesclick")
300
- }
301
-
302
-
303
- // this is reactive in case if limX and limY are interactively changed by parent script
304
- $: if (!limX.some(v => v === undefined)) xLim.update(v => limX);
305
- $: if (!limY.some(v => v === undefined)) yLim.update(v => limY);
306
-
307
- // computes real margins in pixels based on current scale
308
- $: margins = axesMargins.map(v => v * AXES_MARGIN_FACTORS[$scale]);
309
-
310
- // computes status which tells that axes limits look fine and it is safe to draw
311
- // the status is based on the axis limits validity
312
- $: isOk.update(v =>
313
- Array.isArray($yLim) &&
314
- Array.isArray($xLim) &&
315
- $xLim.length === 2 &&
316
- $yLim.length === 2 &&
317
- !$yLim.some(v => v === undefined) &&
318
- !$xLim.some(v => v === undefined) &&
319
- !$yLim.some(v => isNaN(v)) &&
320
- !$xLim.some(v => isNaN(v)) &&
321
- $xLim[1] !== $xLim[0] &&
322
- $yLim[1] !== $yLim[0] &&
323
- $width > (margins[1] + margins[3]) &&
324
- $height > (margins[0] + margins[2])
325
- )
326
-
327
- // computes coordinates for clip path box
328
- $: cpx = $isOk ? scaleX($xLim, $xLim, $width) : [0, 1];
329
- $: cpy = $isOk ? scaleY($yLim, $yLim, $height) : [1, 0];
330
-
331
- /* observer for the axes area size - to update size of axes */
332
- const ro2 = new ResizeObserver(entries => {
333
- for (let entry of entries) {
334
- const acr = axesElement.getBoundingClientRect();
335
- width.update(x => acr.width);
336
- height.update(x => acr.height);
337
- }
338
- });
339
-
340
- /* observer for the plot area size — to update scale */
341
- const ro1 = new ResizeObserver(entries => {
342
- for (let entry of entries) {
343
- const pcr = plotElement.getBoundingClientRect();
344
- scale.update(x => getScale(pcr.width, pcr.height));
345
- }
346
- });
347
-
348
- onMount(() => {
349
- ro1.observe(plotElement);
350
- ro2.observe(axesElement);
351
- });
352
-
353
- onDestroy(() => {
354
- ro1.unobserve(plotElement);
355
- ro2.unobserve(axesElement);
356
- })
357
- </script>
358
-
359
-
360
- <div class="plot {'plot_' + $scale}" bind:this={plotElement} class:plot_error="{!$isOk}">
361
-
362
- <!-- plot title and axis labels -->
363
- {#if title !== ""}<div class="axes__title">{@html title}</div>{/if}
364
- {#if yLabel !== ""}<div class="axes__ylabel"><span>{@html yLabel}</span></div>{/if}
365
- {#if xLabel !== ""}<div class="axes__xlabel"><span>{@html xLabel}</span></div>{/if}
366
-
367
- <!-- axes (coordinate system) -->
368
- <div class="axes-wrapper" bind:this={axesElement} >
369
- <svg on:click={handleClick} on:keydown={handleClick} preserveAspectRatio="none" class="axes">
370
-
371
- <!-- define clipping path -->
372
- <defs>
373
- <clipPath id="{clipPathID}">
374
- <rect style="pointer-events:none" x="{cpx[0]}" y="{cpy[1]}" width = "{cpx[1] - cpx[0]}" height="{cpy[0] - cpy[1]}"></rect>
375
- </clipPath>
376
- </defs>
377
-
378
- <!-- axis and box -->
379
- <slot name="xaxis"></slot>
380
- <slot name="yaxis"></slot>
381
-
382
- <!-- main plot content -->
383
- <g class="axes-content" clip-path="url(#{clipPathID})">
384
- <slot></slot>
385
- </g>
386
-
387
- <!-- axis and box -->
388
- <slot name="box"></slot>
389
-
390
- </svg>
391
- {#if !$isOk}
392
- <p class="message_error">
393
- Axes component was not properly initialized. <br />
394
- Add plot series (check that coordinates are numeric) or define axes limits manually.
395
- </p>
396
- {/if}
397
- </div>
398
-
399
-
400
- </div>
401
-
402
- <style>
403
-
404
- /* Plot (main container) */
405
- .plot {
406
- font-family: Arial, Helvetica, sans-serif;
407
-
408
- display: grid;
409
- grid-template-columns: min-content auto;
410
- grid-template-rows: min-content auto min-content;
411
- grid-template-areas:
412
- ". title"
413
- "ylab axes"
414
- ". xlab";
415
-
416
- box-sizing: border-box;
417
- background: #fefefe;
418
- min-width: 100px;
419
- min-height: 50px;
420
- width: 100%;
421
- height: 100%;
422
- padding: 0;
423
- margin: 0;
424
- }
425
-
426
- :global(.plot_small) {
427
- font-size: 11px;
428
- }
429
-
430
- :global(.plot_medium) {
431
- font-size: 13px;
432
- }
433
-
434
- :global(.plot_large) {
435
- font-size: 16px;
436
- }
437
-
438
- :global(.plot_error) {
439
- display: flex;
440
- }
441
-
442
- :global(.plot_error > .axes-wrapper) {
443
- display: none;
444
- }
445
-
446
- :global(.message_error) {
447
- font-size: 1.2em;
448
- color: crimson;
449
- padding: 1em;
450
- box-sizing: border-box;
451
- text-align: center;
452
- }
453
-
454
- /* Axes (coordinate system) */
455
- .axes-wrapper {
456
- grid-area: axes;
457
- position:relative;
458
- box-sizing: border-box;
459
- display: flex;
460
- width: 100%;
461
- height: 100%;
462
- padding: 0;
463
- margin: 0;
464
- }
465
-
466
- :global(.axes) {
467
- display: block;
468
- box-sizing: border-box;
469
- position:absolute;
470
-
471
- padding: 0;
472
- margin: 0;
473
- height: 100%;
474
- width: 100%;
475
- max-height: 100%;
476
- max-width: 100%;
477
- min-height: 100%;
478
- min-width: 100%;
479
- }
480
-
481
- :global(.axes-content) {
482
- padding: 0;
483
- margin: 0;
484
- height: 100%;
485
- width: 100%;
486
- max-height: 100%;
487
- max-width: 100%;
488
- min-height: 100%;
489
- min-width: 100%;
490
-
491
- }
492
-
493
- :global(.axes__xlabel) {
494
- grid-area: xlab;
495
- font-size: 1.0em;
496
- font-weight: 600;
497
- padding: 0.25em;
498
- text-align: center;
499
- }
500
-
501
-
502
- :global(.axes__ylabel) {
503
- grid-area: ylab;
504
- font-size: 1.0em;
505
- font-weight: 600;
506
- padding: 0.25em;
507
- text-align: center;
508
- vertical-align: middle;
509
- display: flex;
510
- }
511
-
512
- :global(.axes__ylabel > span) {
513
- width: 1.5em;
514
- line-height: 1.5em;
515
- display: inline-block;
516
- writing-mode: vertical-rl;
517
- transform: rotate(180deg);
518
- }
519
-
520
-
521
- :global(.axes__title) {
522
- background: transparent;
523
- grid-area: title;
524
-
525
- font-size: 1.3em;
526
- font-weight: bold;
527
- line-height: 1.2em;
528
- padding: 0.5em 0;
529
- text-align: center;
530
- }
531
-
532
- /* Axis */
533
- :global(.axis-labels) {
534
- fill: #303030;
535
- font-size: 0.95em;
536
- }
537
-
538
- /* Data labels */
539
- :global(.labels) {
540
- fill: #606060;
541
- font-size: 0.90em;
542
- }
543
-
544
- :global(.labels) {
545
- visibility: hidden;
546
- transition:visibility 0.25s linear, opacity 0.25s linear;
547
- opacity: 0;
548
- }
549
-
550
- </style>
@@ -1,68 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte';
3
- import { Colors } from './Colors';
4
- import { max, mrange, diff } from 'mdatools/stat';
5
- import Rectangles from './Rectangles.svelte';
6
-
7
- /* input parameters */
8
- export let xValues;
9
- export let yValues;
10
- export let barWidth = 0.8;
11
- export let title = "";
12
- export let faceColor = Colors.PRIMARY;
13
- export let borderColor = Colors.PRIMARY;
14
- export let showLabels = "no"; // can be "no", "hover", "always"
15
-
16
- // TODO: implemented later
17
- //export let labels = yValues;
18
-
19
- /* internal parameters */
20
- let width;
21
- let left;
22
- let top;
23
- let height;
24
-
25
- // to access shared parameters and methods from Axes
26
- const axes = getContext('axes');
27
-
28
- /* reactive actions related to x-values, fires when there are changes in:
29
- * - xValues
30
- * - barWidth
31
- */
32
- $: {
33
-
34
- if (!Array.isArray(xValues)) {
35
- throw("BarSeries: parameter 'xValues' must be a numeric vector.");
36
- }
37
-
38
- if (barWidth <= 0 || barWidth > 1) {
39
- throw("BarSeries: parameters 'barWidth' should be between 0 and 1.");
40
- }
41
-
42
- const xValuesRange = mrange(xValues, 0.1);
43
- xValuesRange[0] = xValuesRange[0] - barWidth * diff(xValuesRange) / xValues.length * 0.5
44
- xValuesRange[1] = xValuesRange[1] + barWidth * diff(xValuesRange) / xValues.length * 0.5
45
- axes.adjustXAxisLimits(xValuesRange);
46
-
47
- width = Array(xValues.length).fill(max(diff(xValues)) * barWidth);
48
- left = xValues.map((v, i) => v - width[i]/2);
49
- }
50
-
51
- /* reactive actions related to y-values, fires when there are changes in:
52
- * - yValues
53
- */
54
- $: {
55
-
56
- if (!Array.isArray(yValues) || xValues.length != yValues.length) {
57
- throw("BarSeries: parameter 'yValues' must be a numeric vector of the same length as 'xValues'.");
58
- }
59
-
60
- const yValuesRange = mrange(yValues, showLabels === "no" ? 0.05 : 0.20);
61
- axes.adjustYAxisLimits(yValuesRange);
62
-
63
- top = yValues.map(v => v > 0 ? v : 0);
64
- height = yValues.map(v => Math.abs(v));
65
- }
66
- </script>
67
-
68
- <Rectangles style="series_bar" {left} {top} {width} {height} {borderColor} {faceColor} {title} />
package/src/Box.svelte DELETED
@@ -1,35 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte';
3
- import { Colors } from './Colors';
4
- import Rectangles from './Rectangles.svelte';
5
-
6
- /* input parameters */
7
- export let slot;
8
-
9
- // check that the box is located in a correct slot
10
- if (slot !== "box") {
11
- throw("Component Box must have \"slot='box'\" attribute.")
12
- }
13
-
14
- // get axes context and reactive variables needed to compute coordinates
15
- const axes = getContext('axes');
16
- const xLim = axes.xLim;
17
- const yLim = axes.yLim;
18
- const isOk = axes.isOk;
19
-
20
- // reactive variables for coordinates of box points in pixels
21
- $: left = [$xLim[0]];
22
- $: top = [$yLim[1]];
23
- $: width = [$xLim[1] - $xLim[0]];
24
- $: height = [$yLim[1] - $yLim[0]];
25
-
26
- </script>
27
-
28
- {#if $isOk}
29
- <g style="pointer-events:none" class="mdaplot__axes-box">
30
- <Rectangles {left} {top} {width} {height} borderColor="{Colors.DARKGRAY}" faceColor="transparent"></Rectangles>
31
- </g>
32
- {/if}
33
-
34
- <style>
35
- </style>
@@ -1,50 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte';
3
- import { mrange } from 'mdatools/stat';
4
- import { Colors } from './Colors';
5
-
6
- // input parameters
7
- export let xValues;
8
- export let yValues;
9
- export let title = "";
10
- export let lineWidth = 1;
11
- export let lineColor = Colors.PRIMARY;
12
- export let lineType = 1;
13
-
14
- /* sanity check of input parameters */
15
- if (!Array.isArray(xValues) || !Array.isArray(yValues) || xValues.length != yValues.length) {
16
- throw("LineSeries: parameters 'xValues' and 'yValues' must be numeric vectors of the same length.");
17
- }
18
-
19
- // compute ranges for x and y values
20
- const xValuesRange = mrange(xValues, 0.05);
21
- const yValuesRange = mrange(yValues, 0.05);
22
-
23
- // get axes context and adjust axes limits
24
- const axes = getContext('axes');
25
- axes.adjustXAxisLimits(xValuesRange);
26
- axes.adjustYAxisLimits(yValuesRange);
27
-
28
- // get reactive variables needed to compute coordinates
29
- const xLim = axes.xLim;
30
- const yLim = axes.yLim;
31
- const axesWidth = axes.width;
32
- const axesHeight = axes.height;
33
- const scale = axes.scale;
34
-
35
- // reactive variables for coordinates of data points in pixels
36
- $: x = axes.scaleX(xValues, $xLim, $axesWidth);
37
- $: y = axes.scaleY(yValues, $yLim, $axesHeight);
38
- $: p = x !== undefined && y !== undefined ? x.map((v, i) => `${v},${y[i]}`).join(' ') : undefined;
39
- $: lineStyleStr = `fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px;
40
- stroke-dasharray:${axes.LINE_STYLES[$scale][lineType - 1]}`;
41
- </script>
42
-
43
- {#if p !== undefined}
44
- <g class="series series_line" style={lineStyleStr} title={title}>
45
- <polyline class="line" points={p}/>
46
- </g>
47
- {/if}
48
-
49
- <style>
50
- </style>