I know how to draw vertical line in highcharts. But it's possible only when I click anywhere except upon the series. When I click on the series, no prompt is given. If I click anywhere else in the chart container, then it I get a prompt. Please give me a solution. My attempt so far:
$('#save_line_vertical').click(function(event) {
var label=document.getElementById("line_label_vertical").value;
if(label!=null)
{
var id = 'vertLine' + Math.random();
chart.addPlotLine({
value: axis_value,
color: '#'+(Math.random()*0xEEEEEE<<0).toString(16),
width: 2,
id: id,
label : {
text : label
},
events: {
click: function(e) {
chart.removePlotLine(id);
}
},
});
}
});
Here is my fiddle:
http://jsfiddle.net/das_palash89/3AqM7/
You need to add click event to series object too, with small polishing, see:
plotOptions: {
series: {
events: {
click: function (event) {
var label = prompt('Label for Vertical Line');
if (label != null) {
var chart = this.xAxis;
chart.addPlotLine({
value: chart.toValue(event.x),
color: '#' + (Math.random() * 0xEEEEEE << 0).toString(16),
width: 2,
id: 'vertLine',
zIndex: 9999,
label: {
text: label
}
});
}
}
}
}
},
Demo: http://jsfiddle.net/3AqM7/5/
Related
What I would like to accomplish:
I am trying to represent the bubble size (z value) in the legend. When that legend item is hovered over or toggled off the bubbles should shrink to equal sizes, like a normal scatter plot.
What I've tried so far:
I was able to get a legend item to represent the size by adding a new series with no data. I linked the 2 series that have data to this new one. I then overrode Highcharts legend hover function so that when the "size" legend item is hovered the linked series stay fully visible.
Like so:
series: [
{
type: "bubble",
name: HotSpotResources.Positive,
color: "#2699FB",
data: points[0], //example data like -> {x: 10, y: 12, z: 150, id: "some_id"}
linkedTo: "nsize",
showInLegend: true
},
{
type: "bubble",
name: HotSpotResources.Negative,
color: "#F8A6A6",
data: points[1],
linkedTo: "nsize",
showInLegend: true
},
{
id: "nsize",
type: "bubble",
name: HotSpotsResources.nSize,
color: "#4A4A4A",
marker: {
symbol: `url(${LayoutResources.AppRoot}/assets/images/nsize-icon.svg)`
},
}
],
and the legend hover override:
(function (H) {
H.Legend.prototype.setItemEvents = function (item, legendItem, useHTML) {
const legend = this,
boxWrapper = legend.chart.renderer.boxWrapper,
activeClass = 'highcharts-legend-' + (item.series ? 'point' : 'series') + '-active',
hasLinkedSeries = item.linkedSeries && item.linkedSeries.length ? true : false,
setLinkedSeriesState = (item, state) => {
item.linkedSeries.forEach((elem) => (elem.setState(state)));
};
// Set the events on the item group, or in case of useHTML, the item itself (#1249)
(useHTML ? legendItem : item.legendGroup).on('mouseover', () => {
if (item.visible) {
item.setState('hover');
// Add hover state to linked series
if (hasLinkedSeries) {
setLinkedSeriesState(item, 'hover');
}
// A CSS class to dim or hide other than the hovered series
boxWrapper.addClass(activeClass);
legendItem.css(legend.options.itemHoverStyle);
}
}).on('mouseout', () => {
legendItem.css(H.merge(item.visible ? legend.itemStyle : legend.itemHiddenStyle));
// A CSS class to dim or hide other than the hovered series
boxWrapper.removeClass(activeClass);
item.setState();
}).on('click',(event) => {
const strLegendItemClick = 'legendItemClick',
fnLegendItemClick = () => {
item.setVisible ? item.setVisible() : "";
};
// Pass over the click/touch event. #4.
event = {
browserEvent: event
};
// click the name or symbol
if (item.firePointEvent) { // point
item.firePointEvent(strLegendItemClick, event, fnLegendItemClick);
}
else {
H.fireEvent(item, strLegendItemClick, event, fnLegendItemClick);
}
});
};
})(Highcharts)
So far so good.
I tried shrinking the size with just css but being an svg it was not possible / it produced ill results. Scaling them also changed their position so that was out of the question.
.highcharts-series-hover {
transform: scale(1.5);
transition: transform 250ms;
}
I was able to shrink the bubbles on hover (of the bubble itself not the legend item) by changing marker state:
plotOptions: {
bubble: {
marker: {
states: {
hover: {
radius: 4
}
}
}
}
}
But I want that same result when hovering the size legend item, not when hovering the bubble.
Finally, here's a screenshot of the chart I have created for reference:
Can anyone find a way to manipulate Highcharts to accomplish this task or help point me in the right direction?
You can add onmouseover and onmouseout events in a wrap of renderItem method and change type of the series that are unhover to scatter.
(function(H) {
H.wrap(H.Legend.prototype, 'renderItem', function(proceed, item) {
proceed.call(this, item);
var chart = this.chart,
series = chart.series,
element = item.legendGroup.element;
element.onmouseover = function() {
series.forEach(function(s) {
if (s !== item) {
s.update({
type: 'scatter'
}, false);
}
});
chart.redraw();
}
element.onmouseout = function() {
series.forEach(function(s) {
if (s !== item) {
s.update({
type: 'bubble'
}, false);
}
});
chart.redraw();
}
});
}(Highcharts));
Live demo: https://jsfiddle.net/BlackLabel/r64f3w5n/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#update
Docs: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts
How to enforce that the tooltip show up only when mouse pointer is inside the chart area and not when on navigator scrollbar or on time range selectors in the top?
http://jsfiddle.net/1p4f5kny/
/*
The purpose of this demo is to demonstrate how multiple charts on the same page can be linked
through DOM and Highcharts events and API methods. It takes a standard Highcharts config with a
small variation for each data set, and a mouse/touch event handler to bind the charts together.
*/
$(function () {
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.highlight(e);
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
Highcharts.Point.prototype.highlight = function (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
};
/**
* 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' });
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highcharts/highcharts/blob/master/samples/data/activity.json
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function (activity) {
$.each(activity.datasets, function (i, dataset) {
// Add X values
/*dataset.data = Highcharts.map(dataset.data, function (val, j) {
return [activity.xData[j], val];
});*/
$('<div class="chart">')
.appendTo('#container')
.highcharts('StockChart', {
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function () {
return {
x: this.chart.chartWidth - this.label.width, // right aligned
y: -1 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
shared: false,
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
});
});
Insted of binding events on the container, you can use point mouseOver event to synchronize tooltips:
series: [{
point: {
events: {
mouseOver: function(e) {
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
if (chart !== this.series.chart) {
point = chart.series[0].points[this.index];
chart.tooltip.refresh([point]);
}
}
}
}
},
...
}]
Live demo: http://jsfiddle.net/BlackLabel/g0brx52d/
API Reference: https://api.highcharts.com/highcharts/series.line.point.events.mouseOver
I have 3 line series in my highchart , i want to make one series fixed (user) cant disable/hide it by clicking the legend.
And other two i want to work as radio button i.e user can choose among those 2 which one to show , now i was able to make that happen , but now i want a radio button next to those two legend symbols which user can choose from .
legend should be like this.
and the radio button should toggle the series. the working code (without radio button and legend allignment) is :
drawChart(data1, data2, data3) {
let chart = Highcharts.chart("container", {
chart: {
zoomType: "xy"
},
title: {
text: null
},
plotOptions: {
series: {
events: {
show: function () {
let chart = this.chart,
series = chart.series,
i = series.length,
otherSeries;
while (i--) {
if (i != 0)
otherSeries = series[i];
if (otherSeries != this && otherSeries.visible) {
otherSeries.hide();
}
}
},
legendItemClick: function () {
if (this.visible) {
return false;
}
}
}
}
},
series: [{
name: "series1",
data: data1
}, {
name: "series2",
data: data2
}, {
name: "series3",
data: data3,
visible: false
}]
}
You need to set the plotOptions and set showCheckbox: true
plotOptions: {
line: {
marker: { enabled: false }
},
turboThreshold: 0,
series: {
cursor: 'pointer',
showCheckbox: true,
events: {
checkboxClick: function (event) {
if (event.checked) {
this.show();
this.legendSymbol.show();
} else {
this.hide();
this.legendSymbol.hide();
}
},
legendItemClick: function() {
return false;
}
}
}
},
By default the checkboxes are placed right next to series label but we can override it according to our need,
Here is a fiddle that might help !!! It's just a pointer, You can customize according to your need.
I am using highchart for some drilldown functions.
In my case I am having a area chart with an onclick event.
I'd like to let the user click on an area plot to add a line and change the chart color. I therefore have two functions: one changing the chart color and one adding a plot line where the user has clicked.
Below is the plot line click event:
chart: {
type: 'area',
events: {
click: function(evt) {
var xValue = evt.xAxis[0].value;
var xAxis = evt.xAxis[0].axis;
$.each(xAxis.plotLinesAndBands,function(){
if(this.id===myPlotLineId)
{
this.destroy();
}
});
xAxis.addPlotLine({
value: xValue,
width: 1,
color: 'red',
//dashStyle: 'dash',
id: myPlotLineId
});
}
}
},
And this is the color update event, which is inside the plotOptions
plotOptions: {
series: {
point: {
events: {
click: function(event) {
//selector
if(previousPoint){
previousPoint.update({ color: '#FFC7C3' });
}
this.update({ color: '#fe5800' });
//drilldown trigger
var date = this.category.replace(/\-/g,'')
$("#datepicker").click();
//put somewhere else not in the custom
$("#drilldowndate").html(parseInt(date));
$(window).scrollTop(1700);
window.setTimeout(function(){
$("#trendDrill").click();
},500);
window.setTimeout(function(){
$("#periodChecker").text($(".ifNoDrill").data("target"));
},1000);
}
}
}
}
},
And I'd like the addplotline function and the update plot color function both working on the same click, so when the user clicks on the desired area, the chart changes the specific color and a plot line appears.
JS fiddle Demo : http://jsfiddle.net/Xm4vW/70/
You can change add plotLines in your point click event. I have made two functions, one responsible for changing colour of your point (also on hover) and one for adding plotLines:
var updatePoint = function(point) {
if (previousPoint) {
previousPoint.update({
color: '#7cb5ec',
marker: {
states: {
hover: {
fillColor: '#7cb5ec',
}
}
}
});
}
previousPoint = point;
point.update({
color: '#fe5800',
marker: {
states: {
hover: {
fillColor: '#fe5800',
}
}
}
});
},
addPlotLine = function(evt) {
var point = evt.point;
var xValue = point.x;
var xAxis = point.series.xAxis;
Highcharts.each(xAxis.plotLinesAndBands, function(p) {
if (p.id === myPlotLineId) {
p.destroy();
}
});
xAxis.addPlotLine({
value: xValue,
width: 1,
color: 'red',
id: myPlotLineId
});
};
You can use this functions inside your click event function:
point: {
events: {
click: function(event) {
updatePoint(this);
addPlotLine(event);
}
}
}
Here you can find an example how it can work: http://jsfiddle.net/Xm4vW/72/
I am using Synchronized chart of Highcharts to demonstrate the statistics.
For reference : http://www.highcharts.com/demo/synchronized-charts.
Here, when the chart is getting plotted for the first time, no data points is selected. As, the cursor enters into the chart area, the tooltip, crosshairs and data points get highlighted. It works as expected.
The modification I need is, when the user comes out of the chart, the chart should look like as it was in the loading stage.
i.e. If the cursor is not on any of the chart,then no data points should remain selected. In other words, the tooltip, crosshair and the highlighted shadow on data point should get removed.
Thanks in advance for any help or suggestion.
use mouseleave to detect when the mouse is out of the container:
$('#container').bind('mouseleave', function(e) {
use hide method to hide the tooltip and hide Crosshair method to hide the crosshair:
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
Check the example (jsfiddle):
$(function() {
$('#container').bind('mouseleave', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent);
point = chart.series[0].searchPoint(event, true);
point.onMouseOut();
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
}
});
$('#container').bind('mousemove touchmove touchstart', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.onMouseOver(); // Show the hover marker
chart.tooltip.refresh(point); // Show the tooltip
chart.xAxis[0].drawCrosshair(event, point); // Show the crosshair
}
}
});
/**
* 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'
});
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highcharts/highcharts/blob/master/samples/data/activity.json
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function(activity) {
$.each(activity.datasets, function(i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function(val, j) {
return [activity.xData[j], val];
});
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function() {
return {
x: this.chart.chartWidth - this.label.width, // right aligned
y: -1 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
});
});