I see in the documentation that I need to set the boolean to true/false. But my question is how do I do this after the series has been rendered? I am using a custom legend and need to be able to toggle visibility.
export default function Chart() {
const [sciChartSurface, setSciChartSurface] = React.useState<SciChartSurface>();
const [wasmContext, setWasmContext] = React.useState<TSciChart>();
const dataSeriesMapRef = React.useRef<Map<keyof typeof chartData, XyDataSeries>>();
React.useEffect(() => {
(async () => {
const { sciChartSurface, wasmContext } = await drawChart(theme, chartType);
setSciChartSurface(sciChartSurface);
setWasmContext(wasmContext);
})();
dataSeriesMapRef.current = new Map<keyof typeof chartData, XyDataSeries>();
return () => sciChartSurface?.delete();
}, [chartType]); // make sure the chart is initialized only once
React.useEffect(() => {
if (dataSeriesMapRef.current && sciChartSurface && wasmContext && !isLoading) {
// const currentSeries = sciChartSurface.renderableSeries.asArray();
// if (currentSeries) sciChartSurface.renderableSeries.clear();
updateChartWithData(dataSeriesMapRef.current, theme, wasmContext, sciChartSurface, chartData, chartType);
}
}, [theme, chartData, wasmContext, sciChartSurface, isLoading]);
return (
<div id="chart-container">
<ControlsLegend
chartData={chartData}
dataSeriesMap={dataSeriesMapRef.current as Map<keyof typeof chartData, XyDataSeries>}
theme={theme}
sciChartSurface={sciChartSurface as SciChartSurface}
wasmContext={wasmContext as TSciChart}
/>
<div id={DIVID} style={{ width: windowWidth, height: windowHeight }} />
<ControlsBottom />
</div>
);
}
drawChart.js
export default async (theme: ExtendedTheme, chartType: string) => {
const { sciChartSurface, wasmContext } = await SciChartSurface.create(DIVID);
const isLightTheme = theme.palette.type === 'light';
console.log('createChart');
const xAxis = new NumericAxis(wasmContext);
const yAxis = new NumericAxis(wasmContext);
xAxis.labelProvider.formatLabel = (unixTimestamp: number) => {
return new Date(unixTimestamp * 1000).toLocaleDateString('en-us', {
month: 'short',
year: 'numeric',
day: 'numeric',
});
};
yAxis.labelProvider = new CustomLabelProvider();
sciChartSurface.yAxes.add(yAxis);
sciChartSurface.xAxes.add(xAxis);
if (chartType !== 'stack') sciChartSurface.chartModifiers.add(new RolloverModifier({ showRolloverLine: false }));
sciChartSurface.chartModifiers.add(new ZoomPanModifier());
sciChartSurface.chartModifiers.add(new ZoomExtentsModifier());
sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
sciChartSurface.chartModifiers.add(new PinchZoomModifier());
const rubberBandXyZoomModifier = new RubberBandXyZoomModifier({
isAnimated: true,
animationDuration: 400,
easingFunction: easing.outExpo,
fill: '#FFFFFF33',
stroke: '#FFFFFF77',
strokeThickness: 1,
});
sciChartSurface.chartModifiers.add(rubberBandXyZoomModifier);
sciChartSurface.zoomExtents();
if (isLightTheme) sciChartSurface.applyTheme(new SciChartJSLightTheme());
else sciChartSurface.applyTheme(new SciChartJSDarkTheme());
return { sciChartSurface, wasmContext };
};
updateChartWithData.js
export const updateChartWithData = (
dataSeriesMap: Map<keyof typeof chartData, XyDataSeries>,
theme: ExtendedTheme,
wasmContext: TSciChart,
sciChartSurface: SciChartSurface,
chartData: ChartData,
chartType: string
) => {
sciChartSurface.invalidateElement();
const streamIds = Object.keys(chartData);
const isLightTheme = theme.palette.type === 'light';
if (isLightTheme) sciChartSurface.applyTheme(new SciChartJSLightTheme());
else sciChartSurface.applyTheme(new SciChartJSDarkTheme());
sciChartSurface.invalidateElement();
console.log('updateChartWithData');
console.log(chartData);
const stackedColumns: any[] = [];
streamIds.forEach((s) => {
const streamId = Number(s) as keyof ChartData;
const streamSelectorId = streamId as keyof typeof chartData;
if (dataSeriesMap.has(streamSelectorId)) {
const xyDataSeries = dataSeriesMap.get(streamSelectorId);
chartData[streamId].data.forEach((value) => {
xyDataSeries?.append(value.timestamp, value.value);
});
} else if (chartType === 'scatter') {
const lineSeries = LineChart(dataSeriesMap, theme, wasmContext, chartData, streamSelectorId, streamId);
sciChartSurface.renderableSeries.add(lineSeries);
sciChartSurface.zoomExtents();
} else if (chartType === 'bar') {
const lineSeries = BarChart(dataSeriesMap, theme, wasmContext, chartData, streamSelectorId, streamId);
sciChartSurface.renderableSeries.add(lineSeries);
sciChartSurface.zoomExtents();
} else {
const lineSeries = StackedChart(dataSeriesMap, theme, wasmContext, chartData, streamSelectorId, streamId);
stackedColumns.push(lineSeries);
}
});
};
“LineChart.js”
export default (
dataSeriesMap: Map<keyof typeof chartData, XyDataSeries>,
theme: ExtendedTheme,
wasmContext: TSciChart,
chartData: ChartData,
streamSelectorId: keyof typeof chartData,
streamId: keyof ChartData
) => {
const xyDataSeries = new XyDataSeries(wasmContext);
dataSeriesMap.set(streamSelectorId, xyDataSeries);
const obj = chartData[streamSelectorId];
const stroke = obj.stroke as string;
xyDataSeries.dataSeriesName = obj.label as string;
chartData[streamId].data.forEach((value) => {
xyDataSeries.append(value.timestamp, value.value);
});
const lineSeries = new FastLineRenderableSeries(wasmContext, {
stroke,
strokeThickness: obj.strokeThickness,
strokeDashArray: obj.strokeDashArray,
dataSeries: xyDataSeries,
animation: new WaveAnimation({ zeroLine: -1, pointDurationFraction: 0.5, duration: 1000 }),
});
lineSeries.rolloverModifierProps.tooltipColor = theme.palette.background.paper;
lineSeries.rolloverModifierProps.tooltipTextColor = theme.palette.getContrastText(stroke);
lineSeries.rolloverModifierProps.markerColor = stroke;
lineSeries.rolloverModifierProps.tooltipTemplate = (
id: string,
tooltipProps: RolloverModifierRenderableSeriesProps,
seriesInfo: SeriesInfo,
updateSize: (width: number, height: number) => void
) => {
const { tooltipColor, tooltipTextColor, markerColor } = tooltipProps;
const { formattedXValue, yValue, seriesName } = seriesInfo;
const width = 192;
const height = 60;
updateSize(width, height);
return `<svg width='${width}' height='${height}' class="root">
<rect width="100%" height="100%" fill='${tooltipColor}' stroke='${markerColor}' stroke-width='2' />
<svg width='100%'>
<text dy="0" fill='${tooltipTextColor}'>
<tspan x="15" y="20" class="title">${formattedXValue}</tspan>
<tspan x="15" y="45" class="value">
${seriesName} | ${yValue.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
</tspan>
</text>
</svg>
</svg>`;
};
return lineSeries;
};
lengend.js
let _chartData: any[] = [];
export default ({
dataSeriesMap,
theme,
wasmContext,
sciChartSurface,
chartData,
}: {
dataSeriesMap: Map<keyof typeof chartData, XyDataSeries>;
theme: ExtendedTheme;
wasmContext: TSciChart;
sciChartSurface: SciChartSurface;
chartData: ChartData;
}) => {
const classes = useStyles();
const chartRef = React.useRef<any>([]);
const [legendData, setLegendData] = React.useState<any[]>([]);
// _chartData = [..._chartData, ...values(chartData)];
_chartData = values(chartData);
_chartData = uniqby(_chartData, 'groupId');
_chartData = uniqby(_chartData, 'streamId');
React.useEffect(() => {
if (_chartData.length > 0 && !isEqual(chartRef.current, _chartData)) {
setLegendData(_chartData);
chartRef.current = _chartData;
}
}, [_chartData]);
const onClick = React.useCallback(
(item) => {
// const xyDataSeries = dataSeriesMap.get(160);
const _legendData = legendData.map((x) => {
if (x.groupId === item.groupId) x.isVisible = !x.isVisible;
return x;
});
setLegendData(_legendData);
},
[legendData]
);
return (
<div className={classes.root}>
<Paper variant="outlined" square>
{legendData.map((item: any) => (
<div className={classes.listItem} key={item.streamId}>
<IconButton
onClick={() => onClick(item)}
style={{ color: item.stroke }}
size="small"
aria-label={item.label}
>
{item.isVisible ? <VisibilityIcon /> : <VisibilityOffIcon />}
</IconButton>
<div>{item.label}</div>
</div>
))}
</Paper>
</div>
);
};
Inside the onClick function is where I was trying to change visibility for both series. I’ve tried multiple things without any luck. I assumed it would be as simple as getting the correct series, setting the visible property and maybe a re-render if that is even needed? Like I said any advice on a better way of handling this is welcome
- Rodolfo Sanchez asked 3 years ago
- last active 3 years ago
Hello,
I want to use user’s settings in my application. I’ve created my own window for settings with checkboxes and colorpickers.
I’ve binded my series with settings like that
<s:SciChartSurface.RenderableSeries>
<s:FastLineRenderableSeries x:Name="tLineSeries1" StrokeDashArray="7 4" StrokeThickness="3" YAxisId="RightAxis" >
<s:FastLineRenderableSeries.IsVisible>
<Binding Source="{x:Static ProjectProperties:Settings.Default}" Path="Visibility1" />
</s:FastLineRenderableSeries.IsVisible>
<s:FastLineRenderableSeries.SeriesColor>
<Binding Source="{x:Static ProjectProperties:Settings.Default}" Path="Color1" />
</s:FastLineRenderableSeries.SeriesColor>
</s:FastLineRenderableSeries>
Everything is working fine and after restarting the application i get the colors and visibility of series as i want.
The problems starts after turning on ShowVisibilityCheckboxes=”true” in LegendModifier. After that, my settings dont work at all. Is there any way how can i bind checkboxes from the legends with my own created checkboxes or settings? In other words, how can i make them both to work “together”?
- Elteros Projektai asked 7 years ago
- last active 7 years ago