Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions docs/data/charts/scatter/ScatterWebGLRenderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as React from 'react';
import { ScatterChartPremium } from '@mui/x-charts-premium/ScatterChartPremium';

const POINTS_PER_SERIES = 200_000;

// Inline mulberry32 — deterministic, ~20x faster than `chance.floating`.
// 800k calls during module load with Chance takes several seconds and stalls
// the Next.js build; this runs in ~50ms.
/* eslint-disable no-bitwise */
function makeRandom(seed) {
let state = seed;
return () => {
state = (state + 0x6d2b79f5) | 0;
let t = state;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296;
};
}
/* eslint-enable no-bitwise */

function generateSeries(offset, spread, seed) {
const rand = makeRandom(seed);
const data = new Array(POINTS_PER_SERIES);
for (let i = 0; i < POINTS_PER_SERIES; i += 1) {
const u1 = Math.max(rand(), 1e-6);
const u2 = rand();
const r = Math.sqrt(-2 * Math.log(u1));
const theta = 2 * Math.PI * u2;
data[i] = {
id: i,
x: offset + r * Math.cos(theta) * spread,
y: offset + r * Math.sin(theta) * spread,
};
}
return data;
}

const DATA_1 = generateSeries(0, 1, 42);
const DATA_2 = generateSeries(4, 1.5, 7);

export default function ScatterWebGLRenderer() {
const series = React.useMemo(
() => [
{ label: 'Cluster A', data: DATA_1, markerSize: 1 },
{ label: 'Cluster B', data: DATA_2, markerSize: 1 },
],
[],
);

return (
<ScatterChartPremium
series={series}
xAxis={[{ min: -6, max: 12, zoom: true }]}
yAxis={[{ min: -6, max: 12, zoom: true }]}
height={400}
renderer="webgl"
slotProps={{
legend: {
toggleVisibilityOnClick: true,
},
}}
/>
);
}
65 changes: 65 additions & 0 deletions docs/data/charts/scatter/ScatterWebGLRenderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as React from 'react';
import { ScatterChartPremium } from '@mui/x-charts-premium/ScatterChartPremium';

const POINTS_PER_SERIES = 200_000;

// Inline mulberry32 — deterministic, ~20x faster than `chance.floating`.
// 800k calls during module load with Chance takes several seconds and stalls
// the Next.js build; this runs in ~50ms.
/* eslint-disable no-bitwise */
function makeRandom(seed: number) {
let state = seed;
return () => {
state = (state + 0x6d2b79f5) | 0;
let t = state;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296;
};
}
/* eslint-enable no-bitwise */

function generateSeries(offset: number, spread: number, seed: number) {
const rand = makeRandom(seed);
const data = new Array(POINTS_PER_SERIES);
for (let i = 0; i < POINTS_PER_SERIES; i += 1) {
const u1 = Math.max(rand(), 1e-6);
const u2 = rand();
const r = Math.sqrt(-2 * Math.log(u1));
const theta = 2 * Math.PI * u2;
data[i] = {
id: i,
x: offset + r * Math.cos(theta) * spread,
y: offset + r * Math.sin(theta) * spread,
};
}
return data;
}

const DATA_1 = generateSeries(0, 1, 42);
const DATA_2 = generateSeries(4, 1.5, 7);

export default function ScatterWebGLRenderer() {
const series = React.useMemo(
() => [
{ label: 'Cluster A', data: DATA_1, markerSize: 1 },
{ label: 'Cluster B', data: DATA_2, markerSize: 1 },
],
[],
);

return (
<ScatterChartPremium
series={series}
xAxis={[{ min: -6, max: 12, zoom: true }]}
yAxis={[{ min: -6, max: 12, zoom: true }]}
height={400}
renderer="webgl"
slotProps={{
legend: {
toggleVisibilityOnClick: true,
},
}}
/>
);
}
12 changes: 12 additions & 0 deletions docs/data/charts/scatter/ScatterWebGLRenderer.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<ScatterChartPremium
series={series}
xAxis={[{ min: -6, max: 12, zoom: true }]}
yAxis={[{ min: -6, max: 12, zoom: true }]}
height={400}
renderer="webgl"
slotProps={{
legend: {
toggleVisibilityOnClick: true,
},
}}
/>
11 changes: 10 additions & 1 deletion docs/data/charts/scatter/scatter.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: React Scatter chart
productId: x-charts
components: ScatterChart, ScatterChartPro, ScatterPlot, ChartsGrid, ChartsWrapper
components: ScatterChart, ScatterChartPro, ScatterChartPremium, ScatterPlot, ScatterPlotPremium, HighlightedScatterMark, ChartsGrid, ChartsWrapper
---

