svelte-plots-basic 1.0.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.
- package/README.md +130 -0
- package/dist/index.js +4069 -0
- package/dist/index.mjs +4047 -0
- package/package.json +35 -0
- package/src/AreaSeries.svelte +53 -0
- package/src/Axes.svelte +483 -0
- package/src/BarSeries.svelte +80 -0
- package/src/Box.svelte +35 -0
- package/src/Colors.js +15 -0
- package/src/LineSeries.svelte +50 -0
- package/src/Rectangles.svelte +58 -0
- package/src/ScatterSeries.svelte +81 -0
- package/src/Segments.svelte +48 -0
- package/src/TextLabels.svelte +63 -0
- package/src/TextLegend.svelte +38 -0
- package/src/XAxis.svelte +69 -0
- package/src/YAxis.svelte +72 -0
- package/src/index.js +16 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import { mrange } from 'mdatools/stat';
|
|
5
|
+
import { Colors } from './Colors';
|
|
6
|
+
|
|
7
|
+
// input parameters
|
|
8
|
+
export let xValues;
|
|
9
|
+
export let yValues;
|
|
10
|
+
export let title = "";
|
|
11
|
+
export let lineWidth = 1;
|
|
12
|
+
export let lineColor = Colors.PRIMARY;
|
|
13
|
+
export let lineType = 1;
|
|
14
|
+
|
|
15
|
+
/* sanity check of input parameters */
|
|
16
|
+
if (!Array.isArray(xValues) || !Array.isArray(yValues) || xValues.length != yValues.length) {
|
|
17
|
+
throw("LineSeries: parameters 'xValues' and 'yValues' must be numeric vectors of the same length.");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// compute ranges for x and y values
|
|
21
|
+
const xValuesRange = mrange(xValues, 0.05);
|
|
22
|
+
const yValuesRange = mrange(yValues, 0.05);
|
|
23
|
+
|
|
24
|
+
// get axes context and adjust axes limits
|
|
25
|
+
const axes = getContext('axes');
|
|
26
|
+
axes.adjustXAxisLimits(xValuesRange);
|
|
27
|
+
axes.adjustYAxisLimits(yValuesRange);
|
|
28
|
+
|
|
29
|
+
// get reactive variables needed to compute coordinates
|
|
30
|
+
const xLim = axes.xLim;
|
|
31
|
+
const yLim = axes.yLim;
|
|
32
|
+
const axesWidth = axes.width;
|
|
33
|
+
const axesHeight = axes.height;
|
|
34
|
+
const scale = axes.scale;
|
|
35
|
+
|
|
36
|
+
// reactive variables for coordinates of data points in pixels
|
|
37
|
+
$: x = axes.scaleX(xValues, $xLim, $axesWidth);
|
|
38
|
+
$: y = axes.scaleY(yValues, $yLim, $axesHeight);
|
|
39
|
+
$: p = x !== undefined && y !== undefined ? x.map((v, i) => `${v},${y[i]}`).join(' ') : undefined;
|
|
40
|
+
$: lineStyleStr = `fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px;stroke-dasharray:${axes.LINE_STYLES[$scale][lineType - 1]}`;
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{#if p !== undefined}
|
|
44
|
+
<g class="series lineseries" style="{lineStyleStr}" title="{title}">
|
|
45
|
+
<polyline class="line" points="{p}"/>
|
|
46
|
+
</g>
|
|
47
|
+
{/if}
|
|
48
|
+
|
|
49
|
+
<style>
|
|
50
|
+
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import { Colors } from './Colors';
|
|
4
|
+
|
|
5
|
+
/* input parameters */
|
|
6
|
+
export let left;
|
|
7
|
+
export let top;
|
|
8
|
+
export let width;
|
|
9
|
+
export let height;
|
|
10
|
+
export let labels = undefined;
|
|
11
|
+
export let faceColor = Colors.PRIMARY;
|
|
12
|
+
export let borderColor = faceColor;
|
|
13
|
+
export let lineWidth = 1;
|
|
14
|
+
|
|
15
|
+
// styles for bars and labels
|
|
16
|
+
const barsStyleStr = `fill:${faceColor};stroke:${borderColor};stroke-width: ${lineWidth}px;`;
|
|
17
|
+
|
|
18
|
+
// multiply width and height values if needed
|
|
19
|
+
if (!Array.isArray(left) || !Array.isArray(top) || left.length < 1 || left.length != top.length) {
|
|
20
|
+
throw("Rectangles: parameters 'left' and 'top' must be vectors of the same size.")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// we make this reactive in case if left and right has been changed but not width
|
|
24
|
+
const n = left.length;
|
|
25
|
+
if (!Array.isArray(height)) height = Array(n).fill(height);
|
|
26
|
+
if (!Array.isArray(width)) width = Array(n).fill(width);
|
|
27
|
+
|
|
28
|
+
/* sanity check for input parameters */
|
|
29
|
+
if (top.length !== n || width.length !== n || height.length !== n) {
|
|
30
|
+
throw("Rectangles: x, y, w and h should have the same length (w and h can be single values).")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (labels !== undefined && (!Array.isArray(labels) || labels.length !== n)) {
|
|
34
|
+
throw("Rectangles: vector with labels should have the same length as vectors with x and y coordinates.")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// get axes context and reactive variables needed to compute coordinates
|
|
38
|
+
const axes = getContext('axes');
|
|
39
|
+
const xLim = axes.xLim;
|
|
40
|
+
const yLim = axes.yLim;
|
|
41
|
+
const axesWidth = axes.width;
|
|
42
|
+
const axesHeight = axes.height;
|
|
43
|
+
|
|
44
|
+
// reactive variables for coordinates of data points in pixels
|
|
45
|
+
$: rx = axes.scaleX(left, $xLim, $axesWidth);
|
|
46
|
+
$: ry = axes.scaleY(top, $yLim, $axesHeight);
|
|
47
|
+
$: rw = axes.scaleX(width, $xLim, $axesWidth, true);
|
|
48
|
+
$: rh = axes.scaleY(height, $yLim, $axesHeight, true);
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
{#if rx !== undefined && ry !== undefined}
|
|
52
|
+
{#each left as v, i}
|
|
53
|
+
<rect x="{rx[i]}" y="{ry[i]}" width="{rw[i]}" height="{rh[i]}" style="{barsStyleStr}"></rect>
|
|
54
|
+
{/each}
|
|
55
|
+
{/if}
|
|
56
|
+
|
|
57
|
+
<style>
|
|
58
|
+
</style>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import { mrange } from 'mdatools/stat';
|
|
5
|
+
import { Colors } from './Colors';
|
|
6
|
+
import TextLabels from './TextLabels.svelte';
|
|
7
|
+
|
|
8
|
+
// input parameters
|
|
9
|
+
export let xValues;
|
|
10
|
+
export let yValues;
|
|
11
|
+
export let marker = 1
|
|
12
|
+
export let title = "";
|
|
13
|
+
export let faceColor = "transparent";
|
|
14
|
+
export let borderColor = Colors.PRIMARY;
|
|
15
|
+
export let borderWidth = 1;
|
|
16
|
+
export let markerSize = 1;
|
|
17
|
+
|
|
18
|
+
// TODO: implement later
|
|
19
|
+
//export let labels = yValues;
|
|
20
|
+
//export let showLabels = "no"; // can be "no", "hover", "always"
|
|
21
|
+
|
|
22
|
+
const markers = ["●", "◼", "▲", "▼", "⬥", "+", "*", "⨯"];
|
|
23
|
+
let markerSymbol;
|
|
24
|
+
|
|
25
|
+
/* sanity check of input parameters */
|
|
26
|
+
if (typeof(marker) !== "number" || marker < 1 || marker > markers.length) {
|
|
27
|
+
throw(`ScatterSeries: parameter 'marker' must be a number from 1 to ${markers.length}."`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// to access shared parameters and methods from Axes
|
|
31
|
+
const axes = getContext('axes');
|
|
32
|
+
|
|
33
|
+
/* reactive actions related to x-values, fires when there are changes in:
|
|
34
|
+
* - xValues
|
|
35
|
+
* - marker
|
|
36
|
+
*/
|
|
37
|
+
$: {
|
|
38
|
+
if (!Array.isArray(xValues)) {
|
|
39
|
+
throw("ScatterSeries: parameter 'xValues' must be a numeric vector.");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const xValuesRange = mrange(xValues, 0.05);
|
|
43
|
+
axes.adjustXAxisLimits(xValuesRange);
|
|
44
|
+
|
|
45
|
+
markerSymbol = "";
|
|
46
|
+
markerSymbol = markers[marker - 1];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* reactive actions related to y-values, fires when there are changes in:
|
|
50
|
+
* - yValues
|
|
51
|
+
*/
|
|
52
|
+
$: {
|
|
53
|
+
if (!Array.isArray(yValues) || xValues.length != yValues.length) {
|
|
54
|
+
throw("BarSeries: parameter 'yValues' must be a numeric vector of the same length as 'xValues'.");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const yValuesRange = mrange(yValues, 0.05);
|
|
58
|
+
axes.adjustYAxisLimits(yValuesRange);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<g class="series series_scatter" title="{title}">
|
|
64
|
+
<TextLabels {xValues} {yValues} labels="{markerSymbol}" textSize="{markerSize}" {faceColor} {borderColor} {borderWidth} />
|
|
65
|
+
</g>
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
:global(.marker) {
|
|
69
|
+
font-size: 1em;
|
|
70
|
+
cursor: default;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:global(.marker:hover) {
|
|
74
|
+
opacity: 90%;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
:global(.series_scatter > *:hover + .labels_hover) {
|
|
78
|
+
visibility: visible;
|
|
79
|
+
opacity: 1;
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import { Colors } from './Colors';
|
|
4
|
+
|
|
5
|
+
/* input parameters */
|
|
6
|
+
export let xStart;
|
|
7
|
+
export let xEnd;
|
|
8
|
+
export let yStart;
|
|
9
|
+
export let yEnd;
|
|
10
|
+
export let lineColor = Colors.PRIMARY;
|
|
11
|
+
export let lineType = 1;
|
|
12
|
+
export let lineWidth = 1;
|
|
13
|
+
|
|
14
|
+
/* sanity check for input parameters */
|
|
15
|
+
if (!Array.isArray(xStart) || !Array.isArray(xEnd) || !Array.isArray(yStart) || !Array.isArray(yEnd)) {
|
|
16
|
+
throw("Segments: parameters 'xStart', 'yStart', 'xEnd' and 'yEnd' must be vectors.")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const n = xStart.length;
|
|
20
|
+
if (xEnd.length !== n || yStart.length !== n || yEnd.length !== n) {
|
|
21
|
+
throw("Segments: parameters 'xStart', 'yStart', 'xEnd' and 'yEnd' should have the same length.")
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// get axes context and reactive variables needed to compute coordinates
|
|
25
|
+
const axes = getContext('axes');
|
|
26
|
+
const xLim = axes.xLim;
|
|
27
|
+
const yLim = axes.yLim;
|
|
28
|
+
const axesWidth = axes.width;
|
|
29
|
+
const axesHeight = axes.height;
|
|
30
|
+
const scale = axes.scale;
|
|
31
|
+
|
|
32
|
+
// reactive variables for coordinates of data points in pixels (and line style)
|
|
33
|
+
$: x1 = axes.scaleX(xStart, $xLim, $axesWidth);
|
|
34
|
+
$: x2 = axes.scaleX(xEnd, $xLim, $axesWidth);
|
|
35
|
+
$: y1 = axes.scaleY(yStart, $yLim, $axesHeight);
|
|
36
|
+
$: y2 = axes.scaleY(yEnd, $yLim, $axesHeight);
|
|
37
|
+
$: lineStyleStr = `stroke:${lineColor};stroke-width: ${lineWidth}px;stroke-dasharray:${axes.LINE_STYLES[$scale][lineType - 1]}`;
|
|
38
|
+
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
{#if x1 !== undefined && y1 !== undefined}
|
|
42
|
+
{#each x1 as v, i}
|
|
43
|
+
<line x1="{x1[i]}" x2="{x2[i]}" y1="{y1[i]}" y2="{y2[i]}" style="{lineStyleStr}"></line>
|
|
44
|
+
{/each}
|
|
45
|
+
{/if}
|
|
46
|
+
|
|
47
|
+
<style>
|
|
48
|
+
</style>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import { Colors } from './Colors';
|
|
4
|
+
|
|
5
|
+
/* input parameters */
|
|
6
|
+
export let xValues;
|
|
7
|
+
export let yValues;
|
|
8
|
+
export let labels;
|
|
9
|
+
export let pos = 0;
|
|
10
|
+
export let faceColor = Colors.PRIMARY_TEXT;
|
|
11
|
+
export let borderColor = "transparent";
|
|
12
|
+
export let borderWidth = 0;
|
|
13
|
+
export let textSize = 1;
|
|
14
|
+
|
|
15
|
+
// text-anchor values depending on position
|
|
16
|
+
const textAnchors = ["middle", "middle", "start", "middle", "end"];
|
|
17
|
+
|
|
18
|
+
/* sanity check for input parameters */
|
|
19
|
+
if (!Array.isArray(xValues) || !Array.isArray(yValues) || xValues.length !== yValues.length) {
|
|
20
|
+
throw("TextLabels: parameters 'xValues' and 'yValues' must be vectors of the same length.")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// multiply labels values if needed
|
|
24
|
+
$: {
|
|
25
|
+
const n = xValues.length;
|
|
26
|
+
if (!Array.isArray(labels)) labels = Array(n).fill(labels);
|
|
27
|
+
|
|
28
|
+
// workaround for an issue when xValues and yValues are changed in parent app
|
|
29
|
+
// but array of labels is still the same as in the
|
|
30
|
+
if (labels.length != n) labels = Array(n).fill(labels[0]);
|
|
31
|
+
|
|
32
|
+
// check that the length of labels vector is correct
|
|
33
|
+
if (labels.length !== n) {
|
|
34
|
+
throw("TextLabels: parameter 'labels' must be a single text value or a vector of the same size as 'x' and 'y'.")
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// get axes context and reactive variables needed to compute coordinates
|
|
39
|
+
const axes = getContext('axes');
|
|
40
|
+
const xLim = axes.xLim;
|
|
41
|
+
const yLim = axes.yLim;
|
|
42
|
+
const axesWidth = axes.width;
|
|
43
|
+
const axesHeight = axes.height;
|
|
44
|
+
const scale = axes.scale;
|
|
45
|
+
|
|
46
|
+
// reactive variables for coordinates of data points in pixels
|
|
47
|
+
$: x = axes.scaleX(xValues, $xLim, $axesWidth);
|
|
48
|
+
$: y = axes.scaleY(yValues, $yLim, $axesHeight);
|
|
49
|
+
$: dx = [0, 0, 1, 0, -1][pos] * axes.LABELS_MARGIN[$scale];
|
|
50
|
+
$: dy = [0, 1, 0, -1, 0][pos] * axes.LABELS_MARGIN[$scale];
|
|
51
|
+
|
|
52
|
+
// styles for bars and labels
|
|
53
|
+
$: textStyleStr = `fill:${faceColor};stroke-width:${borderWidth}px;stroke:${borderColor};font-size:${textSize}em;`;
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
{#if x !== undefined && y !== undefined}
|
|
57
|
+
{#each x as v, i}
|
|
58
|
+
<text style={textStyleStr} x={x[i]} y={y[i]} dx={dx} dy={dy} dominant-baseline="middle" text-anchor={textAnchors[pos]}>{@html labels[i]}</text>
|
|
59
|
+
{/each}
|
|
60
|
+
{/if}
|
|
61
|
+
|
|
62
|
+
<style>
|
|
63
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import { Colors } from './Colors';
|
|
4
|
+
|
|
5
|
+
/* input parameters */
|
|
6
|
+
export let left;
|
|
7
|
+
export let top;
|
|
8
|
+
export let dx = "0";
|
|
9
|
+
export let dy = "1.25em";
|
|
10
|
+
export let elements;
|
|
11
|
+
export let faceColor = Colors.PRIMARY_TEXT;
|
|
12
|
+
export let borderColor = "transparent";
|
|
13
|
+
export let borderWidth = 0;
|
|
14
|
+
export let textSize = 1;
|
|
15
|
+
|
|
16
|
+
// get axes context and reactive variables needed to compute coordinates
|
|
17
|
+
const axes = getContext('axes');
|
|
18
|
+
const xLim = axes.xLim;
|
|
19
|
+
const yLim = axes.yLim;
|
|
20
|
+
const axesWidth = axes.width;
|
|
21
|
+
const axesHeight = axes.height;
|
|
22
|
+
const scale = axes.scale;
|
|
23
|
+
|
|
24
|
+
// reactive variables for coordinates of data points in pixels
|
|
25
|
+
$: x = axes.scaleX([left], $xLim, $axesWidth);
|
|
26
|
+
$: y = axes.scaleY([top], $yLim, $axesHeight);
|
|
27
|
+
|
|
28
|
+
// styles for bars and labels
|
|
29
|
+
$: textStyleStr = `fill:${faceColor};stroke-width:${borderWidth}px;stroke:${borderColor};font-size:${textSize}em;`;
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
{#if x !== undefined && y !== undefined && elements.length > 0}
|
|
33
|
+
<text style={textStyleStr} x={x} y={y} dx={dx} dy={dy} dominant-baseline="middle" text-anchor="start">
|
|
34
|
+
{#each elements as el, i}
|
|
35
|
+
<tspan x={x} dx={dx} dy={i === 0 ? 0 : dy}>{@html el}</tspan>
|
|
36
|
+
{/each}
|
|
37
|
+
</text>
|
|
38
|
+
{/if}
|
package/src/XAxis.svelte
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import { Colors } from './Colors';
|
|
4
|
+
|
|
5
|
+
// input parameters
|
|
6
|
+
export let slot = "xaxis"; // slot the component must be placed in
|
|
7
|
+
export let ticks = undefined; // vector with numeric tick positions in plot units
|
|
8
|
+
export let tickLabels = ticks; // vector with labels for each tick
|
|
9
|
+
export let showGrid = false; // logical, show or not grid lines
|
|
10
|
+
|
|
11
|
+
// set up tick mode
|
|
12
|
+
const tickMode = ticks === undefined ? "auto" : "manual";
|
|
13
|
+
|
|
14
|
+
/* sanity checks of input parameters */
|
|
15
|
+
if (slot !== "xaxis") {
|
|
16
|
+
throw("Component XAxis must have \"slot='xaxis'\" attribute.")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (ticks !== undefined && !Array.isArray(ticks)) {
|
|
20
|
+
throw("XAxis: 'ticks' must be a vector of numbers.")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (ticks !== undefined && !(Array.isArray(tickLabels) && tickLabels.length == ticks.length)) {
|
|
24
|
+
throw("XAxis: 'tickLabels' must be a vector of the same size as ticks.")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* styles for axis and grid lines */
|
|
28
|
+
const axisLineStyleStr = `stroke:${Colors.DARKGRAY};line-width:1px;`;
|
|
29
|
+
const gridLineStyleStr = `stroke:${Colors.MIDDLEGRAY};stroke-opacity:${showGrid?1:0};stroke-dasharray:2px;`;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// get axes context and adjust x margins
|
|
33
|
+
const axes = getContext('axes');
|
|
34
|
+
axes.addXAxisMargins();
|
|
35
|
+
|
|
36
|
+
// get reactive variables needed to compute coordinates
|
|
37
|
+
const xLim = axes.xLim;
|
|
38
|
+
const yLim = axes.yLim;
|
|
39
|
+
const axesWidth = axes.width;
|
|
40
|
+
const axesHeight = axes.height;
|
|
41
|
+
const scale = axes.scale;
|
|
42
|
+
const isOk = axes.isOk;
|
|
43
|
+
|
|
44
|
+
// reactive variables for coordinates of axis lines
|
|
45
|
+
$: x = axes.scaleX($xLim, $xLim, $axesWidth);
|
|
46
|
+
$: y = axes.scaleY($yLim, $yLim, $axesHeight);
|
|
47
|
+
|
|
48
|
+
// reactive variables for ticks and their coordinates
|
|
49
|
+
$: dy = $scale === "small" ? 7 : 10;
|
|
50
|
+
$: tickNum = axes.TICK_NUM[$scale];
|
|
51
|
+
$: ticks = tickMode === "auto" ? axes.getAxisTicks(undefined, $xLim, tickNum, true) : ticks;
|
|
52
|
+
$: tickLabels = tickMode === "auto" ? ticks : tickLabels;
|
|
53
|
+
$: ticksX = axes.scaleX(ticks, $xLim, $axesWidth);
|
|
54
|
+
$: ticksY = y === undefined ? undefined : [y[0], y[0] + dy];
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
{#if $isOk && x !== undefined && y !== undefined }
|
|
58
|
+
<g class="mdaplot__axis mdaplot__xaxis">
|
|
59
|
+
{#each ticksX as tx, i}
|
|
60
|
+
<line x1="{tx}" x2="{tx}" y1="{y[0]}" y2="{y[1]}" style="{gridLineStyleStr}"></line>
|
|
61
|
+
<line x1="{tx}" x2="{tx}" y1="{ticksY[0]}" y2="{ticksY[1]}" style="{axisLineStyleStr}"></line>
|
|
62
|
+
<text x="{tx}" y="{ticksY[1]}" dx="0" dy="{dy}" class="mdaplot__axis-labels" dominant-baseline="middle" text-anchor="middle">{tickLabels[i]}</text>
|
|
63
|
+
{/each}
|
|
64
|
+
<line x1="{x[0]}" x2="{x[1]}" y1="{y[0]}" y2="{y[0]}" style="{axisLineStyleStr}"></line>
|
|
65
|
+
</g>
|
|
66
|
+
{/if}
|
|
67
|
+
|
|
68
|
+
<style>
|
|
69
|
+
</style>
|
package/src/YAxis.svelte
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
import { Colors } from './Colors';
|
|
4
|
+
|
|
5
|
+
// input parameters
|
|
6
|
+
export let slot = "yaxis"; // slot the component must be placed in
|
|
7
|
+
export let ticks = undefined; // vector with numeric tick positions in plot units
|
|
8
|
+
export let tickLabels = ticks; // vector with labels for each tick
|
|
9
|
+
export let showGrid = false; // logical, show or not grid lines
|
|
10
|
+
export let las = 1;
|
|
11
|
+
|
|
12
|
+
// set up tick mode
|
|
13
|
+
const tickMode = ticks === undefined ? "auto" : "manual";
|
|
14
|
+
|
|
15
|
+
// TODO: set up tick text translation
|
|
16
|
+
const transform = las > 1 ? "" : "";
|
|
17
|
+
|
|
18
|
+
/* sanity checks of input parameters */
|
|
19
|
+
if (slot !== "yaxis") {
|
|
20
|
+
throw("Component YAxis must have \"slot='yaxis'\" attribute.")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (ticks !== undefined && !Array.isArray(ticks)) {
|
|
24
|
+
throw("YAxis: 'ticks' must be a vector of numbers.")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (ticks !== undefined && !(Array.isArray(tickLabels) && tickLabels.length == ticks.length)) {
|
|
28
|
+
throw("YAxis: 'tickLabels' must be a vector of the same size as ticks.")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* styles for axis and grid lines */
|
|
32
|
+
const axisLineStyleStr = `stroke:${Colors.DARKGRAY};line-width:1px;`;
|
|
33
|
+
const gridLineStyleStr = `stroke:${Colors.MIDDLEGRAY};stroke-opacity:${showGrid?1:0};stroke-dasharray:2px;`;
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// get axes context and adjust x margins
|
|
37
|
+
const axes = getContext('axes');
|
|
38
|
+
axes.addYAxisMargins();
|
|
39
|
+
|
|
40
|
+
// get reactive variables needed to compute coordinates
|
|
41
|
+
const xLim = axes.xLim;
|
|
42
|
+
const yLim = axes.yLim;
|
|
43
|
+
const axesWidth = axes.width;
|
|
44
|
+
const axesHeight = axes.height;
|
|
45
|
+
const scale = axes.scale;
|
|
46
|
+
|
|
47
|
+
// reactive variables for coordinates of axis lines
|
|
48
|
+
$: x = axes.scaleX($xLim, $xLim, $axesWidth);
|
|
49
|
+
$: y = axes.scaleY($yLim, $yLim, $axesHeight);
|
|
50
|
+
|
|
51
|
+
// reactive variables for ticks and their coordinates
|
|
52
|
+
$: dx = $scale === "small" ? -4 : -6;
|
|
53
|
+
$: tickNum = axes.TICK_NUM[$scale];
|
|
54
|
+
$: ticks = tickMode === "auto" ? axes.getAxisTicks(undefined, $yLim, tickNum, true) : ticks;
|
|
55
|
+
$: tickLabels = tickMode === "auto" ? ticks : tickLabels;
|
|
56
|
+
$: ticksY = axes.scaleY(ticks, $yLim, $axesHeight);
|
|
57
|
+
$: ticksX = x === undefined ? undefined : [x[0] + dx, x[0]];
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
{#if x !== undefined && y !== undefined }
|
|
61
|
+
<g class="mdaplot__axis mdaplot__yaxis">
|
|
62
|
+
{#each ticksY as ty, i}
|
|
63
|
+
<line x1="{x[0]}" x2="{x[1]}" y1="{ty}" y2="{ty}" style="{gridLineStyleStr}"></line>
|
|
64
|
+
<line x1="{ticksX[0]}" x2="{ticksX[1]}" y1="{ty}" y2="{ty}" style="{axisLineStyleStr}" ></line>
|
|
65
|
+
<text x="{ticksX[0]}" y="{ty}" dx="{dx}" dy="{0}" {transform} style="background:red" class="mdaplot__axis-labels" dominant-baseline="middle" text-anchor="end">{tickLabels[i]}</text>
|
|
66
|
+
{/each}
|
|
67
|
+
<line x1="{x[0]}" x2="{x[0]}" y1="{y[0]}" y2="{y[1]}" style="{axisLineStyleStr}" ></line>
|
|
68
|
+
</g>
|
|
69
|
+
{/if}
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
</style>
|
package/src/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as Axes } from './Axes.svelte';
|
|
2
|
+
export { default as XAxis } from './XAxis.svelte';
|
|
3
|
+
export { default as YAxis } from './YAxis.svelte';
|
|
4
|
+
export { default as Box } from './Box.svelte';
|
|
5
|
+
|
|
6
|
+
export { default as Rectangles } from './Rectangles.svelte';
|
|
7
|
+
export { default as Segments } from './Segments.svelte';
|
|
8
|
+
export { default as TextLabels } from './TextLabels.svelte';
|
|
9
|
+
export { default as TextLegend } from './TextLegend.svelte';
|
|
10
|
+
|
|
11
|
+
export { default as BarSeries } from './BarSeries.svelte';
|
|
12
|
+
export { default as ScatterSeries } from './ScatterSeries.svelte';
|
|
13
|
+
export { default as LineSeries } from './LineSeries.svelte';
|
|
14
|
+
export { default as AreaSeries } from './AreaSeries.svelte';
|
|
15
|
+
|
|
16
|
+
export { Colors } from './Colors.js';
|