chartai 1.0.0 → 1.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.
- package/dist/chart-library.d.ts +1 -0
- package/dist/chart-library.d.ts.map +1 -1
- package/dist/chart-library.js +43 -11
- package/dist/chart-library.min.js +1 -1
- package/dist/charts/area.js +1 -1
- package/dist/charts/area.min.js +1 -1
- package/dist/charts/bar.js +1 -1
- package/dist/charts/bar.min.js +1 -1
- package/dist/charts/boids.js +9 -9
- package/dist/charts/boids.min.js +1 -1
- package/dist/charts/candlestick.js +5 -127
- package/dist/charts/candlestick.min.js +1 -32
- package/dist/charts/experimental/baseline-area.js +70 -0
- package/dist/charts/experimental/baseline-area.min.js +1 -0
- package/dist/charts/experimental/bubble.js +48 -0
- package/dist/charts/experimental/bubble.min.js +1 -0
- package/dist/charts/experimental/error-band.js +111 -0
- package/dist/charts/experimental/error-band.min.js +1 -0
- package/dist/charts/experimental/heatmap.js +69 -0
- package/dist/charts/experimental/heatmap.min.js +1 -0
- package/dist/charts/experimental/histogram.js +139 -0
- package/dist/charts/experimental/histogram.min.js +7 -0
- package/dist/charts/experimental/ohlc.js +132 -0
- package/dist/charts/experimental/ohlc.min.js +32 -0
- package/dist/charts/experimental/step.js +67 -0
- package/dist/charts/experimental/step.min.js +1 -0
- package/dist/charts/experimental/waterfall.js +121 -0
- package/dist/charts/experimental/waterfall.min.js +7 -0
- package/dist/charts/line.js +1 -1
- package/dist/charts/line.min.js +1 -1
- package/dist/charts/scatter.js +1 -1
- package/dist/charts/scatter.min.js +1 -1
- package/dist/{chunk-e7d3zgw5.min.js → chunk-0eh4rzy9.min.js} +1 -1
- package/dist/{chunk-a27be8p9.js → chunk-1ngxm8t2.js} +25 -1
- package/dist/chunk-50bcv2hw.min.js +2 -0
- package/dist/{chunk-dmaxrg6s.min.js → chunk-64q9a7nw.min.js} +1 -1
- package/dist/{chunk-me3qaz3m.min.js → chunk-bbyt23tw.min.js} +1 -1
- package/dist/chunk-cbydth3q.min.js +2 -0
- package/dist/chunk-cvtt04m6.min.js +2 -0
- package/dist/chunk-g2qmt43n.min.js +33 -0
- package/dist/{chunk-1p45ex5n.min.js → chunk-gm0d4cgx.min.js} +2 -2
- package/dist/chunk-mmsy3yqt.js +27 -0
- package/dist/{chunk-g6m56ptf.js → chunk-n8ew0z0e.js} +38 -10
- package/dist/chunk-t0kdz02m.js +129 -0
- package/dist/{chunk-bfyv7z27.min.js → chunk-wdfq2fpx.min.js} +1 -1
- package/dist/gpu-worker.js +8 -3
- package/dist/gpu-worker.min.js +1 -1
- package/dist/plugins/experimental/annotations.js +164 -0
- package/dist/plugins/experimental/annotations.min.js +1 -0
- package/dist/plugins/experimental/crosshair.js +82 -0
- package/dist/plugins/experimental/crosshair.min.js +1 -0
- package/dist/plugins/experimental/minimap.js +190 -0
- package/dist/plugins/experimental/minimap.min.js +1 -0
- package/dist/plugins/experimental/range-selector.js +220 -0
- package/dist/plugins/experimental/range-selector.min.js +1 -0
- package/dist/plugins/experimental/ruler.js +434 -0
- package/dist/plugins/experimental/ruler.min.js +59 -0
- package/dist/plugins/experimental/stats.js +229 -0
- package/dist/plugins/experimental/stats.min.js +8 -0
- package/dist/plugins/experimental/threshold.js +96 -0
- package/dist/plugins/experimental/threshold.min.js +1 -0
- package/dist/plugins/experimental/tooltip-pin.js +177 -0
- package/dist/plugins/experimental/tooltip-pin.min.js +1 -0
- package/dist/plugins/experimental/watermark.js +76 -0
- package/dist/plugins/experimental/watermark.min.js +1 -0
- package/dist/plugins/hover.d.ts.map +1 -1
- package/dist/plugins/hover.js +12 -30
- package/dist/plugins/hover.min.js +1 -1
- package/dist/plugins/labels-panel.js +3 -3
- package/dist/plugins/labels-panel.min.js +1 -1
- package/dist/plugins/labels.d.ts.map +1 -1
- package/dist/plugins/labels.js +3 -3
- package/dist/plugins/labels.min.js +1 -1
- package/dist/plugins/legend.d.ts.map +1 -1
- package/dist/plugins/legend.js +87 -16
- package/dist/plugins/legend.min.js +23 -7
- package/dist/plugins/zoom.js +2 -2
- package/dist/plugins/zoom.min.js +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker-inline.d.ts +1 -1
- package/dist/worker-inline.d.ts.map +1 -1
- package/package.json +1 -1
- package/readme.md +6 -3
- package/dist/chunk-94kc81rr.min.js +0 -2
- package/dist/chunk-qr6mweck.min.js +0 -2
- /package/dist/{chunk-m17t3vjq.js → chunk-5gtx3pza.js} +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COMPUTE_WG,
|
|
3
|
+
UNIFORM_STRUCT
|
|
4
|
+
} from "../../chunk-0jepamv9.js";
|
|
5
|
+
import"../../chunk-5gtx3pza.js";
|
|
6
|
+
|
|
7
|
+
// src/shaders/experimental/histogram.ts
|
|
8
|
+
var HIST_UNIFORMS_STRUCT = `struct HistUniforms {
|
|
9
|
+
binCount: u32,
|
|
10
|
+
minValue: f32,
|
|
11
|
+
maxValue: f32,
|
|
12
|
+
_p0: f32,
|
|
13
|
+
};
|
|
14
|
+
`;
|
|
15
|
+
var HIST_CLEAR_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read_write> histBuffer: array<u32>;@group(0)@binding(2)var<uniform> hu: HistUniforms;@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;if(idx < 4096u){histBuffer[idx] = 0u;}}`;
|
|
16
|
+
var HIST_COUNT_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read_write> histBuffer: array<atomic<u32>>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;if(range <= 0.0){return;}let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let binF =(x - minVal)/ range * f32(binCount);let bin = u32(clamp(binF,0.0,f32(binCount)- 1.0));if(bin < 4096u){atomicAdd(&histBuffer[bin],1u);}}`;
|
|
17
|
+
var HIST_FIND_MAX_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read_write> maxBuffer: array<u32>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(1)fn main(){let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let safeBins = min(binCount,4096u);var maxVal = 0u;for(var i = 0u;i < safeBins;i++){let v = histBuffer[i];if(v > maxVal){maxVal = v;}}maxBuffer[0] = maxVal;}`;
|
|
18
|
+
var HIST_RENDER_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read> maxBuffer: array<u32>;@group(0)@binding(3)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(4)var<uniform> si: SeriesIndex;@group(0)@binding(5)var<uniform> hu: HistUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = si.index;let colIdx = vi / 6u;let vertexType = vi % 6u;let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let maxCount = maxBuffer[0];if(colIdx >= binCount || colIdx >= 4096u || maxCount == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let count = histBuffer[colIdx];if(count == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeX = select(viewRangeX,1.0,viewRangeX < 0.0001);let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let binLeft = minVal + f32(colIdx)/ f32(binCount)* range;let binRight = minVal + f32(colIdx + 1u)/ f32(binCount)* range;let screenLeft =(binLeft - u.viewMinX)/ safeRangeX;let screenRight =(binRight - u.viewMinX)/ safeRangeX;let screenBottom = 1.0 -(0.0 - u.viewMinY)/ safeRangeY;let screenTop = 1.0 -(f32(count)- u.viewMinY)/ safeRangeY;var positions = array<vec2f,6>(vec2f(screenLeft,screenBottom),vec2f(screenRight,screenBottom),vec2f(screenLeft,screenTop),vec2f(screenLeft,screenTop),vec2f(screenRight,screenBottom),vec2f(screenRight,screenTop));let screenPos = positions[vertexType];out.pos = vec4f(screenPos.x * 2.0 - 1.0,1.0 - screenPos.y * 2.0,0.0,1.0);out.alpha = 1.0;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;
|
|
19
|
+
|
|
20
|
+
// src/charts/experimental/histogram.ts
|
|
21
|
+
var HistogramChart = {
|
|
22
|
+
name: "histogram",
|
|
23
|
+
shaders: {
|
|
24
|
+
clear: HIST_CLEAR_SHADER,
|
|
25
|
+
count: HIST_COUNT_SHADER,
|
|
26
|
+
findMax: HIST_FIND_MAX_SHADER,
|
|
27
|
+
render: HIST_RENDER_SHADER
|
|
28
|
+
},
|
|
29
|
+
uniforms: [
|
|
30
|
+
{ name: "binCount", type: "u32", default: 0 },
|
|
31
|
+
{ name: "minValue", type: "f32", default: 0 },
|
|
32
|
+
{ name: "maxValue", type: "f32", default: 0 }
|
|
33
|
+
],
|
|
34
|
+
buffers: [
|
|
35
|
+
{
|
|
36
|
+
name: "histBuffer",
|
|
37
|
+
bytes: () => 4096 * 4,
|
|
38
|
+
usages: ["STORAGE"]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "maxBuffer",
|
|
42
|
+
bytes: () => 4,
|
|
43
|
+
usages: ["STORAGE"]
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
passes: [
|
|
47
|
+
{
|
|
48
|
+
type: "compute",
|
|
49
|
+
shader: "clear",
|
|
50
|
+
perSeries: true,
|
|
51
|
+
dispatch: () => ({ x: Math.ceil(4096 / COMPUTE_WG) }),
|
|
52
|
+
bindings: [
|
|
53
|
+
{ binding: 0, source: "uniforms" },
|
|
54
|
+
{ binding: 1, source: "histBuffer", write: true },
|
|
55
|
+
{ binding: 2, source: "custom-uniforms" }
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: "compute",
|
|
60
|
+
shader: "count",
|
|
61
|
+
perSeries: true,
|
|
62
|
+
dispatch: ({ samples }) => ({ x: Math.ceil(Math.max(1, samples) / COMPUTE_WG) }),
|
|
63
|
+
bindings: [
|
|
64
|
+
{ binding: 0, source: "uniforms" },
|
|
65
|
+
{ binding: 1, source: "x-data" },
|
|
66
|
+
{ binding: 2, source: "histBuffer", write: true },
|
|
67
|
+
{ binding: 3, source: "custom-uniforms" }
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
type: "compute",
|
|
72
|
+
shader: "findMax",
|
|
73
|
+
perSeries: true,
|
|
74
|
+
dispatch: () => ({ x: 1 }),
|
|
75
|
+
bindings: [
|
|
76
|
+
{ binding: 0, source: "uniforms" },
|
|
77
|
+
{ binding: 1, source: "histBuffer" },
|
|
78
|
+
{ binding: 2, source: "maxBuffer", write: true },
|
|
79
|
+
{ binding: 3, source: "custom-uniforms" }
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: "render",
|
|
84
|
+
shader: "render",
|
|
85
|
+
topology: "triangle-list",
|
|
86
|
+
loadOp: "load",
|
|
87
|
+
blend: {
|
|
88
|
+
color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
|
|
89
|
+
alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
|
|
90
|
+
},
|
|
91
|
+
perSeries: true,
|
|
92
|
+
draw: () => 4096 * 6,
|
|
93
|
+
bindings: [
|
|
94
|
+
{ binding: 0, source: "uniforms" },
|
|
95
|
+
{ binding: 1, source: "histBuffer" },
|
|
96
|
+
{ binding: 2, source: "maxBuffer" },
|
|
97
|
+
{ binding: 3, source: "series-info" },
|
|
98
|
+
{ binding: 4, source: "series-index" },
|
|
99
|
+
{ binding: 5, source: "custom-uniforms" }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
computeBounds(series) {
|
|
104
|
+
let minX = Infinity;
|
|
105
|
+
let maxX = -Infinity;
|
|
106
|
+
for (const s of series) {
|
|
107
|
+
for (const x of s.rawX) {
|
|
108
|
+
if (x < minX)
|
|
109
|
+
minX = x;
|
|
110
|
+
if (x > maxX)
|
|
111
|
+
maxX = x;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!isFinite(minX)) {
|
|
115
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
116
|
+
}
|
|
117
|
+
const range = maxX - minX;
|
|
118
|
+
if (range <= 0) {
|
|
119
|
+
return { minX: minX - 0.5, maxX: minX + 0.5, minY: 0, maxY: 1 };
|
|
120
|
+
}
|
|
121
|
+
const approxBins = 512;
|
|
122
|
+
const counts = new Int32Array(approxBins);
|
|
123
|
+
for (const s of series) {
|
|
124
|
+
for (const x of s.rawX) {
|
|
125
|
+
const bin = Math.min(approxBins - 1, Math.max(0, Math.floor((x - minX) / range * approxBins)));
|
|
126
|
+
counts[bin]++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
let maxCount = 0;
|
|
130
|
+
for (let i = 0;i < approxBins; i++) {
|
|
131
|
+
if (counts[i] > maxCount)
|
|
132
|
+
maxCount = counts[i];
|
|
133
|
+
}
|
|
134
|
+
return { minX, maxX, minY: 0, maxY: Math.max(1, Math.ceil(maxCount * 1.1)) };
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
export {
|
|
138
|
+
HistogramChart
|
|
139
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{f as t,g as u}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var f=`struct HistUniforms {
|
|
2
|
+
binCount: u32,
|
|
3
|
+
minValue: f32,
|
|
4
|
+
maxValue: f32,
|
|
5
|
+
_p0: f32,
|
|
6
|
+
};
|
|
7
|
+
`,c=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read_write> histBuffer: array<u32>;@group(0)@binding(2)var<uniform> hu: HistUniforms;@compute @workgroup_size(${t})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;if(idx < 4096u){histBuffer[idx] = 0u;}}`,v=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read_write> histBuffer: array<atomic<u32>>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(${t})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;if(range <= 0.0){return;}let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let binF =(x - minVal)/ range * f32(binCount);let bin = u32(clamp(binF,0.0,f32(binCount)- 1.0));if(bin < 4096u){atomicAdd(&histBuffer[bin],1u);}}`,d=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read_write> maxBuffer: array<u32>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(1)fn main(){let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let safeBins = min(binCount,4096u);var maxVal = 0u;for(var i = 0u;i < safeBins;i++){let v = histBuffer[i];if(v > maxVal){maxVal = v;}}maxBuffer[0] = maxVal;}`,m=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read> maxBuffer: array<u32>;@group(0)@binding(3)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(4)var<uniform> si: SeriesIndex;@group(0)@binding(5)var<uniform> hu: HistUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = si.index;let colIdx = vi / 6u;let vertexType = vi % 6u;let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let maxCount = maxBuffer[0];if(colIdx >= binCount || colIdx >= 4096u || maxCount == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let count = histBuffer[colIdx];if(count == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeX = select(viewRangeX,1.0,viewRangeX < 0.0001);let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let binLeft = minVal + f32(colIdx)/ f32(binCount)* range;let binRight = minVal + f32(colIdx + 1u)/ f32(binCount)* range;let screenLeft =(binLeft - u.viewMinX)/ safeRangeX;let screenRight =(binRight - u.viewMinX)/ safeRangeX;let screenBottom = 1.0 -(0.0 - u.viewMinY)/ safeRangeY;let screenTop = 1.0 -(f32(count)- u.viewMinY)/ safeRangeY;var positions = array<vec2f,6>(vec2f(screenLeft,screenBottom),vec2f(screenRight,screenBottom),vec2f(screenLeft,screenTop),vec2f(screenLeft,screenTop),vec2f(screenRight,screenBottom),vec2f(screenRight,screenTop));let screenPos = positions[vertexType];out.pos = vec4f(screenPos.x * 2.0 - 1.0,1.0 - screenPos.y * 2.0,0.0,1.0);out.alpha = 1.0;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var R={name:"histogram",shaders:{clear:c,count:v,findMax:d,render:m},uniforms:[{name:"binCount",type:"u32",default:0},{name:"minValue",type:"f32",default:0},{name:"maxValue",type:"f32",default:0}],buffers:[{name:"histBuffer",bytes:()=>16384,usages:["STORAGE"]},{name:"maxBuffer",bytes:()=>4,usages:["STORAGE"]}],passes:[{type:"compute",shader:"clear",perSeries:!0,dispatch:()=>({x:Math.ceil(4096/t)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"histBuffer",write:!0},{binding:2,source:"custom-uniforms"}]},{type:"compute",shader:"count",perSeries:!0,dispatch:({samples:r})=>({x:Math.ceil(Math.max(1,r)/t)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"histBuffer",write:!0},{binding:3,source:"custom-uniforms"}]},{type:"compute",shader:"findMax",perSeries:!0,dispatch:()=>({x:1}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"histBuffer"},{binding:2,source:"maxBuffer",write:!0},{binding:3,source:"custom-uniforms"}]},{type:"render",shader:"render",topology:"triangle-list",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},perSeries:!0,draw:()=>24576,bindings:[{binding:0,source:"uniforms"},{binding:1,source:"histBuffer"},{binding:2,source:"maxBuffer"},{binding:3,source:"series-info"},{binding:4,source:"series-index"},{binding:5,source:"custom-uniforms"}]}],computeBounds(r){let e=1/0,a=-1/0;for(let i of r)for(let n of i.rawX){if(n<e)e=n;if(n>a)a=n}if(!isFinite(e))return{minX:0,maxX:1,minY:0,maxY:1};let g=a-e;if(g<=0)return{minX:e-0.5,maxX:e+0.5,minY:0,maxY:1};let o=512,l=new Int32Array(o);for(let i of r)for(let n of i.rawX){let b=Math.min(o-1,Math.max(0,Math.floor((n-e)/g*o)));l[b]++}let s=0;for(let i=0;i<o;i++)if(l[i]>s)s=l[i];return{minX:e,maxX:a,minY:0,maxY:Math.max(1,Math.ceil(s*1.1))}}};export{R as HistogramChart};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CANDLESTICK_COMPUTE_SHADER,
|
|
3
|
+
packRGB
|
|
4
|
+
} from "../../chunk-t0kdz02m.js";
|
|
5
|
+
import {
|
|
6
|
+
COMPUTE_WG,
|
|
7
|
+
UNIFORM_STRUCT
|
|
8
|
+
} from "../../chunk-0jepamv9.js";
|
|
9
|
+
import"../../chunk-5gtx3pza.js";
|
|
10
|
+
|
|
11
|
+
// src/shaders/experimental/ohlc.ts
|
|
12
|
+
var CANDLE_TYPES = `
|
|
13
|
+
struct CandleUniforms {
|
|
14
|
+
maxSamples: f32,
|
|
15
|
+
upColor: u32,
|
|
16
|
+
downColor: u32,
|
|
17
|
+
binSize: u32,
|
|
18
|
+
interval: f32,
|
|
19
|
+
_p0: u32, _p1: u32, _p2: u32,
|
|
20
|
+
};
|
|
21
|
+
struct CandleData {
|
|
22
|
+
screenX: f32,
|
|
23
|
+
barWidth: f32,
|
|
24
|
+
low: f32,
|
|
25
|
+
bodyBottom: f32,
|
|
26
|
+
bodyTop: f32,
|
|
27
|
+
high: f32,
|
|
28
|
+
isUp: f32,
|
|
29
|
+
};`;
|
|
30
|
+
var EFFECTIVE_INTERVAL = `
|
|
31
|
+
fn effectiveInterval() -> f32 {
|
|
32
|
+
if (cu.interval > 0.0) { return cu.interval; }
|
|
33
|
+
let raw = (u.viewMaxX - u.viewMinX) / u.width * f32(cu.binSize);
|
|
34
|
+
let steps = array<f32, 20>(
|
|
35
|
+
1.0, 2.0, 5.0, 10.0, 15.0, 30.0,
|
|
36
|
+
60.0, 120.0, 300.0, 600.0, 900.0, 1800.0,
|
|
37
|
+
3600.0, 7200.0, 14400.0, 43200.0,
|
|
38
|
+
86400.0, 259200.0, 604800.0, 2592000.0
|
|
39
|
+
);
|
|
40
|
+
for (var i = 0u; i < 20u; i++) {
|
|
41
|
+
if (steps[i] >= raw) { return steps[i]; }
|
|
42
|
+
}
|
|
43
|
+
return raw;
|
|
44
|
+
}`;
|
|
45
|
+
var OHLC_RENDER_SHADER = `${UNIFORM_STRUCT}${CANDLE_TYPES}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> candleData: array<CandleData>;@group(0)@binding(2)var<uniform> cu: CandleUniforms;${EFFECTIVE_INTERVAL}struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)isUp: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;let viewRangeX = u.viewMaxX - u.viewMinX;let interval = effectiveInterval();let numBins = min(u32(ceil(viewRangeX / interval))+ 2u,u32(u.width));let colIdx = vi / 18u;let localVi = vi % 18u;let section = localVi / 6u;let vertexType = localVi % 6u;if(colIdx >= numBins){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;return out;}let cd = candleData[colIdx];if(cd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;return out;}out.isUp = cd.isUp;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let onePixelX = 1.0 / u.width;let onePixelY = 1.0 / u.height;let wickWidth = max(onePixelX,cd.barWidth * 0.07);let tickHalfH = max(onePixelY,wickWidth * u.width / u.height);let openPrice = select(cd.bodyTop,cd.bodyBottom,cd.isUp > 0.5);let closePrice = select(cd.bodyBottom,cd.bodyTop,cd.isUp > 0.5);var sLeft: f32;var sRight: f32;var sTop: f32;var sBottom: f32;if(section == 0u){let nb =(cd.low - u.viewMinY)/ safeRangeY;let nt =(cd.high - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;sLeft = cd.screenX - wickWidth;sRight = cd.screenX + wickWidth;}else if(section == 1u){let ny =(openPrice - u.viewMinY)/ safeRangeY;let sy = 1.0 - ny;sTop = sy - tickHalfH;sBottom = sy + tickHalfH;sLeft = cd.screenX - cd.barWidth * 0.45;sRight = cd.screenX;}else{let ny =(closePrice - u.viewMinY)/ safeRangeY;let sy = 1.0 - ny;sTop = sy - tickHalfH;sBottom = sy + tickHalfH;sLeft = cd.screenX;sRight = cd.screenX + cd.barWidth * 0.45;}var positions = array<vec2f,6>(vec2f(sLeft,sBottom),vec2f(sRight,sBottom),vec2f(sLeft,sTop),vec2f(sLeft,sTop),vec2f(sRight,sBottom),vec2f(sRight,sTop));let sp = positions[vertexType];out.pos = vec4f(sp.x * 2.0 - 1.0,1.0 - sp.y * 2.0,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let upRgb = unpack4x8unorm(cu.upColor).rgb;let downRgb = unpack4x8unorm(cu.downColor).rgb;let color = select(downRgb,upRgb,in.isUp > 0.5);return vec4f(color,0.92);}`;
|
|
46
|
+
|
|
47
|
+
// src/charts/experimental/ohlc.ts
|
|
48
|
+
var BYTES_PER_CANDLE = 7 * 4;
|
|
49
|
+
var OhlcChart = {
|
|
50
|
+
name: "ohlc",
|
|
51
|
+
shaders: {
|
|
52
|
+
compute: CANDLESTICK_COMPUTE_SHADER,
|
|
53
|
+
render: OHLC_RENDER_SHADER
|
|
54
|
+
},
|
|
55
|
+
uniforms: [
|
|
56
|
+
{ name: "maxSamples", type: "f32", default: 1e4 },
|
|
57
|
+
{ name: "upColor", type: "u32", default: packRGB(0.2, 0.7, 0.3) },
|
|
58
|
+
{ name: "downColor", type: "u32", default: packRGB(0.9, 0.3, 0.3) },
|
|
59
|
+
{ name: "binSize", type: "u32", default: 8 },
|
|
60
|
+
{ name: "interval", type: "f32", default: 0 }
|
|
61
|
+
],
|
|
62
|
+
buffers: [
|
|
63
|
+
{
|
|
64
|
+
name: "candleBuffer",
|
|
65
|
+
bytes: ({ width }) => Math.max(16, width * BYTES_PER_CANDLE),
|
|
66
|
+
usages: ["STORAGE"]
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
passes: [
|
|
70
|
+
{
|
|
71
|
+
type: "compute",
|
|
72
|
+
shader: "compute",
|
|
73
|
+
perSeries: true,
|
|
74
|
+
dispatch: ({ width }) => ({ x: Math.ceil(Math.max(1, width) / COMPUTE_WG) }),
|
|
75
|
+
bindings: [
|
|
76
|
+
{ binding: 0, source: "uniforms" },
|
|
77
|
+
{ binding: 1, source: "x-data" },
|
|
78
|
+
{ binding: 2, source: "y-data" },
|
|
79
|
+
{ binding: 3, source: "candleBuffer", write: true },
|
|
80
|
+
{ binding: 4, source: "series-info" },
|
|
81
|
+
{ binding: 5, source: "series-index" },
|
|
82
|
+
{ binding: 6, source: "custom-uniforms" },
|
|
83
|
+
{ binding: 7, source: "open-data" },
|
|
84
|
+
{ binding: 8, source: "high-data" },
|
|
85
|
+
{ binding: 9, source: "low-data" }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: "render",
|
|
90
|
+
shader: "render",
|
|
91
|
+
topology: "triangle-list",
|
|
92
|
+
loadOp: "load",
|
|
93
|
+
blend: {
|
|
94
|
+
color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
|
|
95
|
+
alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
|
|
96
|
+
},
|
|
97
|
+
draw: ({ width }) => width * 18,
|
|
98
|
+
bindings: [
|
|
99
|
+
{ binding: 0, source: "uniforms" },
|
|
100
|
+
{ binding: 1, source: "candleBuffer" },
|
|
101
|
+
{ binding: 2, source: "custom-uniforms" }
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
computeBounds(series) {
|
|
106
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
107
|
+
for (const s of series) {
|
|
108
|
+
for (const x of s.rawX) {
|
|
109
|
+
if (x < minX)
|
|
110
|
+
minX = x;
|
|
111
|
+
if (x > maxX)
|
|
112
|
+
maxX = x;
|
|
113
|
+
}
|
|
114
|
+
for (const y of s.extra.high ?? []) {
|
|
115
|
+
if (y > maxY)
|
|
116
|
+
maxY = y;
|
|
117
|
+
}
|
|
118
|
+
for (const y of s.extra.low ?? []) {
|
|
119
|
+
if (y < minY)
|
|
120
|
+
minY = y;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!isFinite(minX))
|
|
124
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
125
|
+
const px = (maxX - minX) * 0.05 || 1;
|
|
126
|
+
const py = (maxY - minY) * 0.1 || 1;
|
|
127
|
+
return { minX: minX - px, maxX: maxX + px, minY: minY - py, maxY: maxY + py };
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
export {
|
|
131
|
+
OhlcChart
|
|
132
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import{a as Q,b as Z}from"../../chunk-g2qmt43n.js";import{f as g,g as z}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var V=`
|
|
2
|
+
struct CandleUniforms {
|
|
3
|
+
maxSamples: f32,
|
|
4
|
+
upColor: u32,
|
|
5
|
+
downColor: u32,
|
|
6
|
+
binSize: u32,
|
|
7
|
+
interval: f32,
|
|
8
|
+
_p0: u32, _p1: u32, _p2: u32,
|
|
9
|
+
};
|
|
10
|
+
struct CandleData {
|
|
11
|
+
screenX: f32,
|
|
12
|
+
barWidth: f32,
|
|
13
|
+
low: f32,
|
|
14
|
+
bodyBottom: f32,
|
|
15
|
+
bodyTop: f32,
|
|
16
|
+
high: f32,
|
|
17
|
+
isUp: f32,
|
|
18
|
+
};`,B=`
|
|
19
|
+
fn effectiveInterval() -> f32 {
|
|
20
|
+
if (cu.interval > 0.0) { return cu.interval; }
|
|
21
|
+
let raw = (u.viewMaxX - u.viewMinX) / u.width * f32(cu.binSize);
|
|
22
|
+
let steps = array<f32, 20>(
|
|
23
|
+
1.0, 2.0, 5.0, 10.0, 15.0, 30.0,
|
|
24
|
+
60.0, 120.0, 300.0, 600.0, 900.0, 1800.0,
|
|
25
|
+
3600.0, 7200.0, 14400.0, 43200.0,
|
|
26
|
+
86400.0, 259200.0, 604800.0, 2592000.0
|
|
27
|
+
);
|
|
28
|
+
for (var i = 0u; i < 20u; i++) {
|
|
29
|
+
if (steps[i] >= raw) { return steps[i]; }
|
|
30
|
+
}
|
|
31
|
+
return raw;
|
|
32
|
+
}`,W=`${z}${V}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> candleData: array<CandleData>;@group(0)@binding(2)var<uniform> cu: CandleUniforms;${B}struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)isUp: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;let viewRangeX = u.viewMaxX - u.viewMinX;let interval = effectiveInterval();let numBins = min(u32(ceil(viewRangeX / interval))+ 2u,u32(u.width));let colIdx = vi / 18u;let localVi = vi % 18u;let section = localVi / 6u;let vertexType = localVi % 6u;if(colIdx >= numBins){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;return out;}let cd = candleData[colIdx];if(cd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;return out;}out.isUp = cd.isUp;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let onePixelX = 1.0 / u.width;let onePixelY = 1.0 / u.height;let wickWidth = max(onePixelX,cd.barWidth * 0.07);let tickHalfH = max(onePixelY,wickWidth * u.width / u.height);let openPrice = select(cd.bodyTop,cd.bodyBottom,cd.isUp > 0.5);let closePrice = select(cd.bodyBottom,cd.bodyTop,cd.isUp > 0.5);var sLeft: f32;var sRight: f32;var sTop: f32;var sBottom: f32;if(section == 0u){let nb =(cd.low - u.viewMinY)/ safeRangeY;let nt =(cd.high - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;sLeft = cd.screenX - wickWidth;sRight = cd.screenX + wickWidth;}else if(section == 1u){let ny =(openPrice - u.viewMinY)/ safeRangeY;let sy = 1.0 - ny;sTop = sy - tickHalfH;sBottom = sy + tickHalfH;sLeft = cd.screenX - cd.barWidth * 0.45;sRight = cd.screenX;}else{let ny =(closePrice - u.viewMinY)/ safeRangeY;let sy = 1.0 - ny;sTop = sy - tickHalfH;sBottom = sy + tickHalfH;sLeft = cd.screenX;sRight = cd.screenX + cd.barWidth * 0.45;}var positions = array<vec2f,6>(vec2f(sLeft,sBottom),vec2f(sRight,sBottom),vec2f(sLeft,sTop),vec2f(sLeft,sTop),vec2f(sRight,sBottom),vec2f(sRight,sTop));let sp = positions[vertexType];out.pos = vec4f(sp.x * 2.0 - 1.0,1.0 - sp.y * 2.0,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let upRgb = unpack4x8unorm(cu.upColor).rgb;let downRgb = unpack4x8unorm(cu.downColor).rgb;let color = select(downRgb,upRgb,in.isUp > 0.5);return vec4f(color,0.92);}`;var F=28,k={name:"ohlc",shaders:{compute:Q,render:W},uniforms:[{name:"maxSamples",type:"f32",default:1e4},{name:"upColor",type:"u32",default:Z(0.2,0.7,0.3)},{name:"downColor",type:"u32",default:Z(0.9,0.3,0.3)},{name:"binSize",type:"u32",default:8},{name:"interval",type:"f32",default:0}],buffers:[{name:"candleBuffer",bytes:({width:j})=>Math.max(16,j*F),usages:["STORAGE"]}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({width:j})=>({x:Math.ceil(Math.max(1,j)/g)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"candleBuffer",write:!0},{binding:4,source:"series-info"},{binding:5,source:"series-index"},{binding:6,source:"custom-uniforms"},{binding:7,source:"open-data"},{binding:8,source:"high-data"},{binding:9,source:"low-data"}]},{type:"render",shader:"render",topology:"triangle-list",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({width:j})=>j*18,bindings:[{binding:0,source:"uniforms"},{binding:1,source:"candleBuffer"},{binding:2,source:"custom-uniforms"}]}],computeBounds(j){let q=1/0,u=-1/0,v=1/0,J=-1/0;for(let K of j){for(let b of K.rawX){if(b<q)q=b;if(b>u)u=b}for(let b of K.extra.high??[])if(b>J)J=b;for(let b of K.extra.low??[])if(b<v)v=b}if(!isFinite(q))return{minX:0,maxX:1,minY:0,maxY:1};let $=(u-q)*0.05||1,f=(J-v)*0.1||1;return{minX:q-$,maxX:u+$,minY:v-f,maxY:J+f}}};export{k as OhlcChart};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LINE_COMPUTE_SHADER
|
|
3
|
+
} from "../../chunk-yabjrff2.js";
|
|
4
|
+
import {
|
|
5
|
+
COMPUTE_WG,
|
|
6
|
+
UNIFORM_STRUCT
|
|
7
|
+
} from "../../chunk-0jepamv9.js";
|
|
8
|
+
import"../../chunk-5gtx3pza.js";
|
|
9
|
+
|
|
10
|
+
// src/shaders/experimental/step.ts
|
|
11
|
+
var STEP_RENDER_SHADER = `${UNIFORM_STRUCT}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};struct StepUniforms{maxSamplesPerPixel: u32,stepMode: u32,_p2: u32,_p3: u32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(3)var<uniform> su: StepUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let spanVerts = maxCols * 2u;if(vi < spanVerts){let segIdx = vi / 2u;let endpoint = vi % 2u;let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connOffset = vi - spanVerts;let connIdx = connOffset / 4u;let localVert = connOffset % 4u;let segInConn = localVert / 2u;let endpoint = localVert % 2u;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);let midY0 =(d0.minScreenY + d0.maxScreenY)* 0.5;let midY1 =(d1.minScreenY + d1.maxScreenY)* 0.5;let midX =(d0.screenX + d1.screenX)* 0.5;var px: f32;var py: f32;if(su.stepMode == 0u){if(segInConn == 0u){px = select(d0.screenX,d1.screenX,endpoint == 1u);py = midY0;}else{px = d1.screenX;py = select(midY0,midY1,endpoint == 1u);}}else if(su.stepMode == 1u){if(segInConn == 0u){px = d0.screenX;py = select(midY0,midY1,endpoint == 1u);}else{px = select(d0.screenX,d1.screenX,endpoint == 1u);py = midY1;}}else{if(segInConn == 0u){px = select(d0.screenX,midX,endpoint == 1u);py = midY0;}else{px = midX;py = select(midY0,midY1,endpoint == 1u);}}out.pos = vec4f(px * 2.0 - 1.0,1.0 - py * 2.0,0.0,segValid);out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;
|
|
12
|
+
|
|
13
|
+
// src/charts/experimental/step.ts
|
|
14
|
+
var StepChart = {
|
|
15
|
+
name: "step",
|
|
16
|
+
shaders: {
|
|
17
|
+
compute: LINE_COMPUTE_SHADER,
|
|
18
|
+
render: STEP_RENDER_SHADER
|
|
19
|
+
},
|
|
20
|
+
uniforms: [
|
|
21
|
+
{ name: "maxSamplesPerPixel", type: "u32", default: 1e4 },
|
|
22
|
+
{ name: "stepMode", type: "u32", default: 0 }
|
|
23
|
+
],
|
|
24
|
+
buffers: [
|
|
25
|
+
{
|
|
26
|
+
name: "lineBuffer",
|
|
27
|
+
bytes: ({ width }) => Math.max(16, width * 4 * 4),
|
|
28
|
+
usages: ["STORAGE"]
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
passes: [
|
|
32
|
+
{
|
|
33
|
+
type: "compute",
|
|
34
|
+
shader: "compute",
|
|
35
|
+
perSeries: true,
|
|
36
|
+
dispatch: ({ width }) => ({ x: Math.ceil(Math.max(1, width) / COMPUTE_WG) }),
|
|
37
|
+
bindings: [
|
|
38
|
+
{ binding: 0, source: "uniforms" },
|
|
39
|
+
{ binding: 1, source: "x-data" },
|
|
40
|
+
{ binding: 2, source: "y-data" },
|
|
41
|
+
{ binding: 3, source: "lineBuffer", write: true },
|
|
42
|
+
{ binding: 4, source: "series-info" },
|
|
43
|
+
{ binding: 5, source: "custom-uniforms" }
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: "render",
|
|
48
|
+
shader: "render",
|
|
49
|
+
topology: "line-list",
|
|
50
|
+
loadOp: "load",
|
|
51
|
+
blend: {
|
|
52
|
+
color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
|
|
53
|
+
alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
|
|
54
|
+
},
|
|
55
|
+
draw: ({ width }) => Math.max(0, width * 2 + (width - 1) * 4),
|
|
56
|
+
bindings: [
|
|
57
|
+
{ binding: 0, source: "uniforms" },
|
|
58
|
+
{ binding: 1, source: "lineBuffer" },
|
|
59
|
+
{ binding: 2, source: "series-info" },
|
|
60
|
+
{ binding: 3, source: "custom-uniforms" }
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
export {
|
|
66
|
+
StepChart
|
|
67
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as n}from"../../chunk-gm0d4cgx.js";import{f as r,g as t}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var i=`${t}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};struct StepUniforms{maxSamplesPerPixel: u32,stepMode: u32,_p2: u32,_p3: u32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(3)var<uniform> su: StepUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let spanVerts = maxCols * 2u;if(vi < spanVerts){let segIdx = vi / 2u;let endpoint = vi % 2u;let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connOffset = vi - spanVerts;let connIdx = connOffset / 4u;let localVert = connOffset % 4u;let segInConn = localVert / 2u;let endpoint = localVert % 2u;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);let midY0 =(d0.minScreenY + d0.maxScreenY)* 0.5;let midY1 =(d1.minScreenY + d1.maxScreenY)* 0.5;let midX =(d0.screenX + d1.screenX)* 0.5;var px: f32;var py: f32;if(su.stepMode == 0u){if(segInConn == 0u){px = select(d0.screenX,d1.screenX,endpoint == 1u);py = midY0;}else{px = d1.screenX;py = select(midY0,midY1,endpoint == 1u);}}else if(su.stepMode == 1u){if(segInConn == 0u){px = d0.screenX;py = select(midY0,midY1,endpoint == 1u);}else{px = select(d0.screenX,d1.screenX,endpoint == 1u);py = midY1;}}else{if(segInConn == 0u){px = select(d0.screenX,midX,endpoint == 1u);py = midY0;}else{px = midX;py = select(midY0,midY1,endpoint == 1u);}}out.pos = vec4f(px * 2.0 - 1.0,1.0 - py * 2.0,0.0,segValid);out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var u={name:"step",shaders:{compute:n,render:i},uniforms:[{name:"maxSamplesPerPixel",type:"u32",default:1e4},{name:"stepMode",type:"u32",default:0}],buffers:[{name:"lineBuffer",bytes:({width:e})=>Math.max(16,e*4*4),usages:["STORAGE"]}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({width:e})=>({x:Math.ceil(Math.max(1,e)/r)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"lineBuffer",write:!0},{binding:4,source:"series-info"},{binding:5,source:"custom-uniforms"}]},{type:"render",shader:"render",topology:"line-list",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({width:e})=>Math.max(0,e*2+(e-1)*4),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"lineBuffer"},{binding:2,source:"series-info"},{binding:3,source:"custom-uniforms"}]}]};export{u as StepChart};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
packRGB
|
|
3
|
+
} from "../../chunk-t0kdz02m.js";
|
|
4
|
+
import {
|
|
5
|
+
UNIFORM_STRUCT
|
|
6
|
+
} from "../../chunk-0jepamv9.js";
|
|
7
|
+
import"../../chunk-5gtx3pza.js";
|
|
8
|
+
|
|
9
|
+
// src/shaders/experimental/waterfall.ts
|
|
10
|
+
var WATERFALL_TYPES = `
|
|
11
|
+
struct WaterfallUniforms {
|
|
12
|
+
upColor: u32,
|
|
13
|
+
downColor: u32,
|
|
14
|
+
totalColor: u32,
|
|
15
|
+
_pad: u32,
|
|
16
|
+
};`;
|
|
17
|
+
var WATERFALL_RENDER_SHADER = `${UNIFORM_STRUCT}${WATERFALL_TYPES}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<uniform> wu: WaterfallUniforms;@group(0)@binding(4)var<storage,read> dataH: array<f32>;@group(0)@binding(5)var<storage,read> dataT: array<f32>;@group(0)@binding(6)var<storage,read> dataBW: array<f32>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)colorType: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;let barIdx = vi / 6u;let vertexType = vi % 6u;let count = u.pointCount;if(barIdx >= count){out.pos = vec4f(0.0,0.0,0.0,1.0);out.colorType = 0.0;return out;}let x = dataX[barIdx];let barBottom = dataY[barIdx];let barHeight = max(dataH[barIdx],0.0);let barTop = barBottom + barHeight;let barWidth = dataBW[barIdx];let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeX = select(viewRangeX,1.0,viewRangeX < 0.0001);let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let screenX =(x - u.viewMinX)/ safeRangeX;let halfW =(barWidth * 0.5)/ safeRangeX;let left = screenX - halfW;let right = screenX + halfW;let normBottom =(barBottom - u.viewMinY)/ safeRangeY;let normTop =(barTop - u.viewMinY)/ safeRangeY;let sBottom = max(1.0 - normBottom,1.0 - normTop);let sTop = min(1.0 - normBottom,1.0 - normTop);var positions = array<vec2f,6>(vec2f(left,sBottom),vec2f(right,sBottom),vec2f(left,sTop),vec2f(left,sTop),vec2f(right,sBottom),vec2f(right,sTop));let sp = positions[vertexType];out.pos = vec4f(sp.x * 2.0 - 1.0,1.0 - sp.y * 2.0,0.0,1.0);out.colorType = dataT[barIdx];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let upRgb = unpack4x8unorm(wu.upColor).rgb;let downRgb = unpack4x8unorm(wu.downColor).rgb;let totalRgb = unpack4x8unorm(wu.totalColor).rgb;var color: vec3f;if(in.colorType < 0.5){color = upRgb;}else if(in.colorType < 1.5){color = downRgb;}else{color = totalRgb;}return vec4f(color,0.9);}`;
|
|
18
|
+
|
|
19
|
+
// src/charts/experimental/waterfall.ts
|
|
20
|
+
function prepareWaterfall(positions, deltas, totals) {
|
|
21
|
+
const n = deltas.length;
|
|
22
|
+
const y = new Array(n);
|
|
23
|
+
const h = new Array(n);
|
|
24
|
+
const t = new Array(n);
|
|
25
|
+
const bw = new Array(n);
|
|
26
|
+
let running = 0;
|
|
27
|
+
for (let i = 0;i < n; i++) {
|
|
28
|
+
const isTotal = (totals?.[i] ?? 0) > 0.5;
|
|
29
|
+
const delta = deltas[i];
|
|
30
|
+
if (isTotal) {
|
|
31
|
+
y[i] = Math.min(0, running);
|
|
32
|
+
h[i] = Math.abs(running);
|
|
33
|
+
t[i] = 2;
|
|
34
|
+
} else {
|
|
35
|
+
if (delta >= 0) {
|
|
36
|
+
y[i] = running;
|
|
37
|
+
h[i] = delta;
|
|
38
|
+
t[i] = 0;
|
|
39
|
+
} else {
|
|
40
|
+
y[i] = running + delta;
|
|
41
|
+
h[i] = Math.abs(delta);
|
|
42
|
+
t[i] = 1;
|
|
43
|
+
}
|
|
44
|
+
running += delta;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (let i = 0;i < n; i++) {
|
|
48
|
+
let spacing;
|
|
49
|
+
if (n <= 1) {
|
|
50
|
+
spacing = 1;
|
|
51
|
+
} else if (i === 0) {
|
|
52
|
+
spacing = positions[1] - positions[0];
|
|
53
|
+
} else if (i === n - 1) {
|
|
54
|
+
spacing = positions[n - 1] - positions[n - 2];
|
|
55
|
+
} else {
|
|
56
|
+
spacing = Math.min(positions[i + 1] - positions[i], positions[i] - positions[i - 1]);
|
|
57
|
+
}
|
|
58
|
+
bw[i] = spacing * 0.8;
|
|
59
|
+
}
|
|
60
|
+
return { x: positions, y, h, t, bw };
|
|
61
|
+
}
|
|
62
|
+
var WaterfallChart = {
|
|
63
|
+
name: "waterfall",
|
|
64
|
+
shaders: { render: WATERFALL_RENDER_SHADER },
|
|
65
|
+
uniforms: [
|
|
66
|
+
{ name: "upColor", type: "u32", default: packRGB(0.2, 0.7, 0.3) },
|
|
67
|
+
{ name: "downColor", type: "u32", default: packRGB(0.9, 0.3, 0.3) },
|
|
68
|
+
{ name: "totalColor", type: "u32", default: packRGB(0.5, 0.5, 0.6) }
|
|
69
|
+
],
|
|
70
|
+
passes: [
|
|
71
|
+
{
|
|
72
|
+
type: "render",
|
|
73
|
+
shader: "render",
|
|
74
|
+
topology: "triangle-list",
|
|
75
|
+
loadOp: "load",
|
|
76
|
+
perSeries: true,
|
|
77
|
+
blend: {
|
|
78
|
+
color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
|
|
79
|
+
alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
|
|
80
|
+
},
|
|
81
|
+
draw: ({ samples }) => Math.max(0, samples * 6),
|
|
82
|
+
bindings: [
|
|
83
|
+
{ binding: 0, source: "uniforms" },
|
|
84
|
+
{ binding: 1, source: "x-data" },
|
|
85
|
+
{ binding: 2, source: "y-data" },
|
|
86
|
+
{ binding: 3, source: "custom-uniforms" },
|
|
87
|
+
{ binding: 4, source: "h-data" },
|
|
88
|
+
{ binding: 5, source: "t-data" },
|
|
89
|
+
{ binding: 6, source: "bw-data" }
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
computeBounds(series) {
|
|
94
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
95
|
+
for (const s of series) {
|
|
96
|
+
for (let i = 0;i < s.rawX.length; i++) {
|
|
97
|
+
const x = s.rawX[i];
|
|
98
|
+
const barBottom = s.rawY[i];
|
|
99
|
+
const barHeight = s.extra["h"]?.[i] ?? 0;
|
|
100
|
+
const barTop = barBottom + barHeight;
|
|
101
|
+
if (x < minX)
|
|
102
|
+
minX = x;
|
|
103
|
+
if (x > maxX)
|
|
104
|
+
maxX = x;
|
|
105
|
+
if (barBottom < minY)
|
|
106
|
+
minY = barBottom;
|
|
107
|
+
if (barTop > maxY)
|
|
108
|
+
maxY = barTop;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!isFinite(minX))
|
|
112
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
113
|
+
const px = (maxX - minX) * 0.05 || 1;
|
|
114
|
+
const py = (maxY - minY) * 0.1 || 0.1;
|
|
115
|
+
return { minX: minX - px, maxX: maxX + px, minY: minY - py, maxY: maxY + py };
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
export {
|
|
119
|
+
prepareWaterfall,
|
|
120
|
+
WaterfallChart
|
|
121
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{b as M}from"../../chunk-g2qmt43n.js";import{g as P}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var D=`
|
|
2
|
+
struct WaterfallUniforms {
|
|
3
|
+
upColor: u32,
|
|
4
|
+
downColor: u32,
|
|
5
|
+
totalColor: u32,
|
|
6
|
+
_pad: u32,
|
|
7
|
+
};`,f=`${P}${D}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<uniform> wu: WaterfallUniforms;@group(0)@binding(4)var<storage,read> dataH: array<f32>;@group(0)@binding(5)var<storage,read> dataT: array<f32>;@group(0)@binding(6)var<storage,read> dataBW: array<f32>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)colorType: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;let barIdx = vi / 6u;let vertexType = vi % 6u;let count = u.pointCount;if(barIdx >= count){out.pos = vec4f(0.0,0.0,0.0,1.0);out.colorType = 0.0;return out;}let x = dataX[barIdx];let barBottom = dataY[barIdx];let barHeight = max(dataH[barIdx],0.0);let barTop = barBottom + barHeight;let barWidth = dataBW[barIdx];let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeX = select(viewRangeX,1.0,viewRangeX < 0.0001);let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let screenX =(x - u.viewMinX)/ safeRangeX;let halfW =(barWidth * 0.5)/ safeRangeX;let left = screenX - halfW;let right = screenX + halfW;let normBottom =(barBottom - u.viewMinY)/ safeRangeY;let normTop =(barTop - u.viewMinY)/ safeRangeY;let sBottom = max(1.0 - normBottom,1.0 - normTop);let sTop = min(1.0 - normBottom,1.0 - normTop);var positions = array<vec2f,6>(vec2f(left,sBottom),vec2f(right,sBottom),vec2f(left,sTop),vec2f(left,sTop),vec2f(right,sBottom),vec2f(right,sTop));let sp = positions[vertexType];out.pos = vec4f(sp.x * 2.0 - 1.0,1.0 - sp.y * 2.0,0.0,1.0);out.colorType = dataT[barIdx];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let upRgb = unpack4x8unorm(wu.upColor).rgb;let downRgb = unpack4x8unorm(wu.downColor).rgb;let totalRgb = unpack4x8unorm(wu.totalColor).rgb;var color: vec3f;if(in.colorType < 0.5){color = upRgb;}else if(in.colorType < 1.5){color = downRgb;}else{color = totalRgb;}return vec4f(color,0.9);}`;function F(v,Q,I){let q=Q.length,K=Array(q),V=Array(q),Z=Array(q),$=Array(q),z=0;for(let j=0;j<q;j++){let J=(I?.[j]??0)>0.5,C=Q[j];if(J)K[j]=Math.min(0,z),V[j]=Math.abs(z),Z[j]=2;else{if(C>=0)K[j]=z,V[j]=C,Z[j]=0;else K[j]=z+C,V[j]=Math.abs(C),Z[j]=1;z+=C}}for(let j=0;j<q;j++){let J;if(q<=1)J=1;else if(j===0)J=v[1]-v[0];else if(j===q-1)J=v[q-1]-v[q-2];else J=Math.min(v[j+1]-v[j],v[j]-v[j-1]);$[j]=J*0.8}return{x:v,y:K,h:V,t:Z,bw:$}}var G={name:"waterfall",shaders:{render:f},uniforms:[{name:"upColor",type:"u32",default:M(0.2,0.7,0.3)},{name:"downColor",type:"u32",default:M(0.9,0.3,0.3)},{name:"totalColor",type:"u32",default:M(0.5,0.5,0.6)}],passes:[{type:"render",shader:"render",topology:"triangle-list",loadOp:"load",perSeries:!0,blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({samples:v})=>Math.max(0,v*6),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"custom-uniforms"},{binding:4,source:"h-data"},{binding:5,source:"t-data"},{binding:6,source:"bw-data"}]}],computeBounds(v){let Q=1/0,I=-1/0,q=1/0,K=-1/0;for(let $ of v)for(let z=0;z<$.rawX.length;z++){let j=$.rawX[z],J=$.rawY[z],C=$.extra.h?.[z]??0,O=J+C;if(j<Q)Q=j;if(j>I)I=j;if(J<q)q=J;if(O>K)K=O}if(!isFinite(Q))return{minX:0,maxX:1,minY:0,maxY:1};let V=(I-Q)*0.05||1,Z=(K-q)*0.1||0.1;return{minX:Q-V,maxX:I+V,minY:q-Z,maxY:K+Z}}};export{F as prepareWaterfall,G as WaterfallChart};
|
package/dist/charts/line.js
CHANGED
package/dist/charts/line.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{d as k,e as q}from"../chunk-gm0d4cgx.js";import{f as j}from"../chunk-64q9a7nw.js";import"../chunk-bbyt23tw.js";var F={name:"line",shaders:{compute:k,render:q},uniforms:[{name:"maxSamplesPerPixel",type:"u32",default:1e4}],buffers:[{name:"lineBuffer",bytes:({width:b})=>Math.max(16,b*4*4),usages:["STORAGE"]}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({width:b})=>({x:Math.ceil(Math.max(1,b)/j)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"lineBuffer",write:!0},{binding:4,source:"series-info"},{binding:5,source:"custom-uniforms"}]},{type:"render",shader:"render",topology:"line-list",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({width:b})=>Math.max(0,b*4-2),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"lineBuffer"},{binding:2,source:"series-info"}]}]};export{F as LineChart};
|
package/dist/charts/scatter.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
COMPUTE_WG,
|
|
3
3
|
UNIFORM_STRUCT
|
|
4
4
|
} from "../chunk-0jepamv9.js";
|
|
5
|
-
import"../chunk-
|
|
5
|
+
import"../chunk-5gtx3pza.js";
|
|
6
6
|
|
|
7
7
|
// src/shaders/scatter.ts
|
|
8
8
|
var SCATTER_COMPUTE_SHADER = `${UNIFORM_STRUCT}struct ScatterUniforms{dispatchXCount: u32,pointSize: f32};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> su: ScatterUniforms;@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * su.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(su.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{f as e,g as t}from"../chunk-64q9a7nw.js";import"../chunk-bbyt23tw.js";var n=`${t}struct ScatterUniforms{dispatchXCount: u32,pointSize: f32};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> su: ScatterUniforms;@compute @workgroup_size(${e})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * su.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(su.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var a=65535,g={name:"scatter",shaders:{compute:n},uniforms:[{name:"dispatchXCount",type:"u32",default:1},{name:"pointSize",type:"f32",default:3}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({samples:o})=>{let i=Math.ceil(Math.max(1,o)/e),r=Math.min(i,a),u=Math.ceil(i/a);return{x:r,y:u,xCount:r*e}},bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"render-target",write:!0},{binding:4,source:"series-info"},{binding:5,source:"series-index"},{binding:6,source:"custom-uniforms"}]}]};export{g as ScatterChart};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
var t={left:55,right:10,top:8,bottom:45};
|
|
2
|
-
export{t as
|
|
2
|
+
export{t as o};
|
|
@@ -3,11 +3,22 @@ import {
|
|
|
3
3
|
} from "./chunk-831dem4f.js";
|
|
4
4
|
import {
|
|
5
5
|
ChartManager
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-n8ew0z0e.js";
|
|
7
7
|
|
|
8
8
|
// src/plugins/labels.ts
|
|
9
9
|
var DEFAULT_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif';
|
|
10
10
|
var DEFAULT_LABEL_SIZE = 12;
|
|
11
|
+
function computeHomeView(width, height) {
|
|
12
|
+
const l = 32, t = 8, r = 8, b = 48;
|
|
13
|
+
const innerW = width - l - r;
|
|
14
|
+
const innerH = height - t - b;
|
|
15
|
+
return {
|
|
16
|
+
panX: innerW > 0 ? -l / innerW : 0,
|
|
17
|
+
panY: innerH > 0 ? -b / innerH : 0,
|
|
18
|
+
zoomX: innerW > 0 ? innerW / width : 1,
|
|
19
|
+
zoomY: innerH > 0 ? innerH / height : 1
|
|
20
|
+
};
|
|
21
|
+
}
|
|
11
22
|
var niceTicks = (min, max, count) => {
|
|
12
23
|
const range = max - min;
|
|
13
24
|
if (range <= 0)
|
|
@@ -41,7 +52,20 @@ var getViewState = (chart) => {
|
|
|
41
52
|
};
|
|
42
53
|
var labelsPlugin = {
|
|
43
54
|
name: "labels",
|
|
55
|
+
install(chart) {
|
|
56
|
+
const hv = computeHomeView(chart.width, chart.height);
|
|
57
|
+
chart.homeView = hv;
|
|
58
|
+
chart.view = { ...hv };
|
|
59
|
+
ChartManager.requestRender(chart.id);
|
|
60
|
+
},
|
|
44
61
|
beforeDraw(ctx, chart) {
|
|
62
|
+
const hv = computeHomeView(chart.width, chart.height);
|
|
63
|
+
const old = chart.homeView;
|
|
64
|
+
chart.homeView = hv;
|
|
65
|
+
if (hv.zoomX !== old.zoomX || hv.zoomY !== old.zoomY || hv.panX !== old.panX || hv.panY !== old.panY) {
|
|
66
|
+
chart.view = { ...hv };
|
|
67
|
+
ChartManager.requestRender(chart.id);
|
|
68
|
+
}
|
|
45
69
|
const { w, h, m, rx, ry, mx, my, grid } = getViewState(chart);
|
|
46
70
|
ctx.strokeStyle = grid;
|
|
47
71
|
ctx.lineWidth = 1;
|