svelte-plots-basic 1.0.3 → 1.0.6

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/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "dist"
26
26
  ],
27
27
  "description": "Svelte components for creating simple plots",
28
- "version": "1.0.3",
28
+ "version": "1.0.6",
29
29
  "repository": {
30
30
  "type": "git",
31
31
  "url": "svkucheryavski/svelte-plots-basic"
package/src/Axes.svelte CHANGED
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { onMount, setContext } from 'svelte';
2
+ import { onMount, setContext, createEventDispatcher } from 'svelte';
3
3
  import { writable } from 'svelte/store';
4
4
 
5
5
  /* input parameters */
@@ -10,7 +10,8 @@
10
10
  export let yLabel = ""; // label for y-axis
11
11
  export let multiSeries = true; // is the plot for one series or for many
12
12
 
13
- /* constants for internal use */
13
+ // event dispatcher
14
+ const dispatch = createEventDispatcher();
14
15
 
15
16
  // how big are margins (number of pixels in unit margin value) between axis and plot area if axis are shown
16
17
  const AXES_MARGIN_FACTORS = {
@@ -277,6 +278,30 @@
277
278
  });
278
279
 
279
280
 
281
+ // handle click on plot elements and dispatch manual events
282
+ function dispatchClickEvent(eventName, el) {
283
+ dispatch(eventName, {seriesTitle: el.parentNode.getAttribute('title'), elementID: el.dataset.id});
284
+ }
285
+
286
+ function handleClick(e) {
287
+
288
+ // scatter plot markers
289
+ if (e.target.tagName === "text" && e.target.parentNode.classList.contains("series_scatter")) {
290
+ dispatchClickEvent("markerclick", e.target);
291
+ return;
292
+ }
293
+
294
+ // bar plot bars
295
+ if (e.target.tagName === "rect" && e.target.parentNode.classList.contains("series_bar")) {
296
+ dispatchClickEvent("barclick", e.target);
297
+ return;
298
+ }
299
+
300
+ // outside any plot element
301
+ dispatch("axesclick")
302
+ }
303
+
304
+
280
305
  // this is reactive in case if limX and limY are interactively changed by parent script
281
306
  $: if (!limX.some(v => v === undefined)) xLim.update(v => limX);
282
307
  $: if (!limY.some(v => v === undefined)) yLim.update(v => limY);
@@ -316,12 +341,12 @@
316
341
 
317
342
  <!-- axes (coordinate system) -->
318
343
  <div class="axes-wrapper" bind:this={axesWrapper} >
319
- <svg preserveAspectRatio="none" class="axes">
344
+ <svg on:click={handleClick} preserveAspectRatio="none" class="axes">
320
345
 
321
346
  <!-- define clipping path -->
322
347
  <defs>
323
348
  <clipPath id="{clipPathID}">
324
- <rect x="{cpx[0]}" y="{cpy[1]}" width = "{cpx[1] - cpx[0]}" height="{cpy[0] - cpy[1]}"></rect>
349
+ <rect style="pointer-events:none" x="{cpx[0]}" y="{cpy[1]}" width = "{cpx[1] - cpx[0]}" height="{cpy[0] - cpy[1]}"></rect>
325
350
  </clipPath>
326
351
  </defs>
327
352
 
@@ -65,9 +65,7 @@
65
65
  }
66
66
  </script>
67
67
 
68
- <g class="series series_bar" title="{title}">
69
- <Rectangles {left} {top} {width} {height} {borderColor} {faceColor} />
70
- </g>
68
+ <Rectangles style="series_bar" {left} {top} {width} {height} {borderColor} {faceColor} {title} />
71
69
 
72
70
  <style>
