chartai 0.1.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 +34 -146
- package/dist/chart-library.d.ts.map +1 -1
- package/dist/chart-library.js +411 -322
- package/dist/chart-library.min.js +1 -1
- package/dist/charts/area.d.ts +6 -0
- package/dist/charts/area.d.ts.map +1 -0
- package/dist/charts/area.js +65 -0
- package/dist/charts/area.min.js +1 -0
- package/dist/charts/bar.d.ts +11 -0
- package/dist/charts/bar.d.ts.map +1 -0
- package/dist/charts/bar.js +65 -0
- package/dist/charts/bar.min.js +1 -0
- package/dist/charts/boids.js +167 -0
- package/dist/charts/boids.min.js +18 -0
- package/dist/charts/candlestick.d.ts +21 -0
- package/dist/charts/candlestick.d.ts.map +1 -0
- package/dist/charts/candlestick.js +10 -0
- package/dist/charts/candlestick.min.js +1 -0
- 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.d.ts +12 -0
- package/dist/charts/line.d.ts.map +1 -0
- package/dist/charts/line.js +62 -0
- package/dist/charts/line.min.js +1 -0
- package/dist/charts/scatter.d.ts +11 -0
- package/dist/charts/scatter.d.ts.map +1 -0
- package/dist/charts/scatter.js +46 -0
- package/dist/charts/scatter.min.js +1 -0
- package/dist/chunk-0eh4rzy9.min.js +2 -0
- package/dist/chunk-0jepamv9.js +7 -0
- package/dist/chunk-1ngxm8t2.js +129 -0
- package/dist/chunk-50bcv2hw.min.js +2 -0
- package/dist/chunk-5gtx3pza.js +9 -0
- package/dist/chunk-64q9a7nw.min.js +2 -0
- package/dist/chunk-831dem4f.js +4 -0
- package/dist/chunk-93yrr7er.js +35 -0
- package/dist/chunk-bbyt23tw.min.js +2 -0
- 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-gm0d4cgx.min.js +2 -0
- package/dist/chunk-mmsy3yqt.js +27 -0
- package/dist/chunk-n8ew0z0e.js +637 -0
- package/dist/chunk-t0kdz02m.js +129 -0
- package/dist/chunk-wdfq2fpx.min.js +2 -0
- package/dist/chunk-yabjrff2.js +11 -0
- package/dist/gpu-worker.js +630 -686
- package/dist/gpu-worker.min.js +1 -1
- package/dist/msg.d.ts +33 -0
- package/dist/msg.d.ts.map +1 -0
- package/dist/plugins/coords.d.ts +18 -0
- package/dist/plugins/coords.d.ts.map +1 -0
- 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 +15 -2
- package/dist/plugins/hover.d.ts.map +1 -1
- package/dist/plugins/hover.js +75 -14
- package/dist/plugins/hover.min.js +1 -1
- package/dist/plugins/labels-panel.d.ts +4 -0
- package/dist/plugins/labels-panel.d.ts.map +1 -0
- package/dist/plugins/labels-panel.js +122 -0
- package/dist/plugins/labels-panel.min.js +1 -0
- package/dist/plugins/labels.d.ts +17 -2
- package/dist/plugins/labels.d.ts.map +1 -1
- package/dist/plugins/labels.js +11 -99
- package/dist/plugins/labels.min.js +1 -1
- package/dist/plugins/legend.d.ts +16 -0
- package/dist/plugins/legend.d.ts.map +1 -0
- package/dist/plugins/legend.js +353 -0
- package/dist/plugins/legend.min.js +37 -0
- package/dist/plugins/shared.d.ts +7 -0
- package/dist/plugins/shared.d.ts.map +1 -0
- package/dist/plugins/zoom.d.ts +10 -2
- package/dist/plugins/zoom.d.ts.map +1 -1
- package/dist/plugins/zoom.js +63 -62
- package/dist/plugins/zoom.min.js +1 -1
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/dist/types.min.js +0 -0
- package/dist/worker-inline.d.ts +1 -1
- package/dist/worker-inline.d.ts.map +1 -1
- package/package.json +11 -11
- package/readme.md +54 -42
- package/dist/chunk-bgfkgcmg.js +0 -25
- package/dist/chunk-cj3zanvs.min.js +0 -2
|
@@ -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};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RendererPlugin } from "../types.ts";
|
|
2
|
+
export interface LineConfig {
|
|
3
|
+
pointSize?: number;
|
|
4
|
+
maxSamplesPerPixel?: number;
|
|
5
|
+
}
|
|
6
|
+
declare module "../types.ts" {
|
|
7
|
+
interface ChartTypeRegistry {
|
|
8
|
+
line: LineConfig;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export declare const LineChart: RendererPlugin;
|
|
12
|
+
//# sourceMappingURL=line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../src/charts/line.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAU,iBAAiB;QACzB,IAAI,EAAE,UAAU,CAAC;KAClB;CACF;AAED,eAAO,MAAM,SAAS,EAAE,cAiDvB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LINE_COMPUTE_SHADER,
|
|
3
|
+
LINE_RENDER_SHADER
|
|
4
|
+
} from "../chunk-yabjrff2.js";
|
|
5
|
+
import {
|
|
6
|
+
COMPUTE_WG
|
|
7
|
+
} from "../chunk-0jepamv9.js";
|
|
8
|
+
import"../chunk-5gtx3pza.js";
|
|
9
|
+
|
|
10
|
+
// src/charts/line.ts
|
|
11
|
+
var LineChart = {
|
|
12
|
+
name: "line",
|
|
13
|
+
shaders: {
|
|
14
|
+
compute: LINE_COMPUTE_SHADER,
|
|
15
|
+
render: LINE_RENDER_SHADER
|
|
16
|
+
},
|
|
17
|
+
uniforms: [
|
|
18
|
+
{ name: "maxSamplesPerPixel", type: "u32", default: 1e4 }
|
|
19
|
+
],
|
|
20
|
+
buffers: [
|
|
21
|
+
{
|
|
22
|
+
name: "lineBuffer",
|
|
23
|
+
bytes: ({ width }) => Math.max(16, width * 4 * 4),
|
|
24
|
+
usages: ["STORAGE"]
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
passes: [
|
|
28
|
+
{
|
|
29
|
+
type: "compute",
|
|
30
|
+
shader: "compute",
|
|
31
|
+
perSeries: true,
|
|
32
|
+
dispatch: ({ width }) => ({ x: Math.ceil(Math.max(1, width) / COMPUTE_WG) }),
|
|
33
|
+
bindings: [
|
|
34
|
+
{ binding: 0, source: "uniforms" },
|
|
35
|
+
{ binding: 1, source: "x-data" },
|
|
36
|
+
{ binding: 2, source: "y-data" },
|
|
37
|
+
{ binding: 3, source: "lineBuffer", write: true },
|
|
38
|
+
{ binding: 4, source: "series-info" },
|
|
39
|
+
{ binding: 5, source: "custom-uniforms" }
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: "render",
|
|
44
|
+
shader: "render",
|
|
45
|
+
topology: "line-list",
|
|
46
|
+
loadOp: "load",
|
|
47
|
+
blend: {
|
|
48
|
+
color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
|
|
49
|
+
alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
|
|
50
|
+
},
|
|
51
|
+
draw: ({ width }) => Math.max(0, width * 4 - 2),
|
|
52
|
+
bindings: [
|
|
53
|
+
{ binding: 0, source: "uniforms" },
|
|
54
|
+
{ binding: 1, source: "lineBuffer" },
|
|
55
|
+
{ binding: 2, source: "series-info" }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
};
|
|
60
|
+
export {
|
|
61
|
+
LineChart
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RendererPlugin } from "../types.ts";
|
|
2
|
+
export interface ScatterConfig {
|
|
3
|
+
pointSize?: number;
|
|
4
|
+
}
|
|
5
|
+
declare module "../types.ts" {
|
|
6
|
+
interface ChartTypeRegistry {
|
|
7
|
+
scatter: ScatterConfig;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export declare const ScatterChart: RendererPlugin;
|
|
11
|
+
//# sourceMappingURL=scatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scatter.d.ts","sourceRoot":"","sources":["../../src/charts/scatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAU,iBAAiB;QACzB,OAAO,EAAE,aAAa,CAAC;KACxB;CACF;AAID,eAAO,MAAM,YAAY,EAAE,cA+B1B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COMPUTE_WG,
|
|
3
|
+
UNIFORM_STRUCT
|
|
4
|
+
} from "../chunk-0jepamv9.js";
|
|
5
|
+
import"../chunk-5gtx3pza.js";
|
|
6
|
+
|
|
7
|
+
// src/shaders/scatter.ts
|
|
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);}}}}`;
|
|
9
|
+
|
|
10
|
+
// src/charts/scatter.ts
|
|
11
|
+
var MAX_WG_DIM = 65535;
|
|
12
|
+
var ScatterChart = {
|
|
13
|
+
name: "scatter",
|
|
14
|
+
shaders: {
|
|
15
|
+
compute: SCATTER_COMPUTE_SHADER
|
|
16
|
+
},
|
|
17
|
+
uniforms: [
|
|
18
|
+
{ name: "dispatchXCount", type: "u32", default: 1 },
|
|
19
|
+
{ name: "pointSize", type: "f32", default: 3 }
|
|
20
|
+
],
|
|
21
|
+
passes: [
|
|
22
|
+
{
|
|
23
|
+
type: "compute",
|
|
24
|
+
shader: "compute",
|
|
25
|
+
perSeries: true,
|
|
26
|
+
dispatch: ({ samples }) => {
|
|
27
|
+
const totalWG = Math.ceil(Math.max(1, samples) / COMPUTE_WG);
|
|
28
|
+
const wgX = Math.min(totalWG, MAX_WG_DIM);
|
|
29
|
+
const wgY = Math.ceil(totalWG / MAX_WG_DIM);
|
|
30
|
+
return { x: wgX, y: wgY, xCount: wgX * COMPUTE_WG };
|
|
31
|
+
},
|
|
32
|
+
bindings: [
|
|
33
|
+
{ binding: 0, source: "uniforms" },
|
|
34
|
+
{ binding: 1, source: "x-data" },
|
|
35
|
+
{ binding: 2, source: "y-data" },
|
|
36
|
+
{ binding: 3, source: "render-target", write: true },
|
|
37
|
+
{ binding: 4, source: "series-info" },
|
|
38
|
+
{ binding: 5, source: "series-index" },
|
|
39
|
+
{ binding: 6, source: "custom-uniforms" }
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
export {
|
|
45
|
+
ScatterChart
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// src/shaders/shared.ts
|
|
2
|
+
var COMPUTE_WG = 256;
|
|
3
|
+
var UNIFORM_STRUCT = `struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,seriesCount: u32,isDark: u32,bgR: f32,bgG: f32,bgB: f32,dataMinX: f32,dataMaxX: f32,dataMinY: f32,dataMaxY: f32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,_pad0: f32,_pad1: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};`;
|
|
4
|
+
var BINARY_SEARCH = `fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}`;
|
|
5
|
+
var BLIT_SHADER = `fn luma(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114));}fn laaa(uv:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let m=textureSample(t,s,uv);let n=textureSample(t,s,uv+vec2f(0.,-r.y));let e=textureSample(t,s,uv+vec2f(r.x,0.));let w=textureSample(t,s,uv+vec2f(-r.x,0.));let sv=textureSample(t,s,uv+vec2f(0.,r.y));let lm=luma(m);let ln=luma(n);let le=luma(e);let lw=luma(w);let ls=luma(sv);let lo=min(lm,min(min(ln,ls),min(le,lw)));let hi=max(lm,max(max(ln,ls),max(le,lw)));let rng=hi-lo;if(rng<max(.0833,hi*.166)){return m;}return mix(m,(m+n+e+w+sv)*.2,min(rng*3.,1.));}struct BV{@builtin(position)p:vec4f,@location(0)uv:vec2f}@group(0)@binding(0)var inputTex:texture_2d<f32>;@group(0)@binding(1)var samp:sampler;@vertex fn vs(@builtin(vertex_index)i:u32)->BV{var p=array<vec2f,4>(vec2f(-1,-1),vec2f(1,-1),vec2f(-1,1),vec2f(1,1));var u=array<vec2f,4>(vec2f(0,1),vec2f(1,1),vec2f(0,0),vec2f(1,0));return BV(vec4f(p[i],0,1),u[i]);}@fragment fn fs(v:BV)->@location(0)vec4f{return laaa(v.uv,inputTex,samp);}`;
|
|
6
|
+
|
|
7
|
+
export { COMPUTE_WG, UNIFORM_STRUCT, BINARY_SEARCH, BLIT_SHADER };
|