yAxis resizer to change svgrenderer position also highcharts - highcharts

I have a chart with some indicators below it. Each indicator area consists
of a svg renderer button. so when I use resize property to drag and resize
the panes, the series resized perfectly but the button remains in its same
position, Can we move the button with the resizer?
Here I created a sample link to regenerate
https://jsfiddle.net/q0ybpnvx/2/
Any help will be appreciated. I am having great trouble. Thank you

You can add and position the custom button in render event:
chart: {
events: {
render: function() {
var chart = this;
if (chart.customBtn) {
chart.customBtn.attr({
y: chart.yAxis[1].top,
});
} else {
chart.customBtn = chart.renderer.button(
'sometext',
5,
chart.yAxis[1].top,
function() {
console.log('some task')
}).add()
}
}
}
},
Live demo: https://jsfiddle.net/BlackLabel/b7vq4ecy/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr

I was able to do something by manually changing the x/y attributes of my svgRenderer label, the same should apply to buttons.
I'm in angular and have a listener for screen resizing:
Also Note that you can change the entire SVGRenderer label with the attr.text property.
this.chart = Highcharts.chart(.....);
// I used a helper method to create the label
this.chart.myLabel = this.labelCreationHelperMethod(this.chart, data);
this.windowEventService.resize$.subscribe(dimensions => {
if(dimensions.x < 500) { //this would be your charts resize breakpoint
// here I was using a specific chart series property to tell where to put my x coordinate,
// you can traverse through the chart object to find a similar number,
// or just use a hardcoded number
this.chart.myLabel.attr({ y: 15, x: this.chart.series[0].points[0].plotX + 20 });
} else {
this.chart.myLabel.attr({ y: 100, x: this.chart.series[0].points[0].plotX + 50 });
}
}
//Returns the label object that we keep a reference to in the chart object.
labelCreationHelperMethod() {
const y = screen.width > 500 ? 100 : 15; 
const x = screen.width > 500 ? this.chart.series[0].points[0].plotX + 50 :
this.chart.series[0].points[0].plotX + 20
// your label
const label = `<div style="color: blue"...> My Label Stuff</div>`
return chart.renderer.label(label, x, y, 'callout', offset + chart.plotLeft, chart.plotTop + 80, true)
.attr({
fill: '#e8e8e8',
padding: 15,
r: 5,
zIndex: 6
})
.add();
}

Related

Custom SVGElement labels loose positioning on zoom

I create some custom SVGElement labels in my chart.. but they loose positioning on zooming the chart.. See this fiddle https://jsfiddle.net/bz6vyedL/
chart:{zoomType: 'xy'},
Labels should not remain stuck when zooming in and behave appropriately
You need to reposition the label after every zoom, for example by using render event function:
chart: {
zoomType: 'xy',
events: {
render: function() {
var chart = this,
point = chart.series[0].points[8],
label = this.customLabel,
xPos,
labelWidth,
newLabelPos;
if (!label) {
this.customLabel = label = chart.renderer.label(
'Label',
null,
null,
'callout',
null,
null,
true, false, 'my-label'
)
.attr({
padding: 0,
zIndex: 10
})
.add();
}
label.attr({
x: point.plotX + chart.plotLeft,
y: point.plotY + chart.plotTop
});
xPos = label.x;
labelWidth = label.width;
newLabelPos = xPos - labelWidth;
label.attr('x', newLabelPos);
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/5v7xo2ky/
API Reference: https://api.highcharts.com/highcharts/chart.events.render

How can i create Highchart xAxis labels centered and enclosed?

I'm trying to replicate the effect on the image but with no luck. On another post someone answered on how to achieve multiple axis lines (see link at the end), but I am unable to achieve the style (labels to maximum width inside the gray and blue boxes).
Previous post: Highcharts: How can I achiveve multiple rows on chart labels?
I would use Highcharts.SVGRenderer to draw rect elements, based on the ticks from the second xAxis and translate the labels. Please check the example below:
chart: {
events: {
render: function() {
var ticks = this.xAxis[1].ticks,
x = this.plotLeft,
y = 378,
width,
color = 'blue',
textColor = 'yellow',
height = 28;
if (!this.customTicks) {
this.customTicks = [];
} else {
this.customTicks.forEach(function(cTick) {
cTick.destroy();
});
this.customTicks.length = 0;
}
Highcharts.objectEach(ticks, function(tick) {
if (tick.mark) {
width = tick.mark.getBBox().x - x;
tick.label.element.children[0].setAttribute('fill', textColor);
tick.label.attr({
translateX: -width / 2
});
this.customTicks.push(
this.renderer.rect(
x,
y,
width,
height
).attr({
fill: color
}).add()
)
x = tick.mark.getBBox().x;
if (color === 'blue') {
color = 'gray';
textColor = 'white';
} else {
color = 'blue';
textColor = 'yellow';
}
}
}, this)
this.customTicks.push(
this.renderer.rect(
x,
y,
this.xAxis[1].width + this.plotLeft - x,
height
).attr({
fill: color
}).add()
)
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/s7vfkgzt/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#rect

Highcarts bar legend symbol alignment to the label

If I modify the symbol Width/Height in a bar-chart the symbol is "bottom" aligned with the legend text. Is there a way to "middle - align" them?
http://jsfiddle.net/klodoma/h8j0kL1e/
legend: {
...
symbolHeight: 5,
symbolWidth: 5,
symbolRadius: 0,
...
},
You can calculate and set translateY attribute for legend symbol SVG elements:
events: {
load: function() {
var legendItems = this.legend.allItems,
textBbox,
symbolBbox;
legendItems.forEach(function(item) {
textBbox = item.legendItem.getBBox();
symbolBbox = item.legendSymbol.getBBox();
item.legendSymbol.attr({
translateY: symbolBbox.height - textBbox.height / 2
});
});
}
}
Live demo: http://jsfiddle.net/BlackLabel/a0ye5tuw/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
The only way I know is to use CSS "it's dirty but it works"
.highcharts-point{
transform: translate(0, -10px)
}
Fiddle
http://jsfiddle.net/klodoma/p5mdy19u/
Based on the answer from #ppotaczek I've aligned the Y so that it's always middle aligned, no matter what the symbol size is.
events: {
load: function() {
var legendItems = this.legend.allItems,
textBbox,
symbolBbox;
legendItems.forEach(function(item) {
textBbox = item.legendItem.getBBox();
symbolBbox = item.legendSymbol.getBBox();
item.legendSymbol.attr({
y: textBbox.y + (textBbox.height - symbolBbox.height) / 2
});
});
}
}

How do I create a draggable plot line in Highcharts?

How do I create a draggable plotline in Highcharts? I couldn't find info about this. See please screenshot. You will see a green line on the screenshot. This plotline must be oriented on xAxis and draggable with max and min value on the axis Х. Can you help me? maybe some suggestion or link to official docs. Thank you in advanced.
screenshot
see pls also some short video
https://drive.google.com/open?id=1sHeIZU1S5M15yxbzKWQrTE44pdrUz7PW
You can simply render the rect element using Highcharts.SVGRenderer class, and then handle appropriate events, to change the line position on drag. Everything should be able to achieve on chart.events.load handler. Here is a sample code:
load() {
var chart = this,
lineWidth = 2,
draggablePlotLine = chart.renderer.rect(100, chart.plotTop, lineWidth, chart.plotHeight)
.attr({
fill: 'blue'
})
.add();
chart.container.onmousemove = function(e) {
if (draggablePlotLine.drag) {
let normalizedEvent = chart.pointer.normalize(e),
extremes = {
left: chart.plotLeft,
right: chart.plotLeft + chart.plotWidth
};
// Move line
if (
e.chartX >= extremes.left &&
e.chartX <= extremes.right
) {
draggablePlotLine.attr({
x: e.chartX
})
}
}
}
draggablePlotLine.element.onmousedown = function() {
draggablePlotLine.drag = true
}
draggablePlotLine.element.onmouseup = function() {
draggablePlotLine.drag = false
}
}
Live exampe: https://jsfiddle.net/Lnj7ac42/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer

How do I move the title-label of a polar (spider) graph with HighChart 4?

I created a polar graph. It has some complicated title-lables. It looks as expected on desktop:
But when it's on mobile, the title-lables don't have enough room to show up. And HighCharts neither did it for me. So it looks like this:
What I desire is to move the two title-labels under the triangle, without changing how it behaves in Desktop view.
What can I do to achieve this?
Thanks!
You can translate labels using tick.label.attr({ x: new_x }); method. For example, create some reposition method:
function reposition () {
var chart = this,
xAxis = chart.xAxis[0],
tick, bbox, xy;
$.each(xAxis.tickPositions, function(i, pos){
tick = xAxis.ticks[pos];
if (tick && tick.label) {
bbox = tick.label.getBBox(); // get label's bounding box
xy = tick.label.xy; // get label's xy position
if (xy.x - bbox.width < 0) {
tick.label.attr({
x: bbox.width
});
}
if (xy.x + bbox.width > chart.plotWidth + chart.plotLeft) {
tick.label.attr({
x: chart.plotWidth + chart.plotLeft - bbox.width
});
}
}
});
}
Which will be called on each chart redraw and starting load events:
$('#container').highcharts({
chart: {
polar: true,
type: 'line',
events: {
redraw: reposition,
load: reposition
}
},
...
});
Live demo: http://jsfiddle.net/wmgbbp9k/

Resources