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.
Files changed (50) hide show
  1. package/README.md +54 -69
  2. package/package.json +28 -33
  3. package/src/2d/Area.svelte +61 -0
  4. package/src/2d/Axes.svelte +500 -0
  5. package/src/2d/Axis.svelte +50 -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/Legend.svelte +148 -0
  12. package/src/2d/Lines.svelte +49 -0
  13. package/src/2d/Multilines.svelte +67 -0
  14. package/src/2d/Points.svelte +79 -0
  15. package/src/2d/Rectangles.svelte +74 -0
  16. package/src/2d/Segments.svelte +65 -0
  17. package/src/2d/TextLabels.svelte +107 -0
  18. package/src/2d/TextLegend.svelte +53 -0
  19. package/src/2d/XAxis.svelte +99 -0
  20. package/src/2d/YAxis.svelte +99 -0
  21. package/src/{index.js → 2d/index.js} +10 -6
  22. package/src/3d/Axes.svelte +445 -0
  23. package/src/3d/Axis.svelte +64 -0
  24. package/src/3d/AxisLines.svelte +50 -0
  25. package/src/3d/AxisTickLabels.svelte +54 -0
  26. package/src/3d/Lines.svelte +49 -0
  27. package/src/3d/Mesh.svelte +188 -0
  28. package/src/3d/Points.svelte +61 -0
  29. package/src/3d/Segments.svelte +69 -0
  30. package/src/3d/TextLabels.svelte +79 -0
  31. package/src/3d/XAxis.svelte +123 -0
  32. package/src/3d/YAxis.svelte +123 -0
  33. package/src/3d/ZAxis.svelte +123 -0
  34. package/src/3d/index.js +13 -0
  35. package/src/Colors.js +36 -1
  36. package/src/Utils.js +205 -0
  37. package/dist/index.js +0 -4209
  38. package/dist/index.mjs +0 -4187
  39. package/src/AreaSeries.svelte +0 -53
  40. package/src/Axes.svelte +0 -538
  41. package/src/BarSeries.svelte +0 -78
  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 -85
  46. package/src/Segments.svelte +0 -48
  47. package/src/TextLabels.svelte +0 -78
  48. package/src/TextLegend.svelte +0 -38
  49. package/src/XAxis.svelte +0 -69
  50. package/src/YAxis.svelte +0 -72
