svelte-plots-basic 2.5.2 → 2.5.4

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "svelte-plots-basic",
3
3
  "description": "Svelte components for creating simple plots",
4
- "version": "2.5.2",
4
+ "version": "2.5.4",
5
5
  "author": "Sergey Kucheryavskiy",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -96,7 +96,7 @@
96
96
 
97
97
  tfCoords = [
98
98
  [[], []],
99
- [[ticksX1.v[tickNum - 1]], [$yLim[1]]],
99
+ [[ticksX2.v[tickNum - 1] + dX], [$yLim[1]]],
100
100
  ];
101
101
  }
102
102
  </script>
package/src/Utils.js CHANGED
@@ -1,6 +1,25 @@
1
1
  import { cbind, vector, isvector, Vector } from 'mdatools/arrays';
2
2
  import { min, max, diff } from 'mdatools/stat';
3
3
 
4
+ /**
5
+ * Trim number leaving only significant decimals.
6
+ * @param {number} num
7
+ * @returns trimmed number
8
+ */
9
+ function trimNum(num) {
10
+
11
+ // check if number is whole — return as is
12
+ if (num === Math.round(num)) return num;
13
+
14
+ // Convert to string with precision to maintain significant digits
15
+ let str = num.toPrecision(12);
16
+
17
+ // Remove trailing zeros
18
+ str = str.replace(/\.?0+$/, '');
19
+
20
+ // Convert back to number
21
+ return parseFloat(str);
22
+ }
4
23
 
5
24
  /**
6
25
  * Generate vector with axis tick labels and tick factor based on numeric tick values.
@@ -14,37 +33,29 @@ export function getTickLabels(ticks) {
14
33
  if (ticks === undefined) return undefined;
15
34
  if (ticks.length === 1) return [0, [ticks[0].toString()]];
16
35
 
17
- const step = Math.abs(min(diff(ticks)));
36
+ // compute and correct step between ticks
37
+ let step = trimNum(Math.abs(min(diff(ticks))));
18
38
  let tickFactor = 0;
19
39
 
20
40
  // step is large (over 1)
21
41
  if (step >= 1 && ticks.length > 1) {
22
42
  if (step < 100) return [0, Array.from(ticks).map(v => v.toFixed(0))];
23
-
24
- let digNum = Math.ceil(Math.log10(step));
43
+ let digNum = Math.ceil(trimNum(Math.log10(step)));
25
44
  tickFactor = digNum - 2;
26
45
  return [tickFactor, Array.from(ticks).map(v => (v / Math.pow(10, tickFactor)).toFixed(0))];
27
46
  }
28
47
 
29
- if (Math.abs(max(ticks)) < 1) {
30
- // tick values between 0 and 1 (absolute) and step is below 1
31
- let decNum = Math.ceil(-Math.log10(step));
32
- if (decNum <= 2) {
33
- return [0, Array.from(ticks).map(v => v.toFixed(decNum))];
34
- }
35
- tickFactor = decNum - 2;
36
- decNum = 2;
48
+ let decNum = Math.ceil(-trimNum(Math.log10(step)));
49
+ if (decNum <= 2) {
50
+ return [0, Array.from(ticks).map(v => v.toFixed(decNum))];
51
+ }
52
+ tickFactor = decNum - 2;
53
+ decNum = 2;
54
+
55
+ if (trimNum(Math.abs(max(ticks))) <= 10) {
37
56
  return [-tickFactor, Array.from(ticks).map(v => (v * Math.pow(10, tickFactor)).toFixed(decNum))];
38
57
  } else {
39
- // tick values above 1 (absolute) and step is below 1
40
- let decNum = -Math.log10(step);
41
- decNum = Math.ceil(Math.round(decNum * 10)/100);
42
- if (decNum <= 2) {
43
- return [0, Array.from(ticks).map(v => v.toFixed(decNum))];
44
- }
45
- tickFactor = decNum - 2;
46
- decNum = 2;
47
- return [tickFactor, Array.from(ticks).map(v => (v / Math.pow(10, tickFactor)).toString())];
58
+ return [-tickFactor, Array.from(ticks).map(v => (v / Math.pow(10, tickFactor)).toString())];
48
59
  }
49
60
  }
50
61
 
@@ -177,7 +188,7 @@ export function getAxisTicks(ticks, lim, maxTickNum, round, whole) {
177
188
  if (typeof(lim) !== "object" || lim[0] === undefined || lim[1] === undefined) return undefined;
178
189
 
179
190
  // get range as a nice number and compute min, max and steps for the tick sequence
180
- const delta = (lim[1] - lim[0]) / 50;
191
+ const delta = (lim[1] - lim[0]) / 100;
181
192
  const localRange = lim[1] - lim[0] - delta;
182
193
  const exponent = Math.floor(Math.log10(localRange));
183
194
  const fraction = 1 / Math.pow(10, exponent - 1);
@@ -190,11 +201,15 @@ export function getAxisTicks(ticks, lim, maxTickNum, round, whole) {
190
201
  }
191
202
 
192
203
  // compute smallest and largest tick rounded to tickSpacing
193
- const tickMin = Math.ceil((lim[0] + delta) / tickSpacing) * tickSpacing;
194
- const tickMax = Math.floor((lim[1] - delta) / tickSpacing) * tickSpacing;
204
+ let tickMin = Math.ceil((lim[0] + delta ) / tickSpacing) * tickSpacing;
205
+ let tickMax = Math.floor((lim[1] - delta) / tickSpacing) * tickSpacing;
206
+
207
+ // adjust largest tick if it is too close to axis limit and tick spacing
208
+ // is small (so tick factor may appear)
209
+ if (tickSpacing < 0.1 && (lim[1] - tickMax) < (tickSpacing / 2)) tickMax = tickMax - tickSpacing;
195
210
 
196
211
  // recompute maxTickNum
197
- maxTickNum = Math.ceil((tickMax - tickMin) / tickSpacing) + 1;
212
+ maxTickNum = (Math.ceil(trimNum((tickMax - tickMin) / tickSpacing)) + 1);
198
213
 
199
214
  // create a sequence of ticks
200
215
  ticks = Vector.zeros(maxTickNum);