@chartts/gl 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/dist/bar3d.cjs +4 -4
- package/dist/bar3d.js +1 -1
- package/dist/{chunk-Q4JAQOV3.cjs → chunk-JCECG2KY.cjs} +192 -81
- package/dist/chunk-JCECG2KY.cjs.map +1 -0
- package/dist/{chunk-M24XMYGG.js → chunk-XGQDO4VO.js} +192 -81
- package/dist/chunk-XGQDO4VO.js.map +1 -0
- package/dist/flow-gl.cjs +4 -4
- package/dist/flow-gl.js +1 -1
- package/dist/globe3d.cjs +4 -4
- package/dist/globe3d.d.cts +2 -1
- package/dist/globe3d.d.ts +2 -1
- package/dist/globe3d.js +1 -1
- package/dist/graph-gl.cjs +4 -4
- package/dist/graph-gl.js +1 -1
- package/dist/index.cjs +52 -52
- package/dist/index.js +1 -1
- package/dist/line3d.cjs +4 -4
- package/dist/line3d.js +1 -1
- package/dist/lines-gl.cjs +4 -4
- package/dist/lines-gl.js +1 -1
- package/dist/lines3d.cjs +4 -4
- package/dist/lines3d.js +1 -1
- package/dist/map3d.cjs +4 -4
- package/dist/map3d.js +1 -1
- package/dist/scatter-gl.cjs +4 -4
- package/dist/scatter-gl.js +1 -1
- package/dist/scatter3d.cjs +4 -4
- package/dist/scatter3d.js +1 -1
- package/dist/surface3d.cjs +4 -4
- package/dist/surface3d.js +1 -1
- package/package.json +5 -4
- package/dist/chunk-M24XMYGG.js.map +0 -1
- package/dist/chunk-Q4JAQOV3.cjs.map +0 -1
|
@@ -1811,20 +1811,36 @@ function createSurface3DPlugin() {
|
|
|
1811
1811
|
}
|
|
1812
1812
|
|
|
1813
1813
|
// src/charts/globe3d/globe3d-type.ts
|
|
1814
|
+
var GLOBE_RADIUS = 3;
|
|
1815
|
+
var SEGMENTS = 128;
|
|
1816
|
+
var RINGS = 64;
|
|
1814
1817
|
function latLngToXYZ(lat, lng, radius) {
|
|
1815
1818
|
const phi = (90 - lat) * Math.PI / 180;
|
|
1816
1819
|
const theta = (lng + 180) * Math.PI / 180;
|
|
1817
|
-
return [
|
|
1820
|
+
return [
|
|
1821
|
+
-radius * Math.sin(phi) * Math.cos(theta),
|
|
1822
|
+
radius * Math.cos(phi),
|
|
1823
|
+
radius * Math.sin(phi) * Math.sin(theta)
|
|
1824
|
+
];
|
|
1825
|
+
}
|
|
1826
|
+
function angularDistance(lat1, lng1, lat2, lng2) {
|
|
1827
|
+
const p1 = lat1 * Math.PI / 180, p2 = lat2 * Math.PI / 180;
|
|
1828
|
+
const dl = (lng2 - lng1) * Math.PI / 180;
|
|
1829
|
+
return Math.acos(
|
|
1830
|
+
Math.min(1, Math.max(
|
|
1831
|
+
-1,
|
|
1832
|
+
Math.sin(p1) * Math.sin(p2) + Math.cos(p1) * Math.cos(p2) * Math.cos(dl)
|
|
1833
|
+
))
|
|
1834
|
+
);
|
|
1818
1835
|
}
|
|
1819
1836
|
function createGlobe3DPlugin() {
|
|
1820
1837
|
let sphereVBO = null;
|
|
1821
1838
|
let sphereIBO = null;
|
|
1822
1839
|
let sphereIndexCount = 0;
|
|
1823
|
-
let pointVBO = null;
|
|
1824
|
-
let pointCount = 0;
|
|
1825
1840
|
const modelMatrix = mat4();
|
|
1826
1841
|
const normalMatrix = new Float32Array(9);
|
|
1827
|
-
let
|
|
1842
|
+
let screenPoints = [];
|
|
1843
|
+
let seriesInfo = [];
|
|
1828
1844
|
return {
|
|
1829
1845
|
type: "globe3d",
|
|
1830
1846
|
prepare(ctx) {
|
|
@@ -1838,93 +1854,178 @@ function createGlobe3DPlugin() {
|
|
|
1838
1854
|
[...MESH_VERT_UNIFORMS, ...MESH_FRAG_UNIFORMS],
|
|
1839
1855
|
MESH_VERT_ATTRIBUTES
|
|
1840
1856
|
);
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
);
|
|
1848
|
-
const globeRadius = 3;
|
|
1849
|
-
const segments = 64, rings = 32;
|
|
1850
|
-
const sphereColor = [0.12, 0.22, 0.48];
|
|
1851
|
-
const sv = [], si = [];
|
|
1852
|
-
for (let ring = 0; ring <= rings; ring++) {
|
|
1853
|
-
const phi = ring / rings * Math.PI;
|
|
1854
|
-
for (let seg = 0; seg <= segments; seg++) {
|
|
1855
|
-
const theta = seg / segments * Math.PI * 2;
|
|
1856
|
-
const nx = Math.sin(phi) * Math.cos(theta), ny = Math.cos(phi), nz = Math.sin(phi) * Math.sin(theta);
|
|
1857
|
-
sv.push(nx * globeRadius, ny * globeRadius, nz * globeRadius, nx, ny, nz, ...sphereColor);
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
for (let ring = 0; ring < rings; ring++) for (let seg = 0; seg < segments; seg++) {
|
|
1861
|
-
const a = ring * (segments + 1) + seg, b = a + segments + 1;
|
|
1862
|
-
si.push(a, b, a + 1, a + 1, b, b + 1);
|
|
1863
|
-
}
|
|
1864
|
-
if (sphereVBO) sphereVBO.update(new Float32Array(sv));
|
|
1865
|
-
else sphereVBO = createVertexBuffer(gl, new Float32Array(sv), gl.STATIC_DRAW);
|
|
1866
|
-
if (sphereIBO) sphereIBO.update(new Uint16Array(si));
|
|
1867
|
-
else sphereIBO = createIndexBuffer(gl, new Uint16Array(si), gl.STATIC_DRAW);
|
|
1868
|
-
sphereIndexCount = si.length;
|
|
1869
|
-
globePoints = [];
|
|
1870
|
-
const pv = [];
|
|
1857
|
+
const patches = [];
|
|
1858
|
+
let maxVal = 0;
|
|
1859
|
+
for (const s of series) for (const v of s.values) if (Math.abs(v) > maxVal) maxVal = Math.abs(v);
|
|
1860
|
+
if (maxVal === 0) maxVal = 1;
|
|
1861
|
+
seriesInfo = [];
|
|
1862
|
+
screenPoints = [];
|
|
1871
1863
|
for (let sIdx = 0; sIdx < series.length; sIdx++) {
|
|
1872
1864
|
const s = series[sIdx];
|
|
1873
|
-
const
|
|
1865
|
+
const colorHex = s.color ?? theme.colors[sIdx % theme.colors.length];
|
|
1866
|
+
const color = hexToRGB(colorHex);
|
|
1867
|
+
seriesInfo.push({ name: s.name, color: colorHex });
|
|
1874
1868
|
for (let di = 0; di < s.values.length; di++) {
|
|
1875
1869
|
const lat = s.y?.[di] ?? 0, lng = s.x?.[di] ?? 0, value = s.values[di];
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
1870
|
+
const normValue = Math.abs(value) / maxVal;
|
|
1871
|
+
patches.push({ lat, lng, value, normValue, color, si: sIdx, di, name: s.name, label: data.categories?.[di] ?? "" });
|
|
1872
|
+
const [wx, wy, wz] = latLngToXYZ(lat, lng, GLOBE_RADIUS);
|
|
1873
|
+
screenPoints.push({ si: sIdx, di, lat, lng, wx, wy, wz, value, name: s.name, label: data.categories?.[di] ?? "" });
|
|
1879
1874
|
}
|
|
1880
1875
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1876
|
+
const baseColor = [0.03, 0.05, 0.12];
|
|
1877
|
+
const patchRadius = 0.8;
|
|
1878
|
+
const gratLatStep = 30, gratLngStep = 30;
|
|
1879
|
+
const gratWidth = 0.015;
|
|
1880
|
+
const gratColor = [0.08, 0.12, 0.22];
|
|
1881
|
+
console.log(`[Globe3D] Building sphere ${SEGMENTS}x${RINGS}, ${patches.length} data patches`);
|
|
1882
|
+
const verts = [];
|
|
1883
|
+
const indices = [];
|
|
1884
|
+
let patchedVerts = 0;
|
|
1885
|
+
for (let ring = 0; ring <= RINGS; ring++) {
|
|
1886
|
+
const phi = ring / RINGS * Math.PI;
|
|
1887
|
+
const lat = 90 - ring / RINGS * 180;
|
|
1888
|
+
for (let seg = 0; seg <= SEGMENTS; seg++) {
|
|
1889
|
+
const theta = seg / SEGMENTS * Math.PI * 2;
|
|
1890
|
+
const lng = seg / SEGMENTS * 360 - 180;
|
|
1891
|
+
const nx = Math.sin(phi) * Math.cos(theta);
|
|
1892
|
+
const ny = Math.cos(phi);
|
|
1893
|
+
const nz = Math.sin(phi) * Math.sin(theta);
|
|
1894
|
+
let r = baseColor[0], g = baseColor[1], b = baseColor[2];
|
|
1895
|
+
const latMod = (lat % gratLatStep + gratLatStep) % gratLatStep;
|
|
1896
|
+
const latDist = Math.min(latMod, gratLatStep - latMod) * Math.PI / 180;
|
|
1897
|
+
const lngMod = (lng % gratLngStep + gratLngStep) % gratLngStep;
|
|
1898
|
+
const lngDist = Math.min(lngMod, gratLngStep - lngMod) * Math.PI / 180;
|
|
1899
|
+
const gratDist = Math.min(latDist, lngDist);
|
|
1900
|
+
if (gratDist < gratWidth) {
|
|
1901
|
+
const gratT = 1 - gratDist / gratWidth;
|
|
1902
|
+
r = r + (gratColor[0] - r) * gratT;
|
|
1903
|
+
g = g + (gratColor[1] - g) * gratT;
|
|
1904
|
+
b = b + (gratColor[2] - b) * gratT;
|
|
1905
|
+
}
|
|
1906
|
+
let ar = 0, ag = 0, ab = 0;
|
|
1907
|
+
for (const patch of patches) {
|
|
1908
|
+
const dist = angularDistance(lat, lng, patch.lat, patch.lng);
|
|
1909
|
+
if (dist < patchRadius) {
|
|
1910
|
+
const t = 1 - dist / patchRadius;
|
|
1911
|
+
const influence = t * (0.4 + t * 0.6) * patch.normValue;
|
|
1912
|
+
ar += patch.color[0] * influence;
|
|
1913
|
+
ag += patch.color[1] * influence;
|
|
1914
|
+
ab += patch.color[2] * influence;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
if (ar > 0.01 || ag > 0.01 || ab > 0.01) {
|
|
1918
|
+
patchedVerts++;
|
|
1919
|
+
r = Math.min(1, r + ar);
|
|
1920
|
+
g = Math.min(1, g + ag);
|
|
1921
|
+
b = Math.min(1, b + ab);
|
|
1922
|
+
}
|
|
1923
|
+
verts.push(
|
|
1924
|
+
nx * GLOBE_RADIUS,
|
|
1925
|
+
ny * GLOBE_RADIUS,
|
|
1926
|
+
nz * GLOBE_RADIUS,
|
|
1927
|
+
nx,
|
|
1928
|
+
ny,
|
|
1929
|
+
nz,
|
|
1930
|
+
r,
|
|
1931
|
+
g,
|
|
1932
|
+
b
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
console.log(`[Globe3D] ${patchedVerts} / ${(RINGS + 1) * (SEGMENTS + 1)} vertices colored by data`);
|
|
1937
|
+
for (let ring = 0; ring < RINGS; ring++) {
|
|
1938
|
+
for (let seg = 0; seg < SEGMENTS; seg++) {
|
|
1939
|
+
const a = ring * (SEGMENTS + 1) + seg;
|
|
1940
|
+
const b = a + SEGMENTS + 1;
|
|
1941
|
+
indices.push(a, b, a + 1, a + 1, b, b + 1);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
const vertArr = new Float32Array(verts);
|
|
1945
|
+
const idxArr = new Uint16Array(indices);
|
|
1946
|
+
if (sphereVBO) sphereVBO.update(vertArr);
|
|
1947
|
+
else sphereVBO = createVertexBuffer(gl, vertArr, gl.DYNAMIC_DRAW);
|
|
1948
|
+
if (sphereIBO) sphereIBO.update(idxArr);
|
|
1949
|
+
else sphereIBO = createIndexBuffer(gl, idxArr, gl.DYNAMIC_DRAW);
|
|
1950
|
+
sphereIndexCount = indices.length;
|
|
1884
1951
|
mat4Identity(modelMatrix);
|
|
1885
1952
|
},
|
|
1886
1953
|
render(ctx) {
|
|
1887
1954
|
const { renderer, camera } = ctx;
|
|
1888
1955
|
const gl = renderer.gl;
|
|
1889
1956
|
const progress = ctx.animationProgress;
|
|
1890
|
-
const
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1957
|
+
const prog = renderer.getProgram("mesh");
|
|
1958
|
+
prog.use();
|
|
1959
|
+
prog.setMat4("u_projView", camera.projViewMatrix);
|
|
1960
|
+
prog.setMat4("u_model", modelMatrix);
|
|
1894
1961
|
mat3NormalFromMat4(normalMatrix, modelMatrix);
|
|
1895
|
-
|
|
1896
|
-
setLightUniforms(
|
|
1897
|
-
|
|
1962
|
+
prog.setMat3("u_normalMatrix", normalMatrix);
|
|
1963
|
+
setLightUniforms(prog, defaultLightConfig(), camera.position);
|
|
1964
|
+
prog.setFloat("u_opacity", progress);
|
|
1898
1965
|
if (sphereVBO && sphereIBO) {
|
|
1899
1966
|
sphereVBO.bind();
|
|
1900
|
-
const
|
|
1901
|
-
{ location:
|
|
1902
|
-
{ location:
|
|
1903
|
-
{ location:
|
|
1967
|
+
const layout = createVertexLayout([
|
|
1968
|
+
{ location: prog.attributes["a_position"], size: 3 },
|
|
1969
|
+
{ location: prog.attributes["a_normal"], size: 3 },
|
|
1970
|
+
{ location: prog.attributes["a_color"], size: 3 }
|
|
1904
1971
|
]);
|
|
1905
|
-
applyVertexLayout(gl,
|
|
1972
|
+
applyVertexLayout(gl, layout);
|
|
1906
1973
|
sphereIBO.bind();
|
|
1907
|
-
|
|
1908
|
-
|
|
1974
|
+
const indexType = gl.UNSIGNED_SHORT;
|
|
1975
|
+
gl.drawElements(gl.TRIANGLES, sphereIndexCount, indexType, 0);
|
|
1976
|
+
disableVertexLayout(gl, layout);
|
|
1909
1977
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1978
|
+
},
|
|
1979
|
+
renderOverlay(ctx, ctx2d) {
|
|
1980
|
+
const { camera, width, height, theme, animationProgress } = ctx;
|
|
1981
|
+
if (animationProgress < 0.5) return;
|
|
1982
|
+
ctx2d.save();
|
|
1983
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
1984
|
+
ctx2d.font = `${theme.fontSize - 1}px ${theme.fontFamily}`;
|
|
1985
|
+
ctx2d.textBaseline = "middle";
|
|
1986
|
+
for (const sp of screenPoints) {
|
|
1987
|
+
if (!sp.label || seenLabels.has(sp.label)) continue;
|
|
1988
|
+
const screen = projectToScreen(
|
|
1989
|
+
new Float32Array([sp.wx, sp.wy, sp.wz]),
|
|
1990
|
+
camera.projViewMatrix,
|
|
1991
|
+
width,
|
|
1992
|
+
height
|
|
1993
|
+
);
|
|
1994
|
+
if (!screen || screen.z < -1 || screen.z > 1 || screen.z > 0.97) continue;
|
|
1995
|
+
seenLabels.add(sp.label);
|
|
1996
|
+
ctx2d.fillStyle = theme.textColor;
|
|
1997
|
+
ctx2d.globalAlpha = 0.7;
|
|
1998
|
+
ctx2d.beginPath();
|
|
1999
|
+
ctx2d.arc(screen.x, screen.y, 2.5, 0, Math.PI * 2);
|
|
2000
|
+
ctx2d.fill();
|
|
2001
|
+
ctx2d.fillStyle = theme.textColor;
|
|
2002
|
+
ctx2d.globalAlpha = 0.85;
|
|
2003
|
+
ctx2d.textAlign = "left";
|
|
2004
|
+
ctx2d.fillText(sp.label, screen.x + 8, screen.y);
|
|
2005
|
+
}
|
|
2006
|
+
if (seriesInfo.length > 1) {
|
|
2007
|
+
const lx = 12, ly = height - 14 - seriesInfo.length * 18;
|
|
2008
|
+
ctx2d.fillStyle = "rgba(0,0,0,0.45)";
|
|
2009
|
+
ctx2d.globalAlpha = 1;
|
|
2010
|
+
ctx2d.beginPath();
|
|
2011
|
+
ctx2d.roundRect(lx - 6, ly - 8, 120, seriesInfo.length * 18 + 12, 6);
|
|
2012
|
+
ctx2d.fill();
|
|
2013
|
+
ctx2d.textAlign = "left";
|
|
2014
|
+
ctx2d.textBaseline = "top";
|
|
2015
|
+
ctx2d.font = `${theme.fontSize - 1}px ${theme.fontFamily}`;
|
|
2016
|
+
for (let i = 0; i < seriesInfo.length; i++) {
|
|
2017
|
+
const s = seriesInfo[i];
|
|
2018
|
+
const y = ly + i * 18;
|
|
2019
|
+
ctx2d.fillStyle = s.color;
|
|
2020
|
+
ctx2d.globalAlpha = 0.9;
|
|
2021
|
+
ctx2d.beginPath();
|
|
2022
|
+
ctx2d.arc(lx + 4, y + 6, 4, 0, Math.PI * 2);
|
|
2023
|
+
ctx2d.fill();
|
|
2024
|
+
ctx2d.fillStyle = "rgba(255,255,255,0.8)";
|
|
2025
|
+
ctx2d.fillText(s.name, lx + 14, y);
|
|
2026
|
+
}
|
|
1927
2027
|
}
|
|
2028
|
+
ctx2d.restore();
|
|
1928
2029
|
},
|
|
1929
2030
|
needsLoop() {
|
|
1930
2031
|
return false;
|
|
@@ -1932,14 +2033,26 @@ function createGlobe3DPlugin() {
|
|
|
1932
2033
|
hitTest(ctx, x, y) {
|
|
1933
2034
|
const { camera, width, height } = ctx;
|
|
1934
2035
|
let closest = null;
|
|
1935
|
-
let closestDist =
|
|
1936
|
-
for (const
|
|
1937
|
-
const screen = projectToScreen(
|
|
2036
|
+
let closestDist = 25;
|
|
2037
|
+
for (const sp of screenPoints) {
|
|
2038
|
+
const screen = projectToScreen(
|
|
2039
|
+
new Float32Array([sp.wx, sp.wy, sp.wz]),
|
|
2040
|
+
camera.projViewMatrix,
|
|
2041
|
+
width,
|
|
2042
|
+
height
|
|
2043
|
+
);
|
|
1938
2044
|
if (!screen || screen.z < -1 || screen.z > 1) continue;
|
|
1939
2045
|
const dist = Math.sqrt((screen.x - x) ** 2 + (screen.y - y) ** 2);
|
|
1940
2046
|
if (dist < closestDist) {
|
|
1941
2047
|
closestDist = dist;
|
|
1942
|
-
closest = {
|
|
2048
|
+
closest = {
|
|
2049
|
+
seriesIndex: sp.si,
|
|
2050
|
+
dataIndex: sp.di,
|
|
2051
|
+
value: sp.value,
|
|
2052
|
+
x: sp.lng,
|
|
2053
|
+
y: sp.lat,
|
|
2054
|
+
seriesName: sp.label || sp.name
|
|
2055
|
+
};
|
|
1943
2056
|
}
|
|
1944
2057
|
}
|
|
1945
2058
|
return closest;
|
|
@@ -1949,9 +2062,7 @@ function createGlobe3DPlugin() {
|
|
|
1949
2062
|
sphereVBO = null;
|
|
1950
2063
|
sphereIBO?.destroy();
|
|
1951
2064
|
sphereIBO = null;
|
|
1952
|
-
|
|
1953
|
-
pointVBO = null;
|
|
1954
|
-
globePoints = [];
|
|
2065
|
+
screenPoints = [];
|
|
1955
2066
|
}
|
|
1956
2067
|
};
|
|
1957
2068
|
}
|
|
@@ -3460,5 +3571,5 @@ function GraphGL(container, opts) {
|
|
|
3460
3571
|
}
|
|
3461
3572
|
|
|
3462
3573
|
export { Bar3D, DEFAULT_GL_THEME, FlowGL, Globe3D, GraphGL, LIGHT_GL_THEME, Line3D, Lines3D, LinesGL, Map3D, Scatter3D, ScatterGL, Surface3D, applyVertexLayout, compileShader, createBar3DPlugin, createCamera, createFlowGLPlugin, createGLChart, createGLRenderer, createGlobe3DPlugin, createGraphGLPlugin, createGrid3D, createIndexBuffer, createLine3DPlugin, createLines3DPlugin, createLinesGLPlugin, createMap3DPlugin, createOrbitControls, createPickingSystem, createScatter3DPlugin, createScatterGLPlugin, createShaderProgram, createSurface3DPlugin, createVertexBuffer, createVertexLayout, defaultLightConfig, hexToRGB, mat4, mat4Identity, mat4Invert, mat4LookAt, mat4Multiply, mat4Perspective, projectToScreen, resolveTheme, setLightUniforms, toRad, updateCamera, updateOrbitControls, vec3 };
|
|
3463
|
-
//# sourceMappingURL=chunk-
|
|
3464
|
-
//# sourceMappingURL=chunk-
|
|
3574
|
+
//# sourceMappingURL=chunk-XGQDO4VO.js.map
|
|
3575
|
+
//# sourceMappingURL=chunk-XGQDO4VO.js.map
|