@@ -0,0 +1,65 @@
1
+ <script>
2
+ /****************************************************
3
+ * Bars *
4
+ * -------------------- *
5
+ * shows series of bars on a plot *
6
+ *****************************************************/
7
+
8
+ import { max, diff } from 'mdatools/stat';
9
+ import { Vector } from 'mdatools/arrays';
10
+ import { Colors } from '../Colors';
11
+ import { checkCoords } from '../Utils';
12
+
13
+ import Rectangles from './Rectangles.svelte';
14
+
15
+
16
+ /*****************************************/
17
+ /* Input parameters */
18
+ /*****************************************/
19
+
20
+ export let xValues; // vector with x-coordinates of middle points of the bars
21
+ export let yValues; // vector with y-coordinates of top points of the bars
22
+ export let barWidth = 0.8; // width of bars as per cent of maximum width
23
+ export let faceColor = Colors.PRIMARY; // face color of the bars
24
+ export let borderColor = Colors.PRIMARY; // border color of the bars
25
+ export let title = ''; // title of the bar series (reserved for future use)
26
+
27
+
28
+ /*****************************************/
29
+ /* Component code */
30
+ /*****************************************/
31
+
32
+ let width, left, top, height;
33
+
34
+ // reactive code for computing position of left sides and bar width
35
+ $: {
36
+
37
+ if (!barWidth) {
38
+ barWidth = 0.8;
39
+ }
40
+
41
+ if (barWidth <= 0 || barWidth > 1) {
42
+ throw Error('BarSeries: parameters "barWidth" should be between 0 and 1.');
43
+ }
44
+
45
+ // compute maximum bar width and position of left side
46
+ const xv = checkCoords(xValues, 'BarSeries');
47
+ const w = max(diff(xv)) * barWidth;
48
+ left = xv.subtract(w/2);
49
+ width = Vector.fill(w, xv.length);
50
+ }
51
+
52
+ // reactive code for computing position of top sides and bar height
53
+ $: {
54
+
55
+ const yv = checkCoords(yValues, 'BarSeries');
56
+ if (yv.length !== left.length) {
57
+ throw Error('BarSeries: parameters "yValues" must be vector of the same length as "xValues".');
58
+ }
59
+
60
+ top = yv.apply(v => v > 0 ? v : 0);
61
+ height = yv.apply(v => Math.abs(v));
62
+ }
63
+ </script>
64
+
65
+ <Rectangles className="series_bar" {left} {top} {width} {height} {borderColor} {faceColor} {title} />
@@ -0,0 +1,50 @@
1
+ <script>
2
+ /****************************************************
3
+ * Box *
4
+ * -------------------- *
5
+ * shows border box around axes *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { Colors } from '../Colors';
10
+
11
+
12
+ /*****************************************/
13
+ /* Input parameters */
14
+ /*****************************************/
15
+
16
+ export let slot; // slot name, must be "box"
17
+
18
+
19
+ /*****************************************/
20
+ /* Component code */
21
+ /*****************************************/
22
+
23
+ // check that the box is located in a correct slot
24
+ if (slot !== 'box') {
25
+ throw('Component Box must have \'slot="box"\' attribute.')
26
+ }
27
+
28
+ // box style
29
+ const rectStyleStr = `fill:transparent;stroke:${Colors.DARKGRAY};stroke-width:1px;`;
30
+
31
+ // get axes context and reactive variables needed to compute coordinates
32
+ const axes = getContext('axes');
33
+ const xLim = axes.xLim;
34
+ const yLim = axes.yLim;
35
+ const isOk = axes.isOk;
36
+ const tX = axes.tX;
37
+ const tY = axes.tY;
38
+
39
+ // reactive variables for coordinates of box points in pixels
40
+ $: xx = $isOk ? axes.transform($xLim, $tX.coords) : undefined;
41
+ $: yy = $isOk ? axes.transform($yLim, $tY.coords) : undefined;
42
+
43
+ </script>
44
+
45
+ {#if $isOk}
46
+ <g style="pointer-events:none" class="mdaplot__axes-box">
47
+ <rect x={xx[0]} y={yy[1]} width={xx[1] - xx[0]} height={yy[0] - yy[1]} style={rectStyleStr} />
48
+ </g>
49
+ {/if}
50
+
@@ -0,0 +1,36 @@
1
+ <script>
2
+ /****************************************************
3
+ * ColorLegend *
4
+ * -------------------- *
5
+ * shows color legend on top part of the plot *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { Colors } from '../Colors';
10
+
11
+
12
+ /*****************************************/
13
+ /* Input parameters */
14
+ /*****************************************/
15
+
16
+ export let colormap; // colormap returned by method getcolormap() from colors
17
+
18
+ /*****************************************/
19
+ /* Component code */
20
+ /*****************************************/
21
+
22
+ const axes = getContext('axes');
23
+ const xLim = axes.xLim;
24
+ const yLim = axes.yLim;
25
+ const tX = axes.tX;
26
+ const tY = axes.tY;
27
+ const isOk = axes.isOk;
28
+
29
+
30
+ // TODO: will be implemented as a sequence of rectangles and text labels beneath them
31
+
32
+ // compute coordinates of rectangles and their colors
33
+
34
+ // compute coordinates of text labels
35
+ </script>
36
+
@@ -0,0 +1,148 @@
1
+ <script>
2
+ /****************************************************
3
+ * Legend *
4
+ * -------------------- *
5
+ * shows legend for plot components *
6
+ *****************************************************/
7
+
8
+ import { mean } from 'mdatools/stat';
9
+ import { getContext } from 'svelte';
10
+ import { Colors } from '../Colors';
11
+
12
+
13
+ /*****************************************/
14
+ /* Input parameters */
15
+ /*****************************************/
16
+
17
+ export let items; // array with text labels for each legend element
18
+ export let position = "topleft"; // position of the legend ("topleft", "top", "topright", "right", "bottomright", etc).
19
+
20
+
21
+ /*****************************************/
22
+ /* Component code */
23
+ /*****************************************/
24
+
25
+ const axes = getContext('axes');
26
+ const scale = axes.scale;
27
+ const xLim = axes.xLim;
28
+ const yLim = axes.yLim;
29
+ const tX = axes.tX;
30
+ const tY = axes.tY;
31
+ const isOk = axes.isOk;
32
+
33
+
34
+ /**
35
+ * Computes width of text element for given font.
36
+ *
37
+ * @param {string} text - string with text
38
+ * @param {string} font - font name and size, e.g. '12px Arial'
39
+ *
40
+ * @return {number} size of element in pixels
41
+ */
42
+ function getTextWidth(text, font) {
43
+ const element = document.createElement('canvas');
44
+ const context = element.getContext('2d');
45
+ context.font = font;
46
+ return context.measureText(text).width;
47
+ }
48
+
49
+ /**
50
+ * Compute size of main legend elements.
51
+ *
52
+ * @param {Array} items - array of legend items and their properties.
53
+ * @param {number} fontSize - font size of a legend element.
54
+ * @param {string} position - position of the legend.
55
+ *
56
+ * @return {Array} array with height and width og graphical part of legend item, padding size,
57
+ * height and width of text labels (all in pixels).
58
+ */
59
+ function getLegendSize(items, fontSize, position) {
60
+
61
+ // compute size of graphical elements
62
+ const elHeight = fontSize; // height of legend element without padding
63
+ const elPadding = elHeight / 4; // top and bottom padding
64
+ const elWidth = elHeight * 1.5; // width of legend element without padding
65
+
66
+ // compute size of text label elements
67
+ // TODO: implement one row legend if position is "top" or "bottom"
68
+ const lbHeight = elHeight;
69
+ let lbWidth = 0;
70
+ for (let i = 0; i < items.length; i++) {
71
+ const w = getTextWidth(' ' + items[i].label + ' ', fontSize + 'px Arial');
72
+ lbWidth = w > lbWidth ? w : lbWidth;
73
+ }
74
+
75
+ return [elHeight, elWidth, elPadding, lbHeight, lbWidth];
76
+ }
77
+
78
+ // reactive expression to compute all sizes and coordinates
79
+ let left, top, elHeight, elWidth, elPadding, lbHeight, lbWidth, legendHeight, legendWidth, fontSize;
80
+ $: if ($isOk) {
81
+
82
+ fontSize = axes.LEGEND_FONT_SIZE[$scale];
83
+
84
+ // compute size of elements
85
+ [elHeight, elWidth, elPadding, lbHeight, lbWidth] = getLegendSize(items, fontSize, position);
86
+
87
+ // compute size of whole legend box
88
+ legendHeight = (elHeight + 2 * elPadding) * items.length;
89
+ legendWidth = (elWidth + 2 * elPadding + lbWidth);
90
+
91
+ // compute coordinates of top left corner of the legend box
92
+ const xLimPx = axes.transform($xLim, $tX.coords);
93
+ left = position.includes("left") ? xLimPx[0] + axes.TICK_SIZE[$scale] :
94
+ position.includes("right") ? xLimPx[1] - legendWidth - axes.TICK_SIZE[$scale] :
95
+ mean(xLimPx) - legendWidth/2;
96
+
97
+ const yLimPx = axes.transform($yLim, $tY.coords);
98
+ top = position.includes("top") ? yLimPx[1] + axes.TICK_SIZE[$scale] :
99
+ position.includes("bottom") ? yLimPx[0] - legendHeight - axes.TICK_SIZE[$scale] :
100
+ mean(yLimPx) - legendHeight/2;
101
+ }
102
+ </script>
103
+
104
+ {#if $isOk }
105
+
106
+ <!-- outer legend box, background and frame -->
107
+ <svg x="{left}px" y="{top}px" height="{legendHeight}px" width="{legendWidth}">
108
+ <rect height="100%" width="100%" style="fill:white;stroke:{Colors.MIDDLEGRAY};"></rect>
109
+
110
+ {#each items as item, i}
111
+
112
+ <!-- individual legend item -->
113
+ <svg x="{0}px" y="{i * (elHeight + 2 * elPadding)}px" width="{legendWidth}px" height="{elHeight + 2 * elPadding}px">
114
+
115
+ <!-- line -->
116
+ {#if item.lineType && item.lineType > 0 && item.lineType <= 4}
117
+ <line x1={elPadding} x2={elPadding + elWidth} y1={(elHeight + elPadding * 2)/2} y2={(elHeight + elPadding * 2)/2} style={`
118
+ stroke:${item.lineColor ? item.lineColor : Colors.PRIMARY};
119
+ stroke-width: ${item.lineWidth ? item.lineWidth : 1}px;
120
+ stroke-dasharray:${axes.LINE_STYLES[$scale][item.lineType - 1]}
121
+ `}/>
122
+ {/if}
123
+
124
+ <!-- marker -->
125
+ {#if item.marker && item.marker > 0 && item.marker < axes.MARKER_SYMBOLS.length}
126
+ <text x="{(elWidth + 2 * elPadding)/2}px" y="{(elHeight + 2 * elPadding)/2}px"
127
+ dominant-baseline="middle"
128
+ style={`
129
+ fill:${item.faceColor ? item.faceColor : "transparent"};
130
+ stroke-width:${item.borderWidth ? item.borderWidth : 1}px;
131
+ stroke:${item.borderColor ? item.borderColor : Colors.PRIMARY};
132
+ font-size:${fontSize}px;
133
+ text-anchor:middle;`}
134
+ >{axes.MARKER_SYMBOLS[item.marker - 1]}</text>
135
+ {/if}
136
+
137
+
138
+
139
+ <!-- text -->
140
+ <text x="{elWidth + elPadding * 3}px" y="{elPadding}px"
141
+ dominant-baseline="hanging"
142
+ style={`text-anchor:start;fill:${Colors.LEGEND};font-size:${fontSize}px`};
143
+ >{@html '&nbsp;' + item.label}</text>
144
+
145
+ </svg>
146
+ {/each}
147
+ </svg>
148
+ {/if}
@@ -0,0 +1,49 @@
1
+ <script>
2
+ /****************************************************
3
+ * Lines *
4
+ * -------------------- *
5
+ * shows lines connected sequence of points *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { Colors } from '../Colors';
10
+ import { val2p } from '../Utils';
11
+
12
+
13
+ /*****************************************/
14
+ /* Input parameters */
15
+ /*****************************************/
16
+
17
+ export let xValues; // vector or array with x-coordinates of the points
18
+ export let yValues; // vector or array with y-coordinates of the points
19
+ export let lineWidth = 1; // width (thickness) of the lines
20
+ export let lineColor = Colors.PRIMARY; // color of the lines
21
+ export let lineType = 1; // type of the lines (1 - solid, 2 - dashed, 3 - dotted, 4 - dashdot)
22
+ export let title = ''; // title of the bar series (reserved for future use)
23
+
24
+
25
+ /*****************************************/
26
+ /* Component code */
27
+ /*****************************************/
28
+
29
+ // get axes context
30
+ const axes = getContext('axes');
31
+
32
+ const scale = axes.scale;
33
+ const isOk = axes.isOk;
34
+ const tX = axes.tX;
35
+ const tY = axes.tY;
36
+
37
+ // compute polynomial coordinates as string
38
+ $: p = $isOk ? val2p(xValues, yValues, $tX, $tY, 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
+
@@ -0,0 +1,67 @@
1
+ <script>
2
+ /****************************************************
3
+ * Multilines *
4
+ * -------------------- *
5
+ * shows series of lines components *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { ismatrix } from 'mdatools/arrays';
10
+ import { Colors } from '../Colors';
11
+ import { val2p } from '../Utils';
12
+
13
+
14
+ /*****************************************/
15
+ /* Input parameters */
16
+ /*****************************************/
17
+
18
+ export let xValues; // vector or array with x-coordinates of the points
19
+ export let yValues; // matrix (!) with y-coordinates of the points - every column is separate line
20
+ export let lineWidth = 1; // width (thickness) of the lines
21
+ export let lineColor = Colors.PRIMARY; // color of the lines
22
+ export let lineType = 1; // type of the lines (1 - solid, 2 - dashed, 3 - dotted, 4 - dashdot)
23
+ export let title = ''; // title of the bar series (reserved for future use)
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 tX = axes.tX;
36
+ const tY = axes.tY;
37
+
38
+ // compute polynomial coordinates as string
39
+ let pp;
40
+ $: if ($isOk) {
41
+
42
+ if (!ismatrix(yValues)) {
43
+ throw Error('Multilines: parameter "yValues" must be a matrix.');
44
+ }
45
+
46
+ if (xValues.length !== yValues.nrows) {
47
+ throw Error('Multilines: parameter "xValues" must have the same number of values as number of rows in "yValues".');
48
+ }
49
+
50
+ pp = new Array(yValues.ncols);
51
+ for (let i = 0; i < pp.length; i++) {
52
+ pp[i] = val2p(xValues, yValues.getcolumn(i + 1), $tX, $tY, axes);
53
+ }
54
+ }
55
+
56
+ // reactive variables for coordinates of data points in pixels
57
+ $: lineStyleStr = `fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px; stroke-dasharray:${axes.LINE_STYLES[$scale][lineType-1]}`;
58
+ </script>
59
+
60
+ {#if $isOk && pp !== undefined && pp.length > 0}
61
+ <g class="series series_multiline" style={lineStyleStr} title={title}>
62
+ {#each pp as p}
63
+ <polyline class="line" points={p}/>
64
+ {/each}
65
+ </g>
66
+ {/if}
67
+
@@ -0,0 +1,79 @@
1
+ <script>
2
+ /****************************************************
3
+ * Points *
4
+ * -------------------- *
5
+ * shows series of points/markers on a plot *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { Colors } from '../Colors';
10
+ import { checkCoords } from '../Utils';
11
+
12
+
13
+ /*****************************************/
14
+ /* Input parameters */
15
+ /*****************************************/
16
+
17
+ export let xValues; // array of vector with x-coordinates of points
18
+ export let yValues; // array of vector with y-coordinates of points
19
+ export let marker = 1 // index for point symbol (from 1 to 8): "●", "◼", "▲", "▼", "⬥", "+", "*", "✕"
20
+ export let faceColor = 'transparent'; // face (fill) color of the points
21
+ export let borderColor = Colors.PRIMARY; // border color of the points
22
+ export let borderWidth = 1; // width (thickness) of the points
23
+ export let markerSize = 1; // size of the marker symbols
24
+ export let title = ''; // title of the point series - required for handling mouse click events
25
+
26
+
27
+ /*****************************************/
28
+ /* Component code */
29
+ /*****************************************/
30
+
31
+ // get axes context and adjust x margins
32
+ const axes = getContext('axes');
33
+ const tX = axes.tX;
34
+ const tY = axes.tY;
35
+ const isOk = axes.isOk;
36
+
37
+ let x, y, markerSymbol;
38
+
39
+ // reactive calculations triggered by changes in coordinates and plot parameters
40
+ $: if ($isOk) {
41
+
42
+ if (typeof(marker) !== "number" || marker < 1 || marker > axes.MARKER_SYMBOLS.length) {
43
+ throw Error(`ScatterSeries: parameter "marker" must be a number from 1 to ${axes.MARKER_SYMBOLS.length}.`);
44
+ }
45
+
46
+ markerSymbol = axes.MARKER_SYMBOLS[marker - 1];
47
+
48
+
49
+ x = axes.transform(checkCoords(xValues, 'Points'), $tX.coords);
50
+ y = axes.transform(checkCoords(yValues, 'Points'), $tY.coords);
51
+
52
+ // sanity check for input parameters
53
+ if (x.length !== y.length) {
54
+ throw Error('Points: parameters "xValues" and "yValues" must be vectors of the same length.')
55
+ }
56
+ }
57
+
58
+
59
+ // styles for the elements
60
+ $: textStyleStr = `dominant-baseline:middle;fill:${faceColor};stroke-width:${borderWidth}px;stroke:${borderColor};
61
+ font-size:${markerSize}em; text-anchor:middle;cursor:default;user-select:none;`;
62
+ </script>
63
+
64
+ {#if $isOk && x !== undefined && y !== undefined}
65
+ <g class="series series_points" title={title} style={textStyleStr} >
66
+ {#each x as v, i}
67
+ <text x={x[i]} y={y[i]}>{markerSymbol}</text>
68
+ {/each}
69
+ </g>
70
+ {/if}
71
+
72
+ <style>
73
+ text, text > :global(tspan) {
74
+ dominant-baseline: middle;
75
+ text-anchor: middle;
76
+ cursor: default;
77
+ user-select: none;
78
+ }
79
+ </style>
@@ -0,0 +1,74 @@
1
+ <script>
2
+ /****************************************************
3
+ * Rectangles *
4
+ * -------------------- *
5
+ * shows series of rectangles *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { Vector } from 'mdatools/arrays';
10
+ import { Colors } from '../Colors';
11
+ import { checkCoords } from '../Utils';
12
+
13
+
14
+ /*****************************************/
15
+ /* Input parameters */
16
+ /*****************************************/
17
+
18
+ export let left; // array of vector with coordinates of left sides of the bars
19
+ export let top; // array of vector with coordinates of top sides of the bars
20
+ export let width; // single value (same for all) or vector/array with bar width
21
+ export let height; // single value (same for all) or vector/array with bar height
22
+ export let faceColor = Colors.PRIMARY; // color of bar faces (fill)
23
+ export let borderColor = faceColor; // color of bar borders
24
+ export let lineWidth = 1; // width (thickness) of bar border lines
25
+ export let className = 'series_rect'; // CSS class name of the SVG group
26
+ export let title = ''; // title of the rectangle series (reserved for future use)
27
+
28
+
29
+ /*****************************************/
30
+ /* Component code */
31
+ /*****************************************/
32
+
33
+ // get axes context and reactive variables needed to compute coordinates
34
+ const axes = getContext('axes');
35
+ const tX = axes.tX;
36
+ const tY = axes.tY;
37
+ const isOk = axes.isOk;
38
+
39
+ let rx, ry, rw, rh = undefined;
40
+ $: {
41
+ if ($isOk) {
42
+ rx = axes.transform(checkCoords(left, 'Rectangles'), $tX.coords);
43
+ ry = axes.transform(checkCoords(top, 'Rectangles'), $tY.coords);
44
+
45
+ if (rx.length !== ry.length) {
46
+ throw Error('Rectangles: parameters "left" and "top" must be vectors of the same length.');
47
+ }
48
+
49
+ if (typeof width !== 'object') {
50
+ width = Vector.fill(width, left.length);
51
+ }
52
+
53
+ if (typeof height !== 'object') {
54
+ height = Vector.fill(height, left.length);
55
+ }
56
+
57
+ rw = axes.transform(width, $tX.objects);
58
+ rh = axes.transform(height, $tY.objects);
59
+ }
60
+ }
61
+
62
+ // styles for bars and labels
63
+ $: barsStyleStr = `fill:${faceColor};stroke:${borderColor};stroke-width:${lineWidth}px;`;
64
+ </script>
65
+
66
+ {#if $isOk}
67
+ <g class="series {className}" title={title} style={barsStyleStr}>
68
+ {#each left as v, i}
69
+ <rect x={rx[i]} y={ry[i]} width={rw[i]} height={rh[i]} />
70
+ {/each}
71
+ </g>
72
+ {/if}
73
+
74
+
@@ -0,0 +1,65 @@
1
+ <script>
2
+ /****************************************************
3
+ * Segments *
4
+ * -------------------- *
5
+ * shows series of line segments *
6
+ *****************************************************/
7
+
8
+ import { getContext } from 'svelte';
9
+ import { Colors } from '../Colors';
10
+ import { checkCoords } from '../Utils';
11
+
12
+ /*****************************************/
13
+ /* Input parameters */
14
+ /*****************************************/
15
+
16
+ export let xStart; // vector or array with x-coordinates of starting points
17
+ export let xEnd; // vector or array with x-coordinates of end points
18
+ export let yStart; // vector or array with y-coordinates of starting points
19
+ export let yEnd; // vector or array with y-coordinates of end points
20
+ export let lineColor = Colors.PRIMARY; // color of segment lines
21
+ export let lineType = 1; // type of segment lines (1 - solid, 2 - dashed, 3 - dotted, 4 - dashdot)
22
+ export let lineWidth = 1; // width (thickness) of segment lines
23
+ export let className = 'series_seg'; // CSS class name of the SVG group
24
+ export let title = ''; // title of the segment series (reserved for future use)
25
+
26
+
27
+ /*****************************************/
28
+ /* Component code */
29
+ /*****************************************/
30
+
31
+ // get axes context and reactive variables needed to compute coordinates
32
+ const axes = getContext('axes');
33
+ const scale = axes.scale;
34
+ const isOk = axes.isOk;
35
+ const tX = axes.tX;
36
+ const tY = axes.tY;
37
+
38
+ let x1, x2, y1, y2 = undefined;
39
+ $: {
40
+ if ($isOk) {
41
+
42
+ x1 = axes.transform(checkCoords(xStart, 'Segments'), $tX.coords);
43
+ y1 = axes.transform(checkCoords(yStart, 'Segments'), $tY.coords);
44
+ x2 = axes.transform(checkCoords(xEnd, 'Segments'), $tX.coords);
45
+ y2 = axes.transform(checkCoords(yEnd, 'Segments'), $tY.coords);
46
+
47
+ const n = x1.length;
48
+ if (x2.length !== n || y1.length !== n || y2.length !== n) {
49
+ throw Error('Segments: parameters "xStart", "yStart", "xEnd" and "yEnd" should have the same length.');
50
+ }
51
+ }
52
+ }
53
+
54
+ // reactive variables for coordinates of data points in pixels (and line style)
55
+ $: lineStyleStr = `stroke:${lineColor};stroke-width: ${lineWidth}px;stroke-dasharray:${axes.LINE_STYLES[$scale][lineType-1]}`;
56
+ </script>
57
+
58
+ {#if $isOk}
59
+ <g class="series {className}" title={title} style={lineStyleStr}>
60
+ {#each x1 as v, i}
61
+ <line x1={x1[i]} x2={x2[i]} y1={y1[i]} y2={y2[i]} />
62
+ {/each}
63
+ </g>
64
+ {/if}
65
+