我在react中工作,并使用highcharts和react-grid-layout来调整div中元素的大小。不知何故,可调整大小的功能适用于图像,但不适用于highchart。Grid.js是一个生成ResponsiveReactGridLayout的文件,它从chart.js文件中获取高值图表。请找到下面的代码。
//Grid.js
import React, { Component } from 'react';
import {Responsive, WidthProvider,ReactGridLayout} from 'react-grid-layout';
import Charts from './charts.js';
const ResponsiveReactGridLayout = WidthProvider(Responsive);
class Grid extends Component {
onLayoutChange(layout) {
console.log(layout);
}
render(){
return (<div style={{borderStyle: 'groove'}}>
<h2> Panel Header </h2>
<ResponsiveReactGridLayout className="layout"
breakpoints={{lg: 1200, md: 96, sm: 768}}
cols={{lg: 5, md: 10, sm: 6}}
onLayoutChange={this.onLayoutChange}>
<div key="c" data-grid={{x: 0, y: 0, w: 1, h: 3}} style={{ border:'1px solid green', borderStyle: 'groove'}}>
<img src="https://cdn.geckoandfly.com/wp-content/uploads/2013/03/530-smiley-face.jpg" style={{width:'inherit', height:'inherit'}} />
</div>
<div key="d" className = 'react-grid-item react-resizable'
data-grid={{x: 1, y: 0, w: 1, h: 3}} style={{ border:'1px solid green', borderStyle: 'groove'}}
>
<Charts style={{width:'inherit'}} id={'Chart 1'}/>
</div>
<div key="e" data-grid={{x: 2, y: 0, w: 1, h: 3}} style={{ border:'1px solid green',borderStyle: 'groove'}}>
<Charts style={{width:'inherit'}} id={'Chart 2'}/>
</div>
<div key="f" data-grid={{x: 3, y: 0, w: 1, h: 3}} style={{ border:'1px solid green',borderStyle: 'groove'}}>
<Charts style={{width:'inherit'}} id={'Chart 3'}/>
</div>
</ResponsiveReactGridLayout>
</div>
)
}
}
export default (Grid);
//Charts.js
import React, { Component } from 'react';
const Highcharts = require('highcharts');
class Charts extends Component{
constructor(props){
super(props);
this.state = {
data : {
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 295.6, 454.4]
}]
},
pieData: [{name: "Firefox",y: 6},{name: "MSIE",y: 4},{name: "Safari",y: 4},{name: "Opera",y: 1},{name: "Chrome",y: 7}]
};
}
/**
* Inject highcharts markup into the DOM after the rest of the component has mounted
* @return {None}
*/
componentDidMount() {
// Load in any highcharts modules
if (this.props.modules) {
this.props.module.forEach((module) => {
module(Highcharts);
});
}
// Create the actual chart and assign reference
const props = this.processPropsModel(this.props);
const containerRef = `container${props.id}`;
this.chart = new Highcharts.chart(
containerRef,
props.options
);
}
processPropsModel(props) {
const newProps = {};
newProps.id = this.props.id;
newProps.options = this.generateDefaultOptions();
return newProps;
}
/**
* Generating some default chart options for placeholding purposes
* @return {Object} The options to be passed into the chart
*/
generateDefaultOptions() {
return {
title: {
text: this.props.id,
x: -20 //center
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
title: {
text: null
}
},
tooltip: {
valueSuffix: '°C'
},
series: [{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}]
};
}
render(){
const props = this.processPropsModel(this.props);
return (
<div id={`container${props.id}`}>
</div>
);
}
}
export default Charts;发布于 2019-01-26 03:18:15
所以,我使用highcharts-react-official和react-grid-layout解决了同样的问题。
这就是我最终让它工作的原因。
tl;dr
下面是我的响应式网格布局,只是为了给出一些上下文。
// Component/Grid/Grid.js
<ResponsiveGridLayout
...
>
{this.state.widgets.map((widget) =>
<Card key={widget.DWG_ID}>
<Widget
widget={widget}
/>
</Card>
)}
</ResponsiveGridLayout>现在,在Widget组件中,将任何div的高度设置为100%,该div将成为highchart的父级。
// Component/Widget/Widget.js
<CardBody className="widgetContent">
<CardTitle className="widget-title">{this.props.widget.DWG_LABEL}</CardTitle>
<Chart
widget={this.props.widget}
/>}
</CardBody> 对于上面的jsx,我只需要对类为widgetContent的元素CardBody执行此操作,因此
// Component/Widget/Widget.css
.widgetContent { height: 100%; }现在,在图表组件(所有有趣的地方)中,我必须创建一个非常难看的div,以便能够识别highcharts创建的最外层的div。
elements created by highcharts
在上图中可以看到有问题的臭名昭著的div,就在带有类highchartsWrapper的div下面,带有属性data-highcharts-chart。这个div是我的图表中唯一一个我不能直接识别给出100%高度的父图表。因此,我创建了包装器,以便能够明确地识别它。请注意,在图表选项中,我们还传递了一个类名,以便能够为图表本身提供css height属性。
如果有人对如何识别这个有问题的div有更好的想法,请让我知道。
// Component/Chart/Chart.js
options = {
...
chart: { className: 'chart' }
}
<div className="highchartsWrapper">
<HighchartsReact
highcharts={Highcharts}
options={options}
callback={(chart) => this.setChart(chart)}
/>
</div>所以我可以给它一个css
// Component/Chart/Chart.css
.highchartsWrapper > div {
height: 100%;
}
.chart {
height: 100%;
}现在,理想情况下,您的高线图将假定正确的宽度和高度。但还有另一个复杂的问题:当highchart第一次渲染并检查他父母的高度时,react-grid-layout还没有完成他的大小调整魔法。这意味着你的图表会很小。此外,当您调整网格项目的大小时,您希望highchart调整为其新的父级大小。等等,我以前用过highcharts,我知道怎么做!很好的老chart.reflow()!不幸的是,这并不是那么容易。
首先,仅仅获取可以调用回流的图表对象并不是很简单。如果你注意到了,我回调了我的HighchartsReact
(chart) => this.setChart(chart)这只是为了将图表对象存储为我的类组件的属性。我的setChart函数只执行以下操作:
setChart(chart) {
this.chart = chart;
}这样做可能看起来很愚蠢。为什么不直接将setChart传递给HighchartsReact的回调属性呢?嗯,因为如果你这样做了,根据highcharts-react-官方文档,你在setChart函数中的这将是你的图表对象……所有这些都非常令人困惑,但它似乎是这样工作的。
同样,如果有人有更好的解决方案,请让我知道
最后,我们可以在更新图表组件时调用this.chart.reflow()。我所做的是这样的
constructor() {
super(props)
this.firstResize = true;
}
componentDidUpdate(prevProps) {
if (this.didWidgetSizeChange(prevProps) || this.isFirstResize) {
this.chart.reflow();
this.isFirstResize = false;
}
}当组件更新时,我们调用图表回流。在componentDidMount上,网格项还没有他的最终大小,所以我使用了一个标志来计算第一次更新(也就是说:网格项已经完成了第一次大小调整)。然后,对于任何其他更新,我编写了一个函数,基本上将此网格项目的以前布局与新布局进行比较,以确定大小或宽度是否发生了变化。如果是这样,我们再次回流以调整highcharts的大小以适应新的网格项大小。
希望这能有所帮助!
安息吧!
发布于 2019-08-05 20:46:02
以下是使其适合网格的示例解决方案……
import React from 'react';
import './App.css';
import '/node_modules/react-grid-layout/css/styles.css';
import '/node_modules/react-resizable/css/styles.css';
import GridLayout from 'react-grid-layout';
import Highcharts from "highcharts/highstock";
import HighchartsReact from "highcharts-react-official";
const options = {
series: [
{
data: [1, 2, 3]
}
]
};
class MyFirstGrid extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.conRef = React.createRef();
}
render() {
// layout is an array of objects, see the demo for more complete usage
var layout = [
{ i: "a", x: 0, y: 0, w: 5, h: 5 },
{ i: "b", x: 1, y: 0, w: 3, h: 2 },
{ i: "c", x: 4, y: 0, w: 1, h: 2 }
];
return (
<GridLayout
className="layout"
layout={layout}
cols={12}
rowHeight={30}
width={1200}
onResizeStop={function(event) {
this.myRef.current.chart.setSize(this.conRef.current.clientWidth,this.conRef.current.clientHeight)
console.log('hello', event);
}.bind(this)}
>
<div ref={this.conRef} style={{ backgroundColor: "#00000000" }} key="a">
<HighchartsReact
ref= {this.myRef}
containerProps={{ style: { width: '100%', height: '100%' } }}
options={options}
highcharts={Highcharts}
/>
</div>
<div style={{ backgroundColor: "red" }} key="b">
b
</div>
<div style={{ backgroundColor: "blue" }} key="c">
c
</div>
</GridLayout>
);
}
}
export default MyFirstGrid;发布于 2021-03-12 10:47:10
我认为调整高分辨率的功能不起作用的原因可以从the documentation of 'reflow' from hightcharts中找到
默认情况下,图表会根据the chart.reflow option在a window.resize event之后自动重排到其容器。但是,div resize没有可靠的事件,因此如果在没有窗口resize事件的情况下调整容器的大小,则必须显式调用此事件。
这种情况与您现在所做的情况相匹配:您试图调整div本身的大小,但没有调整窗口大小,因此它不能按您预期的那样工作。
我做了什么使我的图表在网格中可调整大小,如下所示:
const onLayoutChange = () => {
for (let i = 0; i < Highcharts.charts.length; i += 1) {
if (Highcharts.charts[i] !== undefined) {
Highcharts.charts[i].reflow(); // here is the magic to update charts' looking
}
}
};使用react-grid-layout提供的onLayoutChange的
<GridLayout
cols={12}
layout={layout}
rowHeight={30}
width={1200}
onLayoutChange={() => onLayoutChange()}
>
...
</GridLayout>还有then...BANG!您可以通过react-grid-layout中的调整大小按钮来控制可调整大小的图表。
为了便于理解,您可以在此处查看我的游乐场:https://codesandbox.io/s/resize-highcharts-in-grid-9e625?file=/src/App.js
https://stackoverflow.com/questions/40430415
复制相似问题