如何在Highcharts官方React封装的图表内渲染DatePicker组件
实现方案
核心逻辑是利用Highcharts的渲染接口在图表内部生成自定义DOM容器,再通过React Portal将DatePicker组件挂载到该容器中,完全支持函数式组件实现,修改后的代码如下:
首先需要从react中引入createPortalAPI,新增两个ref分别保存Highcharts实例、DatePicker挂载容器,完整可运行代码:
import { useState, useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import Highcharts from 'highcharts/highstock'; import HighchartsReact from 'highcharts-react-official'; import DatePicker from 'react-datepicker'; import "react-datepicker/dist/react-datepicker.css"; function Graph(props) { const [startDate, setStartDate] = useState(new Date('1969-11-19 PST')); const [bx, setBx] = useState([]); const [by, setBy] = useState([]); const [bz, setBz] = useState([]); // 新增ref存储图表实例和日期选择器挂载容器 const chartRef = useRef(null); const datePickerContainer = useRef(document.createElement('div')); async function getData(table, year, month, day) { // 原有数据请求逻辑保持不变 } useEffect(() => { // 原有监听startDate拉取数据的逻辑保持不变 }, [startDate]) // 新增:更新日期选择器在图表内的位置 const updateDatePickerPos = (chart) => { // 可自定义偏移数值调整位置,当前默认放在图表左上角 datePickerContainer.current.style.position = 'absolute'; datePickerContainer.current.style.left = `${chart.plotLeft + 10}px`; datePickerContainer.current.style.top = `${chart.plotTop + 10}px`; datePickerContainer.current.style.zIndex = '999'; // 确保不被图表SVG层遮挡 chart.container.appendChild(datePickerContainer.current); } const options = { chart: { events: { load: function() { this.showLoading(); setTimeout(this.hideLoading.bind(this), 2000); updateDatePickerPos(this); }, redraw: function() { // 图表缩放、重绘时同步更新日期选择器位置 updateDatePickerPos(this); } }, zoomType: 'x' }, lang: { noData: "Awaiting for data" }, rangeSelector: { inputEnabled: false, buttons: [ { type: 'all', text: '1d', title: 'View 1 Day' }, { type: 'minute', count: 10, text: '10m', title: 'View 10 minutes' }, { type: 'minute', count: 1, text: '1m', title: 'View 1 minutes' }, { type: 'second', count: 30, text: '30s', title: 'View 30 seconds' }, ] }, title: { text: props.title }, xAxis: { type: 'datetime' }, time: { timezoneOffset: 8*60 }, series: [ { marker: { enabled: true, radius: 2 }, color: 'red', name: 'Bx', pointStart: startDate.getTime(), pointInterval: 1000, data: bx }, { marker: { enabled: true, radius: 2 }, color: 'blue', name: 'By', pointStart: startDate.getTime(), pointInterval: 1000, data: by }, { marker: { enabled: true, radius: 2 }, color: 'green', name: 'Bz', pointStart: startDate.getTime(), pointInterval: 1000, data: bz } ] } const isValidDate = (date) => { date.getTime(); const origDate = new Date('1969-11-19 PST'); const finalDate = new Date('1970-04-03 PST'); console.log("GET DATE", date.getTime()) return origDate.getTime() <= date.getTime() && date.getTime() <= finalDate.getTime(); } return ( <React.Fragment> <HighchartsReact highcharts={Highcharts} constructorType={'stockChart'} options={options} ref={chartRef} /> {/* 通过Portal将DatePicker挂载到图表内部容器 */} {createPortal( <DatePicker selected={startDate} filterDate={isValidDate} onChange={(date) => setStartDate(date)} />, datePickerContainer.current )} </React.Fragment> ); }
注意事项
- 可自行调整
updateDatePickerPos方法中的left、top数值,修改DatePicker在图表内的摆放位置 - 如果DatePicker的下拉弹窗被图表容器截断,可给图表外层容器添加
overflow: visible样式 - 可在组件卸载的useEffect回调中手动移除datePickerContainer节点,避免内存泄漏
内容的提问来源于stack exchange,提问作者matthewcy
相关产品推荐
相关产品推荐

