React中Chart.js实现带X轴硬边界的可滑动视口问题
React + Chart.js 实现固定宽度X轴的可平移视口问题
问题描述
需要在React中用Chart.js实现固定宽度(如8小时)的可左右平移图表视口,并为X轴设置硬最小/最大边界:红色框为用户可见区域,左侧“1500”是视口左边界,框外“0400”是数据的最右边界。当前图表始终显示全量数据,无法实现平移功能。
现有代码
import moment from "moment"; import Chart from "chart.js/auto"; import { Bar } from "react-chartjs-2"; import zoomPlugin from 'chartjs-plugin-zoom'; import annotationPlugin from 'chartjs-plugin-annotation'; import 'chartjs-adapter-moment'; Chart.register(annotationPlugin,zoomPlugin); const r = document.querySelector(':root'); const rs = getComputedStyle(r); const data = { datasets: [ { type: 'bar', data: [], //value - set through programming order: 1 }, { type: 'bar', data: [], order: 1 }, { type: 'bar', data: [], order: 1 }, { type: 'bar', data: [], order: 1 }, { data: [], type: 'line', order: 0, steppedLine: true, stepped: 'before' }, { label: "Current Time", //needed for legend type: 'line' } ] }; const options = { plugins: { legend: { position: 'bottom', }, annotation:{ annotations: [{ type: 'line', borderColor: rs.getPropertyValue('--CURRENT_TIMELINE'), borderWidth: 2, mode: 'vertical', xMin: moment().subtract(30, "m").valueOf(), xMax: moment().subtract(30, "m").valueOf() }] } }, zoom: { pan: { enabled: true } }, elements: { point:{ radius: 0 } }, scales: { x: { stacked: true, display: true, offset: false, title: { display: false, text: 'Time' }, type: 'time', time: { unit: 'hour', displayFormats: { 'minute': 'HHmm', 'hour': 'HHmm', } }, ticks: { // forces step size to be 50 units stepSize: 1 } }, y: { stacked: true, min: 0, title: { display: true, text: 'My title' } } } }; class myChart extends React.Component { constructor(props) { super(props); this.state = { data: data, options: options } } render() { return ( <div className="chart" id="chart"> <Bar data={this.state.data} options={this.state.options}/> </div> ); } } export default myChart;
解决方案
1. 配置X轴初始可见范围与硬边界
在scales.x中添加初始的min和max,固定视口宽度(比如8小时);同时设置数据的硬边界,限制平移范围:
scales: { x: { // ...原有配置 type: 'time', // 初始视口:显示最近8小时的数据 min: moment().subtract(8, 'hour').valueOf(), max: moment().valueOf(), // 数据硬边界(根据实际数据起止时间调整) suggestedMin: moment('0400', 'HHmm').valueOf(), suggestedMax: moment('1500', 'HHmm').valueOf(), // ...其他配置 } }
2. 完善Zoom插件的平移配置
在zoom.pan中限制仅X轴平移,并设置平移的硬边界:
zoom: { pan: { enabled: true, // 仅允许X轴平移 mode: 'x', // 设置平移的硬边界,与X轴的suggestedMin/suggestedMax对应 limits: { x: { min: moment('0400', 'HHmm').valueOf(), max: moment('1500', 'HHmm').valueOf() } } } }
3. 动态数据适配(可选)
如果数据是动态加载的,需在更新数据时同步修改X轴的min/max和平移limits,确保边界与实际数据匹配。
修改后的完整关键配置示例
const options = { plugins: { legend: { position: 'bottom', }, annotation:{ annotations: [{ type: 'line', borderColor: rs.getPropertyValue('--CURRENT_TIMELINE'), borderWidth: 2, mode: 'vertical', xMin: moment().subtract(30, "m").valueOf(), xMax: moment().subtract(30, "m").valueOf() }] } }, zoom: { pan: { enabled: true, mode: 'x', limits: { x: { min: moment('0400', 'HHmm').valueOf(), max: moment('1500', 'HHmm').valueOf() } } } }, elements: { point:{ radius: 0 } }, scales: { x: { stacked: true, display: true, offset: false, title: { display: false, text: 'Time' }, type: 'time', time: { unit: 'hour', displayFormats: { 'minute': 'HHmm', 'hour': 'HHmm', } }, ticks: { stepSize: 1 }, // 初始固定8小时视口 min: moment().subtract(8, 'hour').valueOf(), max: moment().valueOf(), // 数据硬边界 suggestedMin: moment('0400', 'HHmm').valueOf(), suggestedMax: moment('1500', 'HHmm').valueOf() }, y: { stacked: true, min: 0, title: { display: true, text: 'My title' } } } };
内容的提问来源于stack exchange,提问作者squidmonkey
相关产品推荐
相关产品推荐