# Charts - Scatter
Expand Down Expand Up @@ -176,6 +176,15 @@ The example below uses the `renderer` prop to render 16,000 points with better p

{{"demo": "ScatterBatchRenderer.js"}}

### WebGL renderer [<span class="plan-premium"></span>](/x/introduction/licensing/#premium-plan 'Premium plan')

For very large datasets, `ScatterChartPremium` supports a `webgl` renderer that draws points into a dedicated WebGL canvas layered behind the SVG.
This bypasses per-point SVG entirely and trades item-level interactivity for throughput.

The example below renders 200,000 points.

{{"demo": "ScatterWebGLRenderer.js"}}

## Composition

Use `ChartsDataProvider` to supply `series`, `xAxis`, and `yAxis` when composing a custom chart.
Expand Down
15 changes: 15 additions & 0 deletions docs/data/chartsApiPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ const chartsApiPages: MuiPage[] = [
title: 'HeatmapTooltipContent',
plan: 'pro',
},
{
pathname: '/x/api/charts/highlighted-scatter-mark',
title: 'HighlightedScatterMark',
plan: 'premium',
},
{
pathname: '/x/api/charts/line-chart',
title: 'LineChart',
Expand Down Expand Up @@ -434,6 +439,11 @@ const chartsApiPages: MuiPage[] = [
pathname: '/x/api/charts/scatter-chart',
title: 'ScatterChart',
},
{
pathname: '/x/api/charts/scatter-chart-premium',
title: 'ScatterChartPremium',
plan: 'premium',
},
{
pathname: '/x/api/charts/scatter-chart-pro',
title: 'ScatterChartPro',
Expand All @@ -443,6 +453,11 @@ const chartsApiPages: MuiPage[] = [
pathname: '/x/api/charts/scatter-plot',
title: 'ScatterPlot',
},
{
pathname: '/x/api/charts/scatter-plot-premium',
title: 'ScatterPlotPremium',
plan: 'premium',
},
{
pathname: '/x/api/charts/spark-line-chart',
title: 'SparkLineChart',
Expand Down
20 changes: 20 additions & 0 deletions docs/pages/x/api/charts/highlighted-scatter-mark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import { ApiPage } from '@mui/internal-core-docs/ApiPage';
import { mapApiPageTranslations } from '@mui/internal-core-docs/mapApiPageTranslations';
import jsonPageContent from './highlighted-scatter-mark.json';

export default function Page(props) {
const { descriptions } = props;
return <ApiPage descriptions={descriptions} pageContent={jsonPageContent} />;
}

export async function getStaticProps() {
const req = require.context(
'docs/translations/api-docs/charts/highlighted-scatter-mark',
false,
/\.\/highlighted-scatter-mark.*\.json$/,
);
const descriptions = mapApiPageTranslations(req);

return { props: { descriptions } };
}
14 changes: 14 additions & 0 deletions docs/pages/x/api/charts/highlighted-scatter-mark.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"props": {},
"name": "HighlightedScatterMark",
"imports": [
"import { HighlightedScatterMark } from '@mui/x-charts-premium/ScatterChartPremium';",
"import { HighlightedScatterMark } from '@mui/x-charts-premium';"
],
"classes": [],
"muiName": "MuiHighlightedScatterMark",
"filename": "/packages/x-charts-premium/src/ScatterChartPremium/HighlightedScatterMark.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/x/react-charts/scatter/\">Charts - Scatter</a></li></ul>",
"cssComponent": false
}
20 changes: 20 additions & 0 deletions docs/pages/x/api/charts/scatter-chart-premium.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import { ApiPage } from '@mui/internal-core-docs/ApiPage';
import { mapApiPageTranslations } from '@mui/internal-core-docs/mapApiPageTranslations';
import jsonPageContent from './scatter-chart-premium.json';

export default function Page(props) {
const { descriptions } = props;
return <ApiPage descriptions={descriptions} pageContent={jsonPageContent} />;
}

export async function getStaticProps() {
const req = require.context(
'docs/translations/api-docs/charts/scatter-chart-premium',
false,
/\.\/scatter-chart-premium.*\.json$/,
);
const descriptions = mapApiPageTranslations(req);

return { props: { descriptions } };
}
Loading
Loading