73
71
  :global(.series_bar > rect){
package/src/Box.svelte CHANGED
@@ -26,7 +26,7 @@
26
26
  </script>
27
27
 
28
28
  {#if $isOk}
29
- <g class="mdaplot__axes-box">
29
+ <g style="pointer-events:none" class="mdaplot__axes-box">
30
30
  <Rectangles {left} {top} {width} {height} borderColor="{Colors.DARKGRAY}" faceColor="transparent"></Rectangles>
31
31
  </g>
32
32
  {/if}
@@ -1,5 +1,4 @@
1
1
  <script>
2
-
3
2
  import { getContext } from 'svelte';
4
3
  import { mrange } from 'mdatools/stat';
5
4
  import { Colors } from './Colors';
@@ -37,12 +36,13 @@
37
36
  $: x = axes.scaleX(xValues, $xLim, $axesWidth);
38
37
  $: y = axes.scaleY(yValues, $yLim, $axesHeight);
39
38
  $: 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]}`;
39
+ $: lineStyleStr = `fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px;
40
+ stroke-dasharray:${axes.LINE_STYLES[$scale][lineType - 1]}`;
41
41
  </script>
42
42
 
43
43
  {#if p !== undefined}
44
- <g class="series lineseries" style="{lineStyleStr}" title="{title}">
45
- <polyline class="line" points="{p}"/>
44
+ <g class="series series_line" style={lineStyleStr} title={title}>
45
+ <polyline class="line" points={p}/>
46
46
  </g>
47
47
  {/if}
48
48
 
@@ -11,9 +11,9 @@
11
11
  export let faceColor = Colors.PRIMARY;
12
12
  export let borderColor = faceColor;
13
13
  export let lineWidth = 1;
14
+ export let title = "";
15
+ export let style = "series_rect";
14
16
 
15
- // styles for bars and labels
16
- const barsStyleStr = `fill:${faceColor};stroke:${borderColor};stroke-width: ${lineWidth}px;`;
17
17
 
18
18
  // multiply width and height values if needed
19
19
  if (!Array.isArray(left) || !Array.isArray(top) || left.length < 1 || left.length != top.length) {
@@ -46,12 +46,18 @@
46
46
  $: ry = axes.scaleY(top, $yLim, $axesHeight);
47
47
  $: rw = axes.scaleX(width, $xLim, $axesWidth, true);
48
48
  $: rh = axes.scaleY(height, $yLim, $axesHeight, true);
49
+
50
+ // styles for bars and labels
51
+ $: barsStyleStr = `fill:${faceColor};stroke:${borderColor};stroke-width: ${lineWidth}px;`;
52
+
49
53
  </script>
50
54
 
51
55
  {#if rx !== undefined && ry !== undefined}
56
+ <g class="series {style}" title={title} style={barsStyleStr}>
52
57
  {#each left as v, i}
53
- <rect x="{rx[i]}" y="{ry[i]}" width="{rw[i]}" height="{rh[i]}" style="{barsStyleStr}"></rect>
58
+ <rect x={rx[i]} y={ry[i]} width={rw[i]} height={rh[i]} />
54
59
  {/each}
60
+ </g>
55
61
  {/if}
56
62
 
57
63
  <style>
@@ -19,6 +19,7 @@
19
19
  //export let labels = yValues;
20
20
  //export let showLabels = "no"; // can be "no", "hover", "always"
21
21
 
22
+ /* constants for internal use */
22
23
  const markers = ["●", "◼", "▲", "▼", "⬥", "+", "*", "⨯"];
23
24
  let markerSymbol;
24
25
 
@@ -57,20 +58,23 @@
57
58
  const yValuesRange = mrange(yValues, 0.05);
58
59
  axes.adjustYAxisLimits(yValuesRange);
59
60
  }
60
-
61
61
  </script>
62
62
 
63
- <g class="series series_scatter" title="{title}">
64
- <TextLabels {xValues} {yValues} labels="{markerSymbol}" textSize="{markerSize}" {faceColor} {borderColor} {borderWidth} />
65
- </g>
63
+ <TextLabels
64
+ {xValues} {yValues} {faceColor} {borderColor} {borderWidth} {title}
65
+ style="series_scatter"
66
+ labels={markerSymbol}
67
+ textSize={markerSize}
68
+ />
66
69
 
67
70
  <style>
68
- :global(.marker) {
71
+
72
+ :global(.series_scatter > text) {
69
73
  font-size: 1em;
70
74
  cursor: default;
71
75
  }
72
76
 
73
- :global(.marker:hover) {
77
+ :global(.series_scatter > text:hover) {
74
78
  opacity: 90%;
75
79
  }
76
80
 
@@ -1,8 +1,15 @@
1
1
  <script>
2
+ /****************************************************
3
+ * TextLabels component *
4
+ * -------------------- *
5
+ * shows a series of text labels on the plot *
6
+ * can be used as basis for marker plot *
7
+ *****************************************************/
8
+
2
9
  import { getContext } from 'svelte';
3
10
  import { Colors } from './Colors';
4
11
 
5
- /* input parameters */
12
+ // input parameters
6
13
  export let xValues;
7
14
  export let yValues;
8
15
  export let labels;
@@ -11,16 +18,18 @@
11
18
  export let borderColor = "transparent";
12
19
  export let borderWidth = 0;
13
20
  export let textSize = 1;
21
+ export let style = "";
22
+ export let title = "series_text";
14
23
 
15
24
  // text-anchor values depending on position
16
25
  const textAnchors = ["middle", "middle", "start", "middle", "end"];
17
26
 
18
- /* sanity check for input parameters */
27
+ // sanity check for input parameters
19
28
  if (!Array.isArray(xValues) || !Array.isArray(yValues) || xValues.length !== yValues.length) {
20
29
  throw("TextLabels: parameters 'xValues' and 'yValues' must be vectors of the same length.")
21
30
  }
22
31
 
23
- // multiply labels values if needed
32
+ // multiply label values if needed
24
33
  $: {
25
34
  const n = xValues.length;
26
35
  if (!Array.isArray(labels)) labels = Array(n).fill(labels);
@@ -49,15 +58,21 @@
49
58
  $: dx = [0, 0, 1, 0, -1][pos] * axes.LABELS_MARGIN[$scale];
50
59
  $: dy = [0, 1, 0, -1, 0][pos] * axes.LABELS_MARGIN[$scale];
51
60
 
52
- // styles for bars and labels
53
- $: textStyleStr = `fill:${faceColor};stroke-width:${borderWidth}px;stroke:${borderColor};font-size:${textSize}em;`;
61
+ // styles for the elements
62
+ $: textStyleStr = `fill:${faceColor};stroke-width:${borderWidth}px;stroke:${borderColor};
63
+ font-size:${textSize}em; text-anchor:${textAnchors[pos]};`;
54
64
  </script>
55
65
 
56
66
  {#if x !== undefined && y !== undefined}
67
+ <g class="series {style}" title={title} style={textStyleStr} >
57
68
  {#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>
69
+ <text data-id={i} x={x[i]} y={y[i]} dx={dx} dy={dy}>{@html labels[i]}</text>
59
70
  {/each}
71
+ </g>
60
72
  {/if}
61
73
 
62
74
  <style>
63
- </style>
75
+ text {
76
+ dominant-baseline: middle;
77
+ }
78
+ </style>
@@ -32,7 +32,7 @@
32
32
  {#if x !== undefined && y !== undefined && elements.length > 0}
33
33
  <text style={textStyleStr} x={x} y={y} dx={dx} dy={dy} dominant-baseline="middle" text-anchor="start">
34
34
  {#each elements as el, i}
35
- <tspan x={x} dx={dx} dy={i === 0 ? 0 : dy}>{@html el}</tspan>
35
+ <tspan {x} {dx} dy={i === 0 ? 0 : dy}>{@html el}</tspan>
36
36
  {/each}
37
37
  </text>
38
38
  {/if}