Javascript 反应高度图表:在相同和不同图表中共享工具提示
我正在为一个项目使用react highchart。并显示两个图表: 1) 具有2个系列数据的折线图,它将在同一图表上呈现两条线。 2) 条形图或柱状图 现在,当我将鼠标悬停在一个点上时,它应该在第一个图表和柱形图表的两行上都启用工具提示。X轴是日期时间。 它应该在两条线上都有一个激活点,如下所示: 在Javascript 反应高度图表:在相同和不同图表中共享工具提示,javascript,reactjs,charts,highcharts,react-highcharts,Javascript,Reactjs,Charts,Highcharts,React Highcharts,我正在为一个项目使用react highchart。并显示两个图表: 1) 具有2个系列数据的折线图,它将在同一图表上呈现两条线。 2) 条形图或柱状图 现在,当我将鼠标悬停在一个点上时,它应该在第一个图表和柱形图表的两行上都启用工具提示。X轴是日期时间。 它应该在两条线上都有一个激活点,如下所示: 在react highchart中,我使用了shared:true属性,但它并没有使两行都处于活动状态 tooltip: { enabled: true, useHTML: true,
react highchart
中,我使用了shared:true
属性,但它并没有使两行都处于活动状态
tooltip: {
enabled: true,
useHTML: true,
shared: true,
backgroundColor: 'rgba(255,255,255,1)',
borderRadius: 3,
shape: 'rectangle'
}
有没有办法使另一个图表的工具提示也处于活动状态
编辑
在一个建议之后,我检查了highcharts,但是代码示例在jQuery中,我需要它在react highcharts
中。但我仍尝试将代码转换为反应,并执行了以下操作:
import ReactHighcharts from 'react-highcharts/ReactHighcharts';
/**
* Override the reset function, we don't need to hide the tooltips and
* crosshairs.
*/
ReactHighcharts.Highcharts.Pointer.prototype.reset = function reset() {
return undefined;
};
ReactHighcharts.Highcharts.Point.prototype.highlight = function highlight(event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the
crosshair
};
图表渲染回调后:
['mousemove', 'touchmove', 'touchstart'].forEach(eventType => {
const container = document.getElementById('tab__charts');
container.removeEventListener(eventType, this.handleMouseMove);
container.addEventListener(eventType, this.handleMouseMove);
});
处理鼠标移动和同步:
handleMouseMove(e) {
for (let i = 0; i < ReactHighcharts.Highcharts.charts.length; i += 1) {
const chart = ReactHighcharts.Highcharts.charts[i];
if (chart) {
// Find coordinates within the chart
const event = chart.pointer.normalize(e);
// Get the hovered point
const point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
}
}
syncExtremes(e) {
const thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
ReactHighcharts.Highcharts.each(ReactHighcharts.Highcharts.charts, (chart) => {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(
e.min,
e.max,
undefined,
false,
{ trigger: 'syncExtremes' },
);
}
}
});
}
}
这不是最好的方法,但很有效。现在唯一的问题是,第一个图表有两条系列线(查看上图),只有第一个得到活动圆,而不是第二个
编辑3:突出显示多个系列的解决方案。
在阅读代码后,我发现这一行,它只导致第一个系列突出显示点:
point = chart.series[0].searchPoint(event, true)
这条线只拍第一部。错误代码。应该是:
chart.series.forEach(series => {
const point = series.searchPoint(event, true);
if (point) {
try {
point.highlight(e);
} catch (err) {
// pass;
}
}
});
现在唯一的问题是这个try-catch,如果没有得到
就无法读取未定义的属性类别
我建议您使用highcharts-react-official
包装器。下面是同步图表的示例:
import React from "react";
import { render } from "react-dom";
// Import Highcharts
import Highcharts from "highcharts/highstock";
//import HighchartsReact from "./HighchartsReact.min.js";
import HighchartsReact from "highcharts-react-official";
(function(H) {
H.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
H.Point.prototype.highlight = function(event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
H.syncExtremes = function(e) {
var thisChart = this.chart;
if (e.trigger !== "syncExtremes") {
// Prevent feedback loop
Highcharts.each(Highcharts.charts, function(chart) {
if (chart && chart !== thisChart) {
if (chart.xAxis[0].setExtremes) {
// It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, {
trigger: "syncExtremes"
});
}
}
});
}
};
})(Highcharts);
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
options: {
chart: {
type: "line",
zoomType: "x",
panning: true,
panKey: "shift"
},
xAxis: {
events: {
setExtremes: function(e) {
Highcharts.syncExtremes(e);
}
}
},
series: [
{
data: [
29.9,
71.5,
106.4,
129.2,
144.0,
176.0,
135.6,
148.5,
216.4,
194.1,
95.6,
54.4
]
}
]
},
options2: {
chart: {
zoomType: "x"
},
series: [
{
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
],
xAxis: {
events: {
setExtremes: function(e) {
Highcharts.syncExtremes(e);
}
}
}
}
};
}
componentDidMount() {
["mousemove", "touchmove", "touchstart"].forEach(function(eventType) {
document
.getElementById("container")
.addEventListener(eventType, function(e) {
var chart, point, i, event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
if (chart) {
// Find coordinates within the chart
event = chart.pointer.normalize(e);
// Get the hovered point
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
}
});
});
}
inputChange(e) {
this.setState({
options: {
series: [{ data: [1, 1, 1] }, { data: [2, 2, 2] }]
}
});
}
render() {
return (
<div id="container">
<HighchartsReact
constructorType={"chart"}
highcharts={Highcharts}
options={this.state.options}
/>
<HighchartsReact
constructorType={"chart"}
highcharts={Highcharts}
options={this.state.options2}
/>
</div>
);
}
}
render(<App />, document.getElementById("root"));
从“React”导入React;
从“react dom”导入{render};
//导入海图
从“Highcharts/highstock”导入Highcharts;
//从“/HighchartsReact.min.js”导入HighchartsReact;
从“highcharts react official”导入highcharts react;
(职能(H){
H.Pointer.prototype.reset=函数(){
返回未定义;
};
/**
*通过显示工具提示、设置悬停状态和绘制十字线来高亮显示点
*/
H.Point.prototype.highlight=功能(事件){
event=this.series.chart.pointer.normalize(事件);
this.onMouseOver();//显示悬停标记
this.series.chart.tooltip.refresh(this);//显示工具提示
this.series.chart.xAxis[0]。drawCrosshair(事件,this);//显示十字线
};
H.e=函数(e){
var thisChart=this.chart;
如果(如触发!=“同步极端”){
//防止反馈回路
Highcharts.each(Highcharts.charts,函数(chart){
如果(图表和图表!==此图表){
if(chart.xAxis[0].setextrems){
//更新时为空
chart.xAxis[0]。设置极值(e.min,e.max,未定义,false{
触发器:“同步极端”
});
}
}
});
}
};
})(高图);
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
选项:{
图表:{
键入:“行”,
zoomType:“x”,
平移:是的,
一键:“移位”
},
xAxis:{
活动:{
设置极端值:函数(e){
海图.海图(e);
}
}
},
系列:[
{
数据:[
29.9,
71.5,
106.4,
129.2,
144.0,
176.0,
135.6,
148.5,
216.4,
194.1,
95.6,
54.4
]
}
]
},
选项2:{
图表:{
zoomType:“x”
},
系列:[
{
数据:[1,2,3,4,5,6,7,8,9,10,11,12]
}
],
xAxis:{
活动:{
设置极端值:函数(e){
海图.海图(e);
}
}
}
}
};
}
componentDidMount(){
[“mousemove”、“touchmove”、“touchstart”].forEach(函数(eventType){
文件
.getElementById(“容器”)
.addEventListener(事件类型,函数(e){
var图,点,i,事件;
对于(i=0;i 提供(它需要同步图表,请检查此示例。@WojciechChmiel感谢您提供了正确的选项,我尝试了它,并更新了问题。是否有相应的示例?@WojciechChmiel对第二个图表有效,如果我将鼠标悬停在第二个图表点上,它将显示两个图表的工具提示。对第一个图表无效。另外,第一个图表有two系列。我正在接近解决方案。这是可行的,但我的第一个图表有两个线系列,我想在两行上都添加悬停圆圈。如果其中任何一行被悬停,请检查我添加的有问题的屏幕截图。只有悬停的线在该点上得到活动圆圈。并且,在其上方给出控制台错误TypeError:无法读取属性“category”在调用point.highlight(e);
function时,这一行point=chart.series[0]。searchPoint(event,true);
只取第一个序列。循环后解决了该问题。
import React from "react";
import { render } from "react-dom";
// Import Highcharts
import Highcharts from "highcharts/highstock";
//import HighchartsReact from "./HighchartsReact.min.js";
import HighchartsReact from "highcharts-react-official";
(function(H) {
H.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
H.Point.prototype.highlight = function(event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
H.syncExtremes = function(e) {
var thisChart = this.chart;
if (e.trigger !== "syncExtremes") {
// Prevent feedback loop
Highcharts.each(Highcharts.charts, function(chart) {
if (chart && chart !== thisChart) {
if (chart.xAxis[0].setExtremes) {
// It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, {
trigger: "syncExtremes"
});
}
}
});
}
};
})(Highcharts);
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
options: {
chart: {
type: "line",
zoomType: "x",
panning: true,
panKey: "shift"
},
xAxis: {
events: {
setExtremes: function(e) {
Highcharts.syncExtremes(e);
}
}
},
series: [
{
data: [
29.9,
71.5,
106.4,
129.2,
144.0,
176.0,
135.6,
148.5,
216.4,
194.1,
95.6,
54.4
]
}
]
},
options2: {
chart: {
zoomType: "x"
},
series: [
{
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
],
xAxis: {
events: {
setExtremes: function(e) {
Highcharts.syncExtremes(e);
}
}
}
}
};
}
componentDidMount() {
["mousemove", "touchmove", "touchstart"].forEach(function(eventType) {
document
.getElementById("container")
.addEventListener(eventType, function(e) {
var chart, point, i, event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
if (chart) {
// Find coordinates within the chart
event = chart.pointer.normalize(e);
// Get the hovered point
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
}
});
});
}
inputChange(e) {
this.setState({
options: {
series: [{ data: [1, 1, 1] }, { data: [2, 2, 2] }]
}
});
}
render() {
return (
<div id="container">
<HighchartsReact
constructorType={"chart"}
highcharts={Highcharts}
options={this.state.options}
/>
<HighchartsReact
constructorType={"chart"}
highcharts={Highcharts}
options={this.state.options2}
/>
</div>
);
}
}
render(<App />, document.getElementById("root"));