chartai 0.0.11 → 0.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/plugins/hover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAGZ,MAAM,qBAAqB,CAAC;AAkC7B,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/plugins/hover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAGZ,MAAM,qBAAqB,CAAC;AAkC7B,eAAO,MAAM,WAAW,EAAE,WA0PzB,CAAC"}
|
package/dist/plugins/hover.js
CHANGED
|
@@ -51,13 +51,21 @@ var hoverPlugin = {
|
|
|
51
51
|
s.pillAnimRef = requestAnimationFrame(tick);
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
|
-
|
|
54
|
+
const handleHover = (clientX, clientY) => {
|
|
55
55
|
if (chart.dragging)
|
|
56
56
|
return;
|
|
57
57
|
const r = el.getBoundingClientRect();
|
|
58
|
-
update(chart.findNearestPoint(
|
|
59
|
-
}
|
|
60
|
-
|
|
58
|
+
update(chart.findNearestPoint(clientX - r.left, clientY - r.top, r.width, r.height));
|
|
59
|
+
};
|
|
60
|
+
el.addEventListener("mousemove", (e) => handleHover(e.clientX, e.clientY), {
|
|
61
|
+
signal: ac.signal
|
|
62
|
+
});
|
|
63
|
+
el.addEventListener("touchmove", (e) => {
|
|
64
|
+
if (e.touches.length === 1) {
|
|
65
|
+
handleHover(e.touches[0].clientX, e.touches[0].clientY);
|
|
66
|
+
}
|
|
67
|
+
}, { signal: ac.signal, passive: true });
|
|
68
|
+
["mouseleave", "pointerdown", "touchend", "touchcancel"].forEach((ev) => el.addEventListener(ev, () => update(null), { signal: ac.signal }));
|
|
61
69
|
},
|
|
62
70
|
afterDraw(ctx, chart) {
|
|
63
71
|
const s = states.get(chart);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as B}from"../chart-library.js";import"../chunk-cj3zanvs.js";var
|
|
1
|
+
import{a as B}from"../chart-library.js";import"../chunk-cj3zanvs.js";var Y=new WeakMap,m=(j,q,I,G,E,O,J,z)=>{j.beginPath(),j.roundRect(q,I,G,E,O),j.fillStyle=J,j.fill(),j.strokeStyle=z,j.lineWidth=1.5,j.stroke()},l={name:"hover",install(j,q){let I=B.getInstance(),G=new AbortController,E={hoverResult:null,pillX:0,pillY:0,pillTargetX:0,pillTargetY:0,pillAnimRef:null,abort:G};Y.set(j,E);let O=(z)=>{if(j.config.onHover)j.config.onHover(z);if(!(j.config.showTooltip??!1))return;if(E.hoverResult=z,I.drawChart(j),z&&!E.pillAnimRef){let U=performance.now(),Q=(F)=>{if(!E.hoverResult)return E.pillAnimRef=null;let N=1-Math.pow(0.5,(F-U)/(j.config.pillDecayMs??60));U=F,E.pillX+=(E.pillTargetX-E.pillX)*N,E.pillY+=(E.pillTargetY-E.pillY)*N,I.drawChart(j),E.pillAnimRef=requestAnimationFrame(Q)};E.pillAnimRef=requestAnimationFrame(Q)}},J=(z,U)=>{if(j.dragging)return;let Q=q.getBoundingClientRect();O(j.findNearestPoint(z-Q.left,U-Q.top,Q.width,Q.height))};q.addEventListener("mousemove",(z)=>J(z.clientX,z.clientY),{signal:G.signal}),q.addEventListener("touchmove",(z)=>{if(z.touches.length===1)J(z.touches[0].clientX,z.touches[0].clientY)},{signal:G.signal,passive:!0}),["mouseleave","pointerdown","touchend","touchcancel"].forEach((z)=>q.addEventListener(z,()=>O(null),{signal:G.signal}))},afterDraw(j,q){let I=Y.get(q);if(!I?.hoverResult||!q.config.showTooltip)return;let{hoverResult:G}=I,E=q.width,O=q.height,J=B.MARGIN,z=B.getInstance().isDark,{formatX:U=String,formatY:Q=String,fontFamily:F=B.DEFAULT_FONT}=q.config,N=(q.bounds.maxX-q.bounds.minX)/q.view.zoomX,g=(q.bounds.maxY-q.bounds.minY)/q.view.zoomY,P=(G.x-(q.bounds.minX+q.view.panX*(q.bounds.maxX-q.bounds.minX)))/N*E,T=O*(1-(G.y-(q.bounds.minY+q.view.panY*(q.bounds.maxY-q.bounds.minY)))/g),u=q.series[G.seriesIndex]||q.series[0],S=`${Math.round(u.color.r*255)},${Math.round(u.color.g*255)},${Math.round(u.color.b*255)}`,H=`rgb(${S})`,k=z?`oklch(from ${H} calc(l + 0.1) c h)`:H;j.save(),j.setLineDash([4,3]),j.strokeStyle=`rgba(${S},0.4)`,j.stroke(new Path2D(`M${P} 0V${O-J.bottom}M${J.left} ${T}H${E}`)),j.restore(),j.beginPath(),j.arc(P,T,4.5,0,Math.PI*2),j.fillStyle=H,j.fill(),j.strokeStyle=z?"rgba(0,0,0,0.6)":"rgba(255,255,255,0.9)",j.stroke();let D=q.series.map((A)=>{let L=0,R=A.rawX.length-1;while(L<=R){let K=L+R>>1;if(Math.abs(A.rawX[K]-G.x)<0.0001)return{label:A.label,val:Q(A.rawY[K]),rawVal:A.rawY[K],col:`rgb(${Math.round(A.color.r*255)},${Math.round(A.color.g*255)},${Math.round(A.color.b*255)})`};A.rawX[K]<G.x?L=K+1:R=K-1}return null}).filter(Boolean);D.sort((A,L)=>Math.abs(L.rawVal)-Math.abs(A.rawVal));let p=D.length,_=D.slice(0,5),C=p-_.length;if(I.pillTargetX=P,I.pillTargetY=T,!I.pillAnimRef)I.pillX=P,I.pillY=T;let X=(A,L,R,K)=>{j.font=`600 10px ${F}`;let b=j.measureText(R).width,Z=b+12,M=18,y=K?A-Z/2:A-Z,o=K?L:L-M/2;j.save();let d=K?Math.atan((I.pillTargetX-I.pillX)/80)*0.2:Math.atan((I.pillTargetY-I.pillY)/80)*0.2;j.translate(A,L),j.rotate(d);let v=K?-Z/2:-Z,w=K?0:-M/2;j.beginPath(),j.roundRect(v,w,Z,M,4),j.fillStyle=z?"rgba(0,0,0,0.75)":"rgba(255,255,255,0.75)",j.fill(),j.fillStyle=`rgba(${S},0.2)`,j.fill(),j.strokeStyle=k,j.lineWidth=1.5,j.stroke(),j.fillStyle=k,j.textAlign="center",j.textBaseline="middle",j.fillText(R,v+Z/2,w+M/2),j.restore()};X(Math.max(J.left,Math.min(E-J.right,I.pillX)),O-J.bottom+4,U(G.x),!0),X(Math.max(J.left,J.left),Math.max(9,Math.min(O-J.bottom-9,I.pillY)),Q(G.y),!1);let f=Math.max(..._.map((A)=>j.measureText(A.label+A.val).width))+40,W=30+_.length*18+(C>0?18:0),V=G.screenX+14,$=G.screenY-W-6;if(V+f>E)V=G.screenX-f-14;if($=Math.max(4,Math.min(O-W-4,G.screenY-W-6)),m(j,V,$,f,W,6,z?"rgba(28,28,30,0.95)":"rgba(255,255,255,0.96)","rgba(0,0,0,0.08)"),j.textAlign="left",j.textBaseline="middle",j.fillStyle=z?"#888":"#999",j.fillText(U(G.x),V+10,$+15),_.forEach((A,L)=>{let R=$+35+L*18;j.fillStyle=A.col,j.beginPath(),j.roundRect(V+10,R-4,8,8,2),j.fill(),j.fillStyle=z?"#eee":"#1a1a1a",j.fillText(`${A.label}: ${A.val}`,V+24,R)}),C>0){let A=$+35+_.length*18;j.fillStyle=z?"#666":"#aaa",j.fillText(`+${C} more`,V+10,A)}},uninstall(j){let q=Y.get(j);if(q?.pillAnimRef)cancelAnimationFrame(q.pillAnimRef);q?.abort.abort(),Y.delete(j)}};export{l as hoverPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../src/plugins/zoom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,qBAAqB,CAAC;AAGtE,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../src/plugins/zoom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,qBAAqB,CAAC;AAGtE,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,WAAW,CA2epE"}
|
package/dist/plugins/zoom.js
CHANGED
|
@@ -5,11 +5,17 @@ import"../chunk-bgfkgcmg.js";
|
|
|
5
5
|
|
|
6
6
|
// src/plugins/zoom.ts
|
|
7
7
|
function zoomPlugin(opts = {}) {
|
|
8
|
-
const decay = opts.momentumDecay ?? 0.
|
|
8
|
+
const decay = opts.momentumDecay ?? 0.9;
|
|
9
9
|
const state = new WeakMap;
|
|
10
10
|
return {
|
|
11
11
|
name: "zoom",
|
|
12
12
|
install(chart, el) {
|
|
13
|
+
const originalTouchAction = el.style.touchAction;
|
|
14
|
+
const originalUserSelect = el.style.userSelect;
|
|
15
|
+
const originalWebkitUserSelect = el.style.webkitUserSelect;
|
|
16
|
+
el.style.touchAction = "none";
|
|
17
|
+
el.style.userSelect = "none";
|
|
18
|
+
el.style.webkitUserSelect = "none";
|
|
13
19
|
const mgr = ChartManager.getInstance();
|
|
14
20
|
const ac = new AbortController;
|
|
15
21
|
const s = {
|
|
@@ -17,12 +23,35 @@ function zoomPlugin(opts = {}) {
|
|
|
17
23
|
lastY: 0,
|
|
18
24
|
velX: 0,
|
|
19
25
|
velY: 0,
|
|
20
|
-
abort: ac
|
|
26
|
+
abort: ac,
|
|
27
|
+
originalTouchAction,
|
|
28
|
+
originalUserSelect,
|
|
29
|
+
originalWebkitUserSelect,
|
|
30
|
+
el
|
|
21
31
|
};
|
|
22
32
|
state.set(chart, s);
|
|
23
33
|
let pointers = [];
|
|
34
|
+
let gestureState = "none";
|
|
35
|
+
let startX = 0;
|
|
36
|
+
let startY = 0;
|
|
37
|
+
let lastX = 0;
|
|
38
|
+
let lastY = 0;
|
|
24
39
|
let lastTime = 0;
|
|
25
|
-
|
|
40
|
+
const PAN_THRESHOLD = 10;
|
|
41
|
+
const TAP_THRESHOLD = 10;
|
|
42
|
+
const PRESS_TIME = 500;
|
|
43
|
+
let pressTimer = null;
|
|
44
|
+
let pinchStartDist = 0;
|
|
45
|
+
let pinchStartZoomX = 1;
|
|
46
|
+
let pinchStartZoomY = 1;
|
|
47
|
+
let pinchCenterX = 0.5;
|
|
48
|
+
let pinchCenterY = 0.5;
|
|
49
|
+
let velX = 0;
|
|
50
|
+
let velY = 0;
|
|
51
|
+
let lastTapTime = 0;
|
|
52
|
+
let edgeScaleMode = null;
|
|
53
|
+
let edgeScaleStart = 0;
|
|
54
|
+
let edgeScaleInitialZoom = 1;
|
|
26
55
|
const sendView = () => {
|
|
27
56
|
mgr.sendViewTransform(chart);
|
|
28
57
|
mgr.drawChart(chart);
|
|
@@ -33,14 +62,14 @@ function zoomPlugin(opts = {}) {
|
|
|
33
62
|
if (chart.momentum)
|
|
34
63
|
cancelAnimationFrame(chart.momentum);
|
|
35
64
|
const tick = () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (Math.abs(
|
|
65
|
+
velX *= decay;
|
|
66
|
+
velY *= decay;
|
|
67
|
+
if (Math.abs(velX) > 0.00005 || Math.abs(velY) > 0.00005) {
|
|
39
68
|
if (chart.zoomMode !== "none" && (chart.zoomMode === "both" || chart.zoomMode === "x-only")) {
|
|
40
|
-
chart.view.panX -=
|
|
69
|
+
chart.view.panX -= velX / chart.view.zoomX;
|
|
41
70
|
}
|
|
42
71
|
if (chart.zoomMode !== "none" && (chart.zoomMode === "both" || chart.zoomMode === "y-only")) {
|
|
43
|
-
chart.view.panY +=
|
|
72
|
+
chart.view.panY += velY / chart.view.zoomY;
|
|
44
73
|
}
|
|
45
74
|
sendView();
|
|
46
75
|
chart.momentum = requestAnimationFrame(tick);
|
|
@@ -50,12 +79,6 @@ function zoomPlugin(opts = {}) {
|
|
|
50
79
|
};
|
|
51
80
|
chart.momentum = requestAnimationFrame(tick);
|
|
52
81
|
};
|
|
53
|
-
const cancelDrag = () => {
|
|
54
|
-
if (chart.dragging) {
|
|
55
|
-
chart.dragging = false;
|
|
56
|
-
pointers = [];
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
82
|
el.addEventListener("pointerdown", (e) => {
|
|
60
83
|
if (chart.momentum) {
|
|
61
84
|
cancelAnimationFrame(chart.momentum);
|
|
@@ -64,89 +87,192 @@ function zoomPlugin(opts = {}) {
|
|
|
64
87
|
pointers.push(e);
|
|
65
88
|
el.setPointerCapture(e.pointerId);
|
|
66
89
|
if (pointers.length === 1) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
gestureState = "detecting";
|
|
91
|
+
startX = e.clientX;
|
|
92
|
+
startY = e.clientY;
|
|
93
|
+
lastX = e.clientX;
|
|
94
|
+
lastY = e.clientY;
|
|
95
|
+
velX = velY = 0;
|
|
71
96
|
lastTime = performance.now();
|
|
97
|
+
edgeScaleMode = null;
|
|
98
|
+
if (e.pointerType === "touch") {
|
|
99
|
+
pressTimer = window.setTimeout(() => {
|
|
100
|
+
if (gestureState === "detecting") {
|
|
101
|
+
gestureState = "press";
|
|
102
|
+
chart.dragging = false;
|
|
103
|
+
}
|
|
104
|
+
}, PRESS_TIME);
|
|
105
|
+
} else {
|
|
106
|
+
const rect = el.getBoundingClientRect();
|
|
107
|
+
const localX = e.clientX - rect.left;
|
|
108
|
+
const localY = e.clientY - rect.top;
|
|
109
|
+
const margin = ChartManager.MARGIN;
|
|
110
|
+
const overYAxis = localX < margin.left;
|
|
111
|
+
const overXAxis = localY > rect.height - margin.bottom;
|
|
112
|
+
if (overYAxis && !overXAxis) {
|
|
113
|
+
edgeScaleMode = "y";
|
|
114
|
+
edgeScaleStart = e.clientY;
|
|
115
|
+
edgeScaleInitialZoom = chart.view.zoomY;
|
|
116
|
+
chart.dragging = true;
|
|
117
|
+
} else if (overXAxis && !overYAxis) {
|
|
118
|
+
edgeScaleMode = "x";
|
|
119
|
+
edgeScaleStart = e.clientX;
|
|
120
|
+
edgeScaleInitialZoom = chart.view.zoomX;
|
|
121
|
+
chart.dragging = true;
|
|
122
|
+
} else {
|
|
123
|
+
chart.dragging = true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
72
126
|
} else if (pointers.length === 2) {
|
|
127
|
+
if (pressTimer) {
|
|
128
|
+
clearTimeout(pressTimer);
|
|
129
|
+
pressTimer = null;
|
|
130
|
+
}
|
|
131
|
+
gestureState = "pinch";
|
|
132
|
+
chart.dragging = false;
|
|
133
|
+
if (e.pointerType === "touch") {
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
}
|
|
73
136
|
const rect = el.getBoundingClientRect();
|
|
74
137
|
const dx = pointers[1].clientX - pointers[0].clientX;
|
|
75
138
|
const dy = pointers[1].clientY - pointers[0].clientY;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
139
|
+
pinchStartDist = Math.hypot(dx, dy);
|
|
140
|
+
pinchStartZoomX = chart.view.zoomX;
|
|
141
|
+
pinchStartZoomY = chart.view.zoomY;
|
|
142
|
+
pinchCenterX = ((pointers[0].clientX + pointers[1].clientX) / 2 - rect.left) / rect.width;
|
|
143
|
+
pinchCenterY = 1 - ((pointers[0].clientY + pointers[1].clientY) / 2 - rect.top) / rect.height;
|
|
81
144
|
}
|
|
82
|
-
}, { signal: ac.signal });
|
|
145
|
+
}, { passive: false, signal: ac.signal });
|
|
83
146
|
el.addEventListener("pointermove", (e) => {
|
|
84
147
|
const idx = pointers.findIndex((p) => p.pointerId === e.pointerId);
|
|
85
|
-
if (idx >= 0)
|
|
148
|
+
if (idx >= 0) {
|
|
86
149
|
pointers[idx] = e;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
150
|
+
}
|
|
151
|
+
if (pointers.length === 1) {
|
|
152
|
+
const totalDist = Math.hypot(e.clientX - startX, e.clientY - startY);
|
|
153
|
+
if (gestureState === "detecting" && totalDist > PAN_THRESHOLD) {
|
|
154
|
+
gestureState = "pan";
|
|
155
|
+
chart.dragging = true;
|
|
156
|
+
if (pressTimer) {
|
|
157
|
+
clearTimeout(pressTimer);
|
|
158
|
+
pressTimer = null;
|
|
159
|
+
}
|
|
95
160
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
chart.view.panX -= dx / chart.view.zoomX;
|
|
161
|
+
if (gestureState === "press") {
|
|
162
|
+
return;
|
|
99
163
|
}
|
|
100
|
-
if (
|
|
101
|
-
|
|
164
|
+
if (edgeScaleMode && e.pointerType !== "touch") {
|
|
165
|
+
if (edgeScaleMode === "x") {
|
|
166
|
+
const pixelDelta = e.clientX - edgeScaleStart;
|
|
167
|
+
const scale = Math.exp(pixelDelta / 200);
|
|
168
|
+
const newZoom = Math.max(ChartManager.MIN_ZOOM, Math.min(ChartManager.MAX_ZOOM, edgeScaleInitialZoom * scale));
|
|
169
|
+
const fx = chart.view.panX + 0.5 / edgeScaleInitialZoom;
|
|
170
|
+
chart.view.zoomX = newZoom;
|
|
171
|
+
chart.view.panX = fx - 0.5 / newZoom;
|
|
172
|
+
sendView();
|
|
173
|
+
return;
|
|
174
|
+
} else if (edgeScaleMode === "y") {
|
|
175
|
+
const pixelDelta = edgeScaleStart - e.clientY;
|
|
176
|
+
const scale = Math.exp(pixelDelta / 200);
|
|
177
|
+
const newZoom = Math.max(ChartManager.MIN_ZOOM, Math.min(ChartManager.MAX_ZOOM, edgeScaleInitialZoom * scale));
|
|
178
|
+
const fy = chart.view.panY + 0.5 / edgeScaleInitialZoom;
|
|
179
|
+
chart.view.zoomY = newZoom;
|
|
180
|
+
chart.view.panY = fy - 0.5 / newZoom;
|
|
181
|
+
sendView();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
102
184
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
185
|
+
if (gestureState === "pan" || chart.dragging && !edgeScaleMode) {
|
|
186
|
+
const rect = el.getBoundingClientRect();
|
|
187
|
+
const dx = (e.clientX - lastX) / rect.width;
|
|
188
|
+
const dy = (e.clientY - lastY) / rect.height;
|
|
189
|
+
const now = performance.now();
|
|
190
|
+
if (now - lastTime < 100) {
|
|
191
|
+
velX = velX * 0.3 + dx * 0.7;
|
|
192
|
+
velY = velY * 0.3 + dy * 0.7;
|
|
193
|
+
}
|
|
194
|
+
lastTime = now;
|
|
195
|
+
if (chart.zoomMode !== "none" && (chart.zoomMode === "both" || chart.zoomMode === "x-only")) {
|
|
196
|
+
chart.view.panX -= dx / chart.view.zoomX;
|
|
197
|
+
}
|
|
198
|
+
if (chart.zoomMode !== "none" && (chart.zoomMode === "both" || chart.zoomMode === "y-only")) {
|
|
199
|
+
chart.view.panY += dy / chart.view.zoomY;
|
|
200
|
+
}
|
|
201
|
+
lastX = e.clientX;
|
|
202
|
+
lastY = e.clientY;
|
|
203
|
+
sendView();
|
|
204
|
+
}
|
|
205
|
+
} else if (pointers.length === 2 && gestureState === "pinch") {
|
|
206
|
+
if (e.pointerType === "touch") {
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
}
|
|
209
|
+
const rect = el.getBoundingClientRect();
|
|
107
210
|
const dx = pointers[1].clientX - pointers[0].clientX;
|
|
108
211
|
const dy = pointers[1].clientY - pointers[0].clientY;
|
|
109
|
-
const
|
|
110
|
-
const
|
|
212
|
+
const dist = Math.hypot(dx, dy);
|
|
213
|
+
const currentPinchCenterX = ((pointers[0].clientX + pointers[1].clientX) / 2 - rect.left) / rect.width;
|
|
214
|
+
const currentPinchCenterY = 1 - ((pointers[0].clientY + pointers[1].clientY) / 2 - rect.top) / rect.height;
|
|
215
|
+
const pixelChange = dist - pinchStartDist;
|
|
216
|
+
const scale = Math.exp(pixelChange / 280);
|
|
111
217
|
if (chart.zoomMode !== "none" && (chart.zoomMode === "both" || chart.zoomMode === "x-only")) {
|
|
112
|
-
const newZoomX = Math.max(ChartManager.MIN_ZOOM, Math.min(ChartManager.MAX_ZOOM,
|
|
113
|
-
const fx = chart.view.panX +
|
|
218
|
+
const newZoomX = Math.max(ChartManager.MIN_ZOOM, Math.min(ChartManager.MAX_ZOOM, pinchStartZoomX * scale));
|
|
219
|
+
const fx = chart.view.panX + currentPinchCenterX / chart.view.zoomX;
|
|
114
220
|
chart.view.zoomX = newZoomX;
|
|
115
|
-
chart.view.panX = fx -
|
|
221
|
+
chart.view.panX = fx - currentPinchCenterX / newZoomX;
|
|
116
222
|
}
|
|
117
223
|
if (chart.zoomMode !== "none" && (chart.zoomMode === "both" || chart.zoomMode === "y-only")) {
|
|
118
|
-
const newZoomY = Math.max(ChartManager.MIN_ZOOM, Math.min(ChartManager.MAX_ZOOM,
|
|
119
|
-
const fy = chart.view.panY +
|
|
224
|
+
const newZoomY = Math.max(ChartManager.MIN_ZOOM, Math.min(ChartManager.MAX_ZOOM, pinchStartZoomY * scale));
|
|
225
|
+
const fy = chart.view.panY + currentPinchCenterY / chart.view.zoomY;
|
|
120
226
|
chart.view.zoomY = newZoomY;
|
|
121
|
-
chart.view.panY = fy -
|
|
227
|
+
chart.view.panY = fy - currentPinchCenterY / newZoomY;
|
|
122
228
|
}
|
|
123
229
|
sendView();
|
|
124
230
|
}
|
|
125
|
-
}, { signal: ac.signal });
|
|
231
|
+
}, { passive: false, signal: ac.signal });
|
|
126
232
|
const endPointer = (e) => {
|
|
127
233
|
pointers = pointers.filter((p) => p.pointerId !== e.pointerId);
|
|
128
234
|
el.releasePointerCapture(e.pointerId);
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
235
|
+
if (pressTimer) {
|
|
236
|
+
clearTimeout(pressTimer);
|
|
237
|
+
pressTimer = null;
|
|
238
|
+
}
|
|
239
|
+
if (pointers.length === 0) {
|
|
240
|
+
const totalDist = Math.hypot(e.clientX - startX, e.clientY - startY);
|
|
241
|
+
const isTap = totalDist < TAP_THRESHOLD && gestureState !== "pan";
|
|
242
|
+
if (isTap && e.pointerType === "touch") {
|
|
243
|
+
const now = Date.now();
|
|
244
|
+
if (now - lastTapTime < 300) {
|
|
245
|
+
mgr.resetView(chart.id);
|
|
246
|
+
lastTapTime = 0;
|
|
247
|
+
} else {
|
|
248
|
+
lastTapTime = now;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (isTap && e.pointerType !== "touch") {
|
|
252
|
+
const now = Date.now();
|
|
253
|
+
if (now - lastTapTime < 300) {
|
|
254
|
+
mgr.resetView(chart.id);
|
|
255
|
+
lastTapTime = 0;
|
|
256
|
+
} else {
|
|
257
|
+
lastTapTime = now;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (gestureState === "pan" && (Math.abs(velX) > 0.001 || Math.abs(velY) > 0.001)) {
|
|
132
261
|
startMomentum();
|
|
133
262
|
}
|
|
263
|
+
gestureState = "none";
|
|
264
|
+
chart.dragging = false;
|
|
265
|
+
edgeScaleMode = null;
|
|
266
|
+
} else if (pointers.length === 1) {
|
|
267
|
+
gestureState = "detecting";
|
|
268
|
+
startX = pointers[0].clientX;
|
|
269
|
+
startY = pointers[0].clientY;
|
|
270
|
+
lastX = pointers[0].clientX;
|
|
271
|
+
lastY = pointers[0].clientY;
|
|
134
272
|
}
|
|
135
273
|
};
|
|
136
274
|
el.addEventListener("pointerup", endPointer, { signal: ac.signal });
|
|
137
|
-
el.addEventListener("pointercancel", endPointer, {
|
|
138
|
-
signal: ac.signal
|
|
139
|
-
});
|
|
140
|
-
el.addEventListener("pointerleave", cancelDrag, {
|
|
141
|
-
signal: ac.signal
|
|
142
|
-
});
|
|
143
|
-
let lastTap = 0;
|
|
144
|
-
el.addEventListener("pointerup", () => {
|
|
145
|
-
const now = Date.now();
|
|
146
|
-
if (now - lastTap < 300)
|
|
147
|
-
mgr.resetView(chart.id);
|
|
148
|
-
lastTap = now;
|
|
149
|
-
}, { signal: ac.signal });
|
|
275
|
+
el.addEventListener("pointercancel", endPointer, { signal: ac.signal });
|
|
150
276
|
el.addEventListener("wheel", (e) => {
|
|
151
277
|
e.preventDefault();
|
|
152
278
|
if (chart.momentum) {
|
|
@@ -195,6 +321,9 @@ function zoomPlugin(opts = {}) {
|
|
|
195
321
|
cancelAnimationFrame(chart.momentum);
|
|
196
322
|
chart.momentum = null;
|
|
197
323
|
}
|
|
324
|
+
s.el.style.touchAction = s.originalTouchAction;
|
|
325
|
+
s.el.style.userSelect = s.originalUserSelect;
|
|
326
|
+
s.el.style.webkitUserSelect = s.originalWebkitUserSelect;
|
|
198
327
|
s.abort.abort();
|
|
199
328
|
state.delete(chart);
|
|
200
329
|
}
|
package/dist/plugins/zoom.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as $}from"../chart-library.js";import"../chunk-cj3zanvs.js";function r(S={}){let M=S.momentumDecay??0.9,v=new WeakMap;return{name:"zoom",install(j,F){let g=F.style.touchAction,m=F.style.userSelect,p=F.style.webkitUserSelect;F.style.touchAction="none",F.style.userSelect="none",F.style.webkitUserSelect="none";let E=$.getInstance(),H=new AbortController,n={lastX:0,lastY:0,velX:0,velY:0,abort:H,originalTouchAction:g,originalUserSelect:m,originalWebkitUserSelect:p,el:F};v.set(j,n);let B=[],O="none",A=0,P=0,z=0,y=0,w=0,i=10,l=10,o=500,b=null,T=0,X=1,Y=1,s=0.5,h=0.5,_=0,k=0,V=0,W=null,Z=0,f=1,D=()=>{if(E.sendViewTransform(j),E.drawChart(j),E.syncViews)E.syncAllViews(j)},c=()=>{if(j.momentum)cancelAnimationFrame(j.momentum);let q=()=>{if(_*=M,k*=M,Math.abs(_)>0.00005||Math.abs(k)>0.00005){if(j.zoomMode!=="none"&&(j.zoomMode==="both"||j.zoomMode==="x-only"))j.view.panX-=_/j.view.zoomX;if(j.zoomMode!=="none"&&(j.zoomMode==="both"||j.zoomMode==="y-only"))j.view.panY+=k/j.view.zoomY;D(),j.momentum=requestAnimationFrame(q)}else j.momentum=null};j.momentum=requestAnimationFrame(q)};F.addEventListener("pointerdown",(q)=>{if(j.momentum)cancelAnimationFrame(j.momentum),j.momentum=null;if(B.push(q),F.setPointerCapture(q.pointerId),B.length===1)if(O="detecting",A=q.clientX,P=q.clientY,z=q.clientX,y=q.clientY,_=k=0,w=performance.now(),W=null,q.pointerType==="touch")b=window.setTimeout(()=>{if(O==="detecting")O="press",j.dragging=!1},o);else{let J=F.getBoundingClientRect(),K=q.clientX-J.left,G=q.clientY-J.top,L=$.MARGIN,Q=K<L.left,N=G>J.height-L.bottom;if(Q&&!N)W="y",Z=q.clientY,f=j.view.zoomY,j.dragging=!0;else if(N&&!Q)W="x",Z=q.clientX,f=j.view.zoomX,j.dragging=!0;else j.dragging=!0}else if(B.length===2){if(b)clearTimeout(b),b=null;if(O="pinch",j.dragging=!1,q.pointerType==="touch")q.preventDefault();let J=F.getBoundingClientRect(),K=B[1].clientX-B[0].clientX,G=B[1].clientY-B[0].clientY;T=Math.hypot(K,G),X=j.view.zoomX,Y=j.view.zoomY,s=((B[0].clientX+B[1].clientX)/2-J.left)/J.width,h=1-((B[0].clientY+B[1].clientY)/2-J.top)/J.height}},{passive:!1,signal:H.signal}),F.addEventListener("pointermove",(q)=>{let J=B.findIndex((K)=>K.pointerId===q.pointerId);if(J>=0)B[J]=q;if(B.length===1){let K=Math.hypot(q.clientX-A,q.clientY-P);if(O==="detecting"&&K>i){if(O="pan",j.dragging=!0,b)clearTimeout(b),b=null}if(O==="press")return;if(W&&q.pointerType!=="touch"){if(W==="x"){let G=q.clientX-Z,L=Math.exp(G/200),Q=Math.max($.MIN_ZOOM,Math.min($.MAX_ZOOM,f*L)),N=j.view.panX+0.5/f;j.view.zoomX=Q,j.view.panX=N-0.5/Q,D();return}else if(W==="y"){let G=Z-q.clientY,L=Math.exp(G/200),Q=Math.max($.MIN_ZOOM,Math.min($.MAX_ZOOM,f*L)),N=j.view.panY+0.5/f;j.view.zoomY=Q,j.view.panY=N-0.5/Q,D();return}}if(O==="pan"||j.dragging&&!W){let G=F.getBoundingClientRect(),L=(q.clientX-z)/G.width,Q=(q.clientY-y)/G.height,N=performance.now();if(N-w<100)_=_*0.3+L*0.7,k=k*0.3+Q*0.7;if(w=N,j.zoomMode!=="none"&&(j.zoomMode==="both"||j.zoomMode==="x-only"))j.view.panX-=L/j.view.zoomX;if(j.zoomMode!=="none"&&(j.zoomMode==="both"||j.zoomMode==="y-only"))j.view.panY+=Q/j.view.zoomY;z=q.clientX,y=q.clientY,D()}}else if(B.length===2&&O==="pinch"){if(q.pointerType==="touch")q.preventDefault();let K=F.getBoundingClientRect(),G=B[1].clientX-B[0].clientX,L=B[1].clientY-B[0].clientY,Q=Math.hypot(G,L),N=((B[0].clientX+B[1].clientX)/2-K.left)/K.width,I=1-((B[0].clientY+B[1].clientY)/2-K.top)/K.height,x=Q-T,u=Math.exp(x/280);if(j.zoomMode!=="none"&&(j.zoomMode==="both"||j.zoomMode==="x-only")){let U=Math.max($.MIN_ZOOM,Math.min($.MAX_ZOOM,X*u)),R=j.view.panX+N/j.view.zoomX;j.view.zoomX=U,j.view.panX=R-N/U}if(j.zoomMode!=="none"&&(j.zoomMode==="both"||j.zoomMode==="y-only")){let U=Math.max($.MIN_ZOOM,Math.min($.MAX_ZOOM,Y*u)),R=j.view.panY+I/j.view.zoomY;j.view.zoomY=U,j.view.panY=R-I/U}D()}},{passive:!1,signal:H.signal});let d=(q)=>{if(B=B.filter((J)=>J.pointerId!==q.pointerId),F.releasePointerCapture(q.pointerId),b)clearTimeout(b),b=null;if(B.length===0){let K=Math.hypot(q.clientX-A,q.clientY-P)<l&&O!=="pan";if(K&&q.pointerType==="touch"){let G=Date.now();if(G-V<300)E.resetView(j.id),V=0;else V=G}if(K&&q.pointerType!=="touch"){let G=Date.now();if(G-V<300)E.resetView(j.id),V=0;else V=G}if(O==="pan"&&(Math.abs(_)>0.001||Math.abs(k)>0.001))c();O="none",j.dragging=!1,W=null}else if(B.length===1)O="detecting",A=B[0].clientX,P=B[0].clientY,z=B[0].clientX,y=B[0].clientY};F.addEventListener("pointerup",d,{signal:H.signal}),F.addEventListener("pointercancel",d,{signal:H.signal}),F.addEventListener("wheel",(q)=>{if(q.preventDefault(),j.momentum)cancelAnimationFrame(j.momentum),j.momentum=null;let J=F.getBoundingClientRect(),K=q.clientX-J.left,G=q.clientY-J.top,L=K/J.width,Q=1-G/J.height,N=1-q.deltaY*0.002,I=$.MARGIN,x=K<I.left,u=G>J.height-I.bottom,U,R;if(x)U=!1,R=!0;else if(u)U=!0,R=!1;else U=j.zoomMode==="both"||j.zoomMode==="x-only",R=j.zoomMode==="both"||j.zoomMode==="y-only";if(U){let C=j.view.panX+L/j.view.zoomX;j.view.zoomX=Math.max($.MIN_ZOOM,Math.min($.MAX_ZOOM,j.view.zoomX*N)),j.view.panX=C-L/j.view.zoomX}if(R){let C=j.view.panY+Q/j.view.zoomY;j.view.zoomY=Math.max($.MIN_ZOOM,Math.min($.MAX_ZOOM,j.view.zoomY*N)),j.view.panY=C-Q/j.view.zoomY}if(U||R)D()},{passive:!1,signal:H.signal})},uninstall(j){let F=v.get(j);if(F){if(j.momentum)cancelAnimationFrame(j.momentum),j.momentum=null;F.el.style.touchAction=F.originalTouchAction,F.el.style.userSelect=F.originalUserSelect,F.el.style.webkitUserSelect=F.originalWebkitUserSelect,F.abort.abort(),v.delete(j)}}}}export{r as zoomPlugin};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chartai",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "tiny gpu powered charts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/chart-library.js",
|
|
@@ -74,5 +74,6 @@
|
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=18.0.0"
|
|
77
|
-
}
|
|
77
|
+
},
|
|
78
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
78
79
|
}
|