storybook/stories/interactions/17_png_export.story.tsx (132 lines of code) (raw):
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { button, select } from '@storybook/addon-knobs';
import React from 'react';
import type { Datum, BandFillColorAccessorInput } from '@elastic/charts';
import {
Axis,
BarSeries,
Chart,
niceTimeFormatter,
Position,
ScaleType,
Settings,
Partition,
Goal,
ChartType,
defaultPartitionValueFormatter,
LegendValue,
} from '@elastic/charts';
import { GoalSubtype } from '@elastic/charts/src/chart_types/goal_chart/specs/constants';
import { mocks } from '@elastic/charts/src/mocks/hierarchical';
import { KIBANA_METRICS } from '@elastic/charts/src/utils/data_samples/test_dataset_kibana';
import type { ChartsStory } from '../../types';
import { useBaseTheme } from '../../use_base_theme';
import { productLookup, indexInterpolatedFillColor, interpolatorCET2s, getBandFillColorFn } from '../utils/utils';
export const Example: ChartsStory = (_, { title, description }) => {
/**
* The handler section of this story demonstrates the PNG export functionality
*/
const chartRef = React.useRef<Chart>(null);
const handler = () => {
if (!chartRef.current) {
return;
}
const snapshot = chartRef.current.getPNGSnapshot({
// you can set the background and pixel ratio for the PNG export
backgroundColor: 'white',
});
if (!snapshot) {
return;
}
// will save as chart.png
const fileName = 'chart.png';
const link = document.createElement('a');
link.download = fileName;
link.href = snapshot.blobOrDataUrl;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
button('Export PNG', handler);
const selectedChart = select('chart type', [ChartType.XYAxis, ChartType.Partition, ChartType.Goal], ChartType.XYAxis);
return (
<Chart title={title} description={description} ref={chartRef}>
<Settings
baseTheme={useBaseTheme()}
showLegend={selectedChart === ChartType.XYAxis}
legendValues={selectedChart === ChartType.XYAxis ? [LegendValue.CurrentAndLastValue] : []}
/>
{selectedChart === ChartType.Partition
? renderPartitionChart()
: selectedChart === ChartType.Goal
? renderGoalchart()
: renderXYAxisChart()}
</Chart>
);
};
function renderPartitionChart() {
return (
<Partition
id="spec_1"
data={mocks.pie}
valueAccessor={(d: Datum) => d.exportVal as number}
valueFormatter={(d: number) => `$${defaultPartitionValueFormatter(Math.round(d / 1000000000))}\u00A0Bn`}
layers={[
{
groupByRollup: (d: Datum) => d.sitc1,
nodeLabel: (d: Datum) => productLookup[d].name,
shape: {
fillColor: (key, sortIndex, node, tree) =>
indexInterpolatedFillColor(interpolatorCET2s())(null, sortIndex, tree),
},
},
]}
/>
);
}
function renderXYAxisChart() {
const data = KIBANA_METRICS.metrics.kibana_os_load.v1.data.slice(0, 100);
return (
<>
<Axis
id="time"
position={Position.Bottom}
tickFormat={niceTimeFormatter([data[0][0], data[data.length - 1][0]])}
/>
<Axis
id="count"
domain={{
min: NaN,
max: NaN,
fit: true,
}}
position={Position.Left}
/>
<BarSeries
id="series bars chart"
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
xAccessor={0}
yAccessors={[1]}
data={data}
/>
</>
);
}
function renderGoalchart() {
const subtype = GoalSubtype.Goal;
const getBandFillColor = getBandFillColorFn({
200: '#fc8d62',
250: 'lightgrey',
300: '#66c2a5',
});
return (
<Goal
id="spec_1"
subtype={subtype}
base={0}
target={260}
actual={280}
domain={{ min: 0, max: 300 }}
bands={[200, 250, 300]}
ticks={[0, 50, 100, 150, 200, 250, 300]}
tickValueFormatter={({ value }: BandFillColorAccessorInput) => String(value)}
bandFillColor={getBandFillColor}
labelMajor=""
labelMinor=""
centralMajor="280 MB/s"
centralMinor=""
angleStart={Math.PI + (Math.PI - (2 * Math.PI) / 3) / 2}
angleEnd={-(Math.PI - (2 * Math.PI) / 3) / 2}
/>
);
}
Example.parameters = {
markdown:
'Generate a PNG of the chart by clicking on the Export PNG button in the knobs section. In this Example, the button handler is setting the PNG background to white with a pixel ratio of 2. If the browser is detected to be IE11, msSaveBlob will be used instead of a PNG capture.',
};