Adding tooltips for preconfigured date ranges in stock chart (Highstock) - javascript

I want to add some tooltips for the preconfigured date range buttons (like 1 day, 1 month etc.) in stock chart in highstock. I am not able to find a way to do it.
refer this link
Any help would be appreciated.
Thanks

Highcharts doesn't have built-in tooltip for the rangeSelector, but still you can create your own tooltip for that. It is very simple to add events to the buttons:
Highcharts.stockChart('container', {
chart: {
events: {
load: function() {
var chart = this,
buttons = chart.rangeSelector.buttons;
for (var i = 0, len = buttons.length; i < len; i++) {
(function(i) {
var item = buttons[i],
group = $('.highcharts-range-selector-tooltip'),
rectElem = $('.range-selector-tooltip'),
textElem = $('.range-selector-tooltip-text'),
box;
item.on('mouseover', function(e) {
// Define legend-tooltip text
var str = item.text.textStr;
textElem.text(str)
// Adjust rect size to text
box = textElem[0].getBBox()
rectElem.attr({
x: box.x - 8,
y: box.y - 5,
width: box.width + 15,
height: box.height + 10
})
// Show tooltip
group.attr({
transform: `translate(${e.clientX + 7}, ${e.clientY + 7})`
})
}).on('mouseout', function(e) {
// Hide tooltip
group.attr({
transform: 'translate(-9999,-9999)'
})
});
})(i);
}
}
}
},
...
}, function(chart) {
var group = chart.renderer.g('range-selector-tooltip')
.attr({
transform: 'translate(-9999, -9999)',
zIndex: 99
}).add(),
text = chart.renderer.text()
.attr({
class: 'range-selector-tooltip-text',
zIndex: 7
}).add(group),
box = text.getBBox();
chart.renderer.rect().attr({
'class': 'range-selector-tooltip',
'stroke-width': 1,
'stroke': 'grey',
'fill': 'white',
'zIndex': 6
})
.add(group)
});
Live example: http://jsfiddle.net/BlackLabel/Lg9cfrub/
API Reference: https://api.highcharts.com/highstock/chart.events.load

Related

Setting Color With Array Data Format in Highcharts Funnel

I have attached the funnel visualization code that I have so far.
$(function() {
var dataEx = [
['1 Visit', 352000],
['2 Visits', 88000],
['3+ Visits', 42000]
],
len = dataEx.length,
sum = 0,
minHeight = 0.05,
data = [];
//specify your percent of prior visit value manually here:
var perc = [100, 25, 48];
for (var i = 0; i < len; i++) {
sum += dataEx[i][1];
}
for (var i = 0; i < len; i++) {
var t = dataEx[i],
r = t[1] / sum;
data[i] = {
name: t[0],
y: (r > minHeight ? t[1] : sum * minHeight),
percent: perc[i], // <----- this here is manual input
//percent: Math.round(r * 100), <--- this here is mathematical
label: t[1]
}
}
console.log(dataEx, data)
$('#container').highcharts({
chart: {
type: 'funnel',
marginRight: 100,
events: {
load: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
var bBox = p.dataLabel.getBBox()
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
'text-anchor': 'middle',
y: p.labelPos.y - (bBox.height / 2)
})
})
},
redraw: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
'text-anchor': 'middle',
y: p.labelPos.y - (bBox.height / 2)
})
})
}
},
},
title: {
text: 'Guest Return Funnel',
x: -50
},
tooltip: {
//enabled: false
formatter: function() {
return '<b>' + this.key +
'</b><br/>Percent of Prior Visit: '+ this.point.percent + '%<br/>Guests: ' + Highcharts.numberFormat(this.point.label, 0);
}
},
plotOptions: {
series: {
allowPointSelect: true,
borderWidth: 12,
animation: {
duration: 400
},
dataLabels: {
enabled: true,
connectorWidth: 0,
distance: 0,
formatter: function() {
var point = this.point;
console.log(point);
return '<b>' + point.name + '</b> (' + Highcharts.numberFormat(point.label, 0) + ')<br/>' + point.percent + '%';
},
minSize: '10%',
color: 'black',
softConnector: true
},
neckWidth: '30%',
neckHeight: '0%',
width: '50%',
height: '110%'
//old options are as follows:
//neckWidth: '50%',
//neckHeight: '50%',
//-- Other available options
//height: '200'
// width: pixels or percent
}
},
legend: {
enabled: false
},
series: [{
name: 'Unique users',
data: data
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/funnel.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="width: 500px; height: 400px; margin: 0 auto"></div>
What I want to do is manually change the color of each category (piece) of the funnel (for example, maybe first category red, second category orange, third category yellow). I know that there are some ways to enter in data into a series in Highcharts such as:
[['CATEOGRY', 'VALUE],...['CATEGORY','VALUE']]
or you can do an array with names value and specify something like
color: "#00FF00" inside of it.
So maybe I can use the second form of writing data into a series cause you can specify color.
However, how would I be able to specify color of the pieces WHILE ALSO ensuring that the data processing algorithm to scale when there are small values works and the rest of the code works?
Also, is there any way to specify color given the current array of data that I have in my code? Being dataEx = [['CATEOGRY', 'VALUE],...['CATEGORY','VALUE']]
You can simply set the color as the third element in dataEx array and then set it as a point color:
var dataEx = [
['1 Visit', 352000, 'red'],
['2 Visits', 88000, 'orange'],
['3+ Visits', 42000, 'yellow']
],
len = dataEx.length,
sum = 0,
minHeight = 0.05,
data = [];
//specify your percent of prior visit value manually here:
var perc = [100, 25, 48];
for (var i = 0; i < len; i++) {
sum += dataEx[i][1];
}
for (var i = 0; i < len; i++) {
var t = dataEx[i],
r = t[1] / sum;
data[i] = {
name: t[0],
color: t[2],
y: (r > minHeight ? t[1] : sum * minHeight),
percent: perc[i], // <----- this here is manual input
//percent: Math.round(r * 100), <--- this here is mathematical
label: t[1]
}
}
Live demo: https://jsfiddle.net/BlackLabel/8be3c1sm/
API Reference: https://api.highcharts.com/highcharts/series.funnel.data.color

Canvas/fabricjs: How to group items?

I have an error when grouping elements. The error is only visible on the circles. Circles are rectangles. How to group items?
var activegroup = canvas.getActiveGroup();
var objectsInGroup = activegroup.getObjects();
activegroup.clone(function (newgroup) {
canvas.discardActiveGroup();
objectsInGroup.forEach(function (object) {
canvas.remove(object);
});
canvas.add(newgroup);
});
The full code
Video bug
Your problem when you create a circle object you put type is a 'rect', replace with 'circle'.
} else if (position.drawingType == "circle") {
var circle = new fabric.Circle({
id: position.i++,
type: "circle",
radius: Math.abs(position.firstClickPositionX < position.lastClickPositionX ? position.firstClickPositionX - position.lastClickPositionX : position.lastClickPositionX - position.firstClickPositionX) / 2,
fill: 'red',
left: position.firstClickPositionX < position.lastClickPositionX ? position.firstClickPositionX : position.lastClickPositionX,
top: position.firstClickPositionY < position.lastClickPositionY ? position.firstClickPositionY : position.lastClickPositionY,
scaleY: 1,
scaleX: 1
});
canvas.add(circle);
Check updated fiddle

Highcharts capture selection

I have a high chart on my web page which is a line chart. It has a functionality to zoom and I capture the zoom event using chart.events.selection. That all is working fine.
But I want to continuously capture the selection event (i.e. basically click and drag event) to show a tooltip in the beginning and end of the selection to show the time user has selected. Couldn't find in high charts documentation. Any help would be appreciated.
Here is my current code to capture selection event:
$(obj.id).highcharts({
chart: {
type: 'areaspline',
backgroundColor:"rgba(0,0,0,0)",
zoomType:"x",
events: {
selection: function(event){
if(!event.xAxis)
return;
.....
Updated:
Updated example in which labels following selection marker: http://jsfiddle.net/pq0wn0xx/2/
I do not think there is a drag event (not for points), but you can wrap drag pointer's method.
Highcharts.wrap(Highcharts.Pointer.prototype, 'drag', function (p, e) {
p.call(this, e);
var H = Highcharts,
chart = this.chart,
selectionMarker = this.selectionMarker,
bBox,
xAxis,
labelLeft,
labelRight,
labelY,
attr,
css,
timerLeft,
timerRight;
if (selectionMarker) {
if (!chart.customLabels) {
chart.customLabels = [];
}
bBox = selectionMarker.getBBox();
xAxis = chart.xAxis[0];
labelLeft = chart.customLabels[0];
labelRight = chart.customLabels[1];
labelY = chart.plotTop + 10;
if (!labelLeft || !labelRight) {
attr = {
fill: Highcharts.getOptions().colors[0],
padding: 10,
r: 5,
zIndex: 8
};
css = {
color: '#FFFFFF'
};
labelLeft = chart.renderer.label('', 0, 0).attr(attr).css(css).add();
labelRight = chart.renderer.label('', 0, 0).attr(attr).css(css).add();
chart.customLabels.push(labelLeft, labelRight);
}
clearTimeout(timerLeft);
clearTimeout(timerRight);
labelLeft.attr({
x: bBox.x - labelLeft.getBBox().width,
y: labelY,
text: 'min: ' + H.numberFormat(xAxis.toValue(bBox.x), 2),
opacity: 1
});
labelRight.attr({
x: bBox.x + bBox.width,
y: labelY,
text: 'max: ' + H.numberFormat(xAxis.toValue(bBox.x + bBox.width), 2),
opacity: 1
});
timerLeft = setTimeout(function () {
labelLeft.fadeOut();
}, 3000);
timerRight = setTimeout(function () {
labelRight.fadeOut();
}, 3000);
}
});
Old answer:
The example from the official API
can be extended to what you need.
The code and the example on jsfiddle are below:
function positionLabels(e, chart) {
if (!chart.customLabels) {
chart.customLabels = [];
}
var labelLeft,
labelRight,
attr,
css,
xAxis,
xMin,
xMax,
yAxis,
yMin,
yMax,
yMiddle,
timerLeft,
timerRight;
if (!e.resetSelection) {
labelLeft = chart.customLabels[0];
labelRight = chart.customLabels[1];
if (!labelLeft || !labelRight) {
attr = {
fill: Highcharts.getOptions().colors[0],
padding: 10,
r: 5,
zIndex: 8
};
css = {
color: '#FFFFFF'
};
labelLeft = chart.renderer.label('', 0, 0).attr(attr).css(css).add();
labelRight = chart.renderer.label('', 0, 0).attr(attr).css(css).add();
chart.customLabels.push(labelLeft, labelRight);
}
clearTimeout(timerLeft);
clearTimeout(timerRight);
xAxis = e.xAxis[0].axis;
xMin = e.xAxis[0].min;
xMax = e.xAxis[0].max;
yAxis = chart.yAxis[0];
yMin = yAxis.min;
yMax = yAxis.max;
yMiddle = (yMax - yMin) * 0.95;
labelLeft.attr({
x: xAxis.toPixels(xMin) - labelLeft.getBBox().width,
y: yAxis.toPixels(yMiddle),
text: 'min: ' + Highcharts.numberFormat(xMin, 2),
opacity: 1
});
labelRight.attr({
x: xAxis.toPixels(xMax),
y: yAxis.toPixels(yMiddle),
text: 'max: ' + Highcharts.numberFormat(xMax, 2),
opacity: 1
});
timerLeft = setTimeout(function () {
labelLeft.fadeOut();
}, 2000);
timerRight = setTimeout(function () {
labelRight.fadeOut();
}, 2000);
}
}
example: http://jsfiddle.net/pq0wn0xx/

highchart place x-axis labels in between ticks on a datetime axis

Using various posts/questions in SO as reference I created a scatter highchart jsfiddle
xAxis: {
opposite:true,
type: 'datetime',
gridLineWidth: 1,
gridLineDashStyle: 'ShortDot',
gridLineColor:'black',
alternateGridColor: 'lightgrey',
tickInterval: 3 * 30 * 24 * 3600 * 1000, // 1 quarter
labels: {
//align: "left",
//padding:200,
formatter: function () {
var s = "";
if (Highcharts.dateFormat('%b', this.value) == 'Jan') {
s = s + "Q1"
};
if (Highcharts.dateFormat('%b', this.value) == 'Apr') {
s = s + "Q2"
};
if (Highcharts.dateFormat('%b', this.value) == 'Jul') {
s = s + "Q3"
};
if (Highcharts.dateFormat('%b', this.value) == 'Oct') {
s = s + "Q4"
};
s = s + " " + Highcharts.dateFormat('%Y', this.value);
return s;
}
},
plotLines: [{
color: 'red', // Color value
value: now, // Value of where the line will appear
width: 2, // Width of the line
label: {
text: 'Now',
align: 'center',
verticalAlign: 'bottom',
y: +20,
rotation: 0
}
}]
},
But I'm struck with having the X-axis label positioned near the tick.
How to move to middle of the grid?
Is there anyway I can achieve the below?
I tried align, padding but didn't help. When the timeline increases I should still have the labels positioned in the middle.
should I do something with tickInterval? It might be a simple property I'm missing.
I found this link jsfiddle which addresses my concern but with 2 x-axis and I'm populating the data from a list.
I implemented Christopher Cortez' solution found here:
However, also changed to to fire on the highcharts load event, rather than the callback, and I've changed it to be recalled when the HighCharts redraw event is fired, so that they stay aligned when the page is resized.
$('#container').highcharts({
chart: {
defaultSeriesType: 'scatter',
events: {
load: centerLabels,
redraw: centerLabels
}
},
/* ... all the other options ...*/
});
Where
function centerLabels(chart) {
var $container = $(chart.target.container);
var axes = chart.target.axes;
var $labels = $container.find('.highcharts-axis-labels .timeline_label');
var $thisLabel, $nextLabel, thisXPos, nextXPos, delta, newXPos;
$labels.each(function () {
$thisLabel = $(this).parent('span');
thisXPos = parseInt($thisLabel.css('left'));
$nextLabel = $thisLabel.next();
// next position is either a label or the end of the axis
nextXPos = $nextLabel.length ? parseInt($nextLabel.css('left')) : axes[0].left + axes[0].width;
delta = (nextXPos - thisXPos) / 2.0;
newXPos = thisXPos + delta;
// remove the last label if it won't fit
if ($nextLabel.length || $(this).width() + newXPos < nextXPos) {
$thisLabel.css('left', newXPos + 'px');
} else {
$thisLabel.remove();
}
});
}
JSFiddle

How to center chart title position dynamically inside pie chart in highcharts

I'm doing a responsive pie chart which holds title in centered position inside it.I've used,
title: {
text: "",
margin: 0,
y:0,
x:0,
align: 'center',
verticalAlign: 'middle',
},
but it's not perfectly centered inside the chart.Any suggestions would be appreciated.Thank you in advance.
Here's the Link : http://jsfiddle.net/LHSey/128/
Better is remove title and use renderer which allows to add custom text, which can be repositioned each time (when you redraw chart). Only what you need is catch this event.
function addTitle() {
if (this.title) {
this.title.destroy();
}
var r = this.renderer,
x = this.series[0].center[0] + this.plotLeft,
y = this.series[0].center[1] + this.plotTop;
this.title = r.text('Series 1', 0, 0)
.css({
color: '#4572A7',
fontSize: '16px'
}).hide()
.add();
var bbox = this.title.getBBox();
this.title.attr({
x: x - (bbox.width / 2),
y: y
}).show();
}
chart:{
events: {
load: addTitle,
redraw: addTitle,
},
}
Example: http://jsfiddle.net/LHSey/129/
We can customize any properties of title using chart.setTitle() as shown below.I've added a title and set useHTML property to true.
chart: {
events: {
load: function () {
this.setTitle({text: 'Title',useHTML:true});
}
}
}

Categories

Resources