我有两个图表显示时间序列数据,我正在尝试同步十字准线和工具提示。但是,图表并不总是具有相同数量的数据点。这会导致十字准线和工具提示在两个图形之间变得不同步。
我在两者上都启用了connectNulls: true
,虽然这会使线条平滑,但它不会为它们不存在的时间段添加数据点。
有没有办法配置connectNulls
以便插入填充点?
已更新
这是一个简单的jsFiddle示例,其中一天中缺少值,导致十字线在两个图形之间变得不同步。
答案 0 :(得分:0)
要设置点之间的实际x距离,可以将xAxis.ordinal
设置为false。另一种解决方案是将空值放在空位。您还可以设置pointStart
和pointInterval
属性。
API参考:
http://api.highcharts.com/highstock/xAxis.ordinal
http://api.highcharts.com/highstock/plotOptions.series.pointStart
http://api.highcharts.com/highstock/plotOptions.series.pointInterval
示例:
http://jsfiddle.net/csgbxdaj/ - 将序数设为假
http://jsfiddle.net/gjxhbf7w/ - 将空值放在series.data数组
答案 1 :(得分:0)
@d_paul这是一个更新的小提示显示接近预期的行为,但是当顶部图中的十字准线在底部的同一点没有数据时,我还在努力防止点悬停/晕圈曲线图。
https://jsfiddle.net/jknipp/g3vr5v44/13/
// Global state variable
window.isOutOfSync = false;
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function(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'
});
}
}
});
}
}
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#success-graphs-container').bind('mousemove touchmove touchstart', function(e) {
var charts = Highcharts.charts.filter(function(chart) {
return (chart.title.textStr.match(/success/i)) ? chart : null;
});
for (i = 0; i < charts.length; i++) {
chart = charts[i];
e = chart.pointer.normalize(e); // Find coordinates within the chart
points = [chart.series[0].searchPoint(e, true), chart.series[1].searchPoint(e, true)]; // Get the hovered point
var show = function() {
if (points[0] && points[1]) {
chart.tooltip.refresh(points); // Show the tooltip
points[0].onMouseOver(); // Show the hover marker
points[1].onMouseOver(); // Show the hover marker
chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
}
}
if (i == 0) {
chart2 = charts[i + 1];
e2 = chart2.pointer.normalize(e); // Find coordinates within the chart
points2 = [chart2.series[0].searchPoint(e2, true), chart2.series[1].searchPoint(e2, true)];
if (((points[0] && points[1]) && points[0].x != points2[0].x && points[1].x != points2[1].x)) {
console.log("val set " + window.isOutOfSync);
//console.log("The points are different AF!");
//if(!window.isOutOfSync) {
points[0].onMouseOut();
points[1].onMouseOut();
points[0].select(false);
points[1].select(false);
chart.tooltip.refresh(points); // Show the tooltip
//chart.tooltip.hide(points); // Hide the tooltip
//points[0].(); // Show the hover marker
//points[1].onMouseOut(); // Show the hover marker
chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
window.isOutOfSync = true;
//}
} else {
window.isOutOfSync = false
show();
}
} else {
show();
}
}
});
// Remove tool tips when the user leaves the container
// We do this for all charts because we had to override the reset function
$('#success-graphs-container').bind('mouseleave', function(e) {
Highcharts.each(Highcharts.charts, function(chart) {
var event = chart.pointer.normalize(e.originalEvent);
var point = chart.series[0].searchPoint(event, true);
if (point) {
point.onMouseOut();
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
}
});
});
function formatSuccessRateToolTip(pointValue, isSuccessful) {
var text = (isSuccessful) ? "Success" : "Failure";
var style = (isSuccessful) ? "color:#1EC06A; font-family: BentonSans Medium, sans-serif;" : "color:#E23C3F; font-family: BentonSans Medium, sans-serif;";
// Use whole numbers if no decimal places to report
var decimalPlaces = (Number(pointValue) === pointValue && pointValue % 1 === 0) ? 0 : 1;
return "<span style=\"" + style + "\">" + Highcharts.numberFormat(pointValue, decimalPlaces, ".", ",") + "% " + text + "</span>";
}
var App = {
renderSubsetSuccessRateChart: function renderSubsetSuccessRateChart(container) {
Highcharts.chart(container, {
chart: {
renderTo: container,
type: 'areaspline',
height: '220',
spacingBottom: 20,
spacingTop: 20,
spacingLeft: 20,
spacingRight: 20
},
title: {
align: 'center',
text: 'Your Success Rate',
margin: 10,
style: {
fontFamily: '\'BentonSans Medium\', sans-serif',
fontSize: '14px'
}
},
xAxis: {
type: 'datetime',
crosshair: {
zIndex: 4,
snap: false
},
events: {
setExtremes: syncExtremes
},
},
yAxis: {
title: {
text: ''
},
min: 0,
max: 100
},
legend: {
enabled: true,
align: 'left'
},
plotOptions: {
series: {
connectNulls: true,
fillOpacity: 1,
stacking: 'normal',
//stickyTracking: true,
point: {
events: {
mouseOver: function(e) {
/*
var chart = this.series.chart;
e = chart.pointer.normalize(e); // Find coordinates within the chart
console.log("here");
points = [chart.series[0].searchPoint(e, true), chart.series[1].searchPoint(e, true)]; // Get the hovered point
var chart2 = $("#total_success_rates").highcharts();
var e2 = chart2.pointer.normalize(e); // Find coordinates within the chart
var points2 = [chart2.series[0].searchPoint(e2, true), chart2.series[1].searchPoint(e2, true)];
console.log(points);
console.log(points2);
if (points[0].x != points2[0].x && points[1].x != points2[1].x) {
console.log("The points are different AF!");
chart.tooltip.hide(points); // Show the tooltip
points[0].onMouseOut(); // Don't hover marker
points[1].onMouseOut(); // Don't hover marker
}
*/
}
}
},
events: {
mouseOut: function() {
//console.log("mouse out");
}
}
}
},
series: [{
name: "Failure",
data: [
[Date.UTC(2017, 7, 1), 20],
[Date.UTC(2017, 7, 2), 25],
[Date.UTC(2017, 7, 3), 24],
[Date.UTC(2017, 7, 4), 7],
[Date.UTC(2017, 7, 6), 0],
[Date.UTC(2017, 7, 7), 35],
[Date.UTC(2017, 7, 9), 12],
[Date.UTC(2017, 7, 10), 10]
],
color: '#1C81C6',
lineColor: 'none',
legendIndex: 1
}, {
name: 'Success',
data: [
[Date.UTC(2017, 7, 1), 80],
[Date.UTC(2017, 7, 2), 75],
[Date.UTC(2017, 7, 3), 76],
[Date.UTC(2017, 7, 4), 93],
[Date.UTC(2017, 7, 6), 100],
[Date.UTC(2017, 7, 7), 65],
[Date.UTC(2017, 7, 9), 88],
[Date.UTC(2017, 7, 10), 90]
],
color: '#E2EFF8',
lineColor: 'none',
legendIndex: 0
}],
tooltip: {
padding: 12,
shared: true,
borderWidth: 2,
borderRadius: 3,
//snap: 0,
style: {
fontSize: '12px',
fontFamily: '\'BentonSans\', sans-serif'
},
formatter: function(tooltip) {
var header,
s = [];
console.log(window.isOutOfSync);
if (window.isOutOfSync) {
console.log("don't show tooltip");
//return false;
return "No data";
}
$.each(this.points, function(i, point) {
// check to see if the point is in the overall graph
//var overallChart = $("#total_success_rates").highcharts();
//console.log(overallChart);
var isSuccessRate = (point.series.name == 'Success');
if (header == null) {
var config = point.point.getLabelConfig();
header = tooltip.tooltipFooterHeaderFormatter(config);
}
s.push(formatSuccessRateToolTip(point.y, isSuccessRate));
// $("#" + point.series.name.toLowerCase() + "-rate").html(point.y + "%");
});
return header + s.reverse().join('<br>');
},
shared: true
},
});
},
renderTotalSuccessRateChart: function renderTotalSuccessRateChart(container) {
Highcharts.chart(container, {
chart: {
renderTo: container,
type: 'areaspline',
height: '220',
spacingBottom: 20,
spacingTop: 20,
spacingLeft: 20,
spacingRight: 20,
},
title: {
align: 'center',
text: "Overall Success Rate",
margin: 10,
style: {
fontFamily: '\'BentonSans Medium\', sans-serif',
fontSize: '14px'
}
},
xAxis: {
type: 'datetime',
crosshair: {
zIndex: 4,
snap: false
},
events: {
setExtremes: syncExtremes
},
},
yAxis: {
title: {
text: ''
},
min: 0,
max: 100
},
legend: {
enabled: true,
align: 'left'
},
plotOptions: {
series: {
connectNulls: true,
fillOpacity: 1,
stacking: 'normal',
stickyTracking: true,
}
},
series: [{
name: "Failure",
data: [
[Date.UTC(2017, 7, 1), 20],
[Date.UTC(2017, 7, 2), 25],
[Date.UTC(2017, 7, 3), 24],
[Date.UTC(2017, 7, 4), 7],
[Date.UTC(2017, 7, 5), 15],
[Date.UTC(2017, 7, 6), 0],
[Date.UTC(2017, 7, 7), 35],
[Date.UTC(2017, 7, 8), 18],
[Date.UTC(2017, 7, 9), 12],
[Date.UTC(2017, 7, 10), 10]
],
color: '#1C81C6',
lineColor: 'none',
legendIndex: 1
}, {
name: 'Success',
data: [
[Date.UTC(2017, 7, 1), 80],
[Date.UTC(2017, 7, 2), 75],
[Date.UTC(2017, 7, 3), 76],
[Date.UTC(2017, 7, 4), 93],
[Date.UTC(2017, 7, 5), 85],
[Date.UTC(2017, 7, 6), 100],
[Date.UTC(2017, 7, 7), 65],
[Date.UTC(2017, 7, 8), 82],
[Date.UTC(2017, 7, 9), 88],
[Date.UTC(2017, 7, 10), 90]
],
color: '#E2EFF8',
lineColor: 'none',
legendIndex: 0
}],
tooltip: {
padding: 12,
crosshair: true,
shared: true,
borderWidth: 2,
borderRadius: 3,
snap: 0,
style: {
fontSize: '12px',
fontFamily: '\'BentonSans\', sans-serif'
},
formatter: function(tooltip) {
var header,
s = [];
$.each(this.points, function(i, point) {
var isSuccessRate = (point.series.name == 'Success');
if (header == null) {
var config = point.point.getLabelConfig();
header = tooltip.tooltipFooterHeaderFormatter(config);
}
s.push(formatSuccessRateToolTip(point.y, isSuccessRate));
// $("#overall-" + point.series.name.toLowerCase() + "-rate").html(point.y + "%");
});
return header + s.reverse().join('<br>');
},
shared: true
},
});
}
}
window.App = App;
App.renderSubsetSuccessRateChart('subset_success_rates');
App.renderTotalSuccessRateChart('total_success_rates');
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/5.0.6/highcharts.js"></script>
<div id="success-graphs-container" class="success-graphs">
<div id="subset_success_rates" style="width:100%; border-bottom: 1px solid #F8F8F8"></div>
<div id="total_success_rates" style="width:100%;"></div>
</div>
&#13;