I have a problem with styling legend items in Highcharts, when applying a Custom Font to the legend items. Actually items are so close to each other and itemMarginBottom and itemMarginTop are not working.
Here is part of my Highcharts code:
legend: {
enabled: true,
y: 20,
align: 'right',
verticalAlign: 'top',
margin: 30,
width: 200,
borderWidth: 0,
itemMarginTop: 15,
itemMarginBottom: 15,
itemStyle: {
color: '#000',
fontFamily: 'MuseoS500'
}
},
And here is the legend's screenshot:
My Ugly Solution:
I solved that like below, but sadly hard-coded:
// it is for the text's in the legend, I'll start from 0 and will
// increase by 10, so it's adding 10 pixels extra space to the next one
var z = 0;
// this is for tiny-lines near the texts in legend, they starts from 14
// and increasing by 14 also ...
var p = 14;
// loop through <text> tags, which are texts in the lgened
$('.highcharts-legend > text').each( function (i) {
// they have 'x' and 'y' attribute, I need to work on 'y' obviously
y = parseInt($(this).attr('y'));
// increasing 'y' value ...
$(this).attr('y', y + z);
// next element is <path>, the colorful lines ...
$(this).next().attr('transform', 'translate(30,' + p + ')');
// increasing the values, for the next item in the loop ...
z = z + 10;
p = p + 10 + 14;
});
I know that it's so stupid, but I couldn't solve that in any other ways, and I had to make them works somehow. I would be happy to hear your thoughts also ... :)
The new legends after the patch:
The Highchart documentation says that there is a property called lineHeight but Its deprecated since Highcharts 2.1
The post of official Highcharts forum also confirms the same. So, Either you can hack source code to change the height according to your need or Try to correct item height with javascript after chart render.
Also, There is an attribute called itemStyle which allows to set CSS for legend item.
e.g. paddingBottom: '10px'
Check the example :
http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/legend/lineheight/
Related
I have created a chart with 3 points. I have added two graphical elements as circle and rectangle (line) for dragging the points.
Circle dragging should apply for all three points in the graph as in the expected behavior screenshot below.
Line dragging is a vertical shift for graph to move it vertically.
Circle dragging does not apply for all 3 points when I return both graphical elements in the elements array as in the code. It just applies only for 1st point.
When I return one graphical element at a time it works.
Current Behaviour
image of how chart works now
Below I have included the code which returns graphic elements
myChart.setOption({
graphic: data.map(function (item, dataIndex) {
let rec = {
type: 'group',
left: 'center',
position: myChart.convertToPixel('grid', item),
draggable: 'vertical',
ondrag: function (dx, dy) {
onPointDraggingLine(dataIndex, [this.x, this.y]);
},
children: [
{
type: 'rect',
top: '200x',
shape: {
width: 470,
height: 0
},
style: {
stroke: 'gray',
lineWidth: 5,
lineDash: [6]
},
cursor: 'move'
}
]
};
let onlyCrc = {
type: 'circle',
position: myChart.convertToPixel('grid', item),
draggable: true,
ondrag: function (dx, dy) {
onPointDragging(dataIndex, [this.x, this.y]);
},
shape: {
cx: 0,
cy: 0,
r: symbolSize / 2
},
invisible: false,
z: 100,
cursor: 'move'
};
return { elements: [rec, onlyCrc] };
})
});
I have tried to return graphical elements as array of objects .And I have tried by giving a condition for dataIndex while mapping. but didn't work. Expected behavior is as below.
Expected Behavior.
image of how chart should work
Below I have attached the whole code I tried in Codepen.
Link to Minimal Reproduction
https://codepen.io/rushaidrilaf/pen/bGKONRj
I was able to Solve this. Started to resolve it by pointing the dragging function to 2nd point in the graph and updating the position of circular graphical element while dragging the horizontal line.
solution can be viewed from this link
https://codepen.io/rushaidrilaf/pen/bGKONRj
enter code here
I am adding a list of markers to my chart based of certain conditions, these conditions are varying and therefore I will need to have markers that look different:
(using the setGridStrokeXStyle function doesn't seem to have an effect. What is the correct way to accomplish this?)
Markers.map((marker) => {
const chartMarker = chart.addChartMarkerXY()
.setPosition({ x: new Date(marker.x) - startDate, y: marker.y });
chartMarker
.setResultTableVisibility(UIVisibilityModes.always)
.setResultTable((table) => table
.setContent([
['Type']
])
)
.setGridStrokeXVisibility(UIVisibilityModes.whenDragged)
.setGridStrokeYVisibility(UIVisibilityModes.whenDragged)
.setTickMarkerXVisibility(UIVisibilityModes.whenDragged)
.setTickMarkerYVisibility(UIVisibilityModes.whenDragged)
.setDraggingMode(UIDraggingModes.notDraggable)
.setGridStrokeXStyle(new SolidLine({ fillStyle: new SolidFill({ color: ColorHEX("#FF69B4"), thickness: 2 }) })); //This doesn't seem to change the marker's appearance.
console.log("style", chartMarker.getGridStrokeXStyle());
});
The reason why in your code snippet the setGridStrokeXStyle is seemingly not having an effect is because the X grid stroke is not visible.
I have highlighted which element the "X grid stroke" is in the below picture with red to make sure:
As per why this is not visible in your example code, it is due to this method call which makes it so it is only displayed when the Chart Marker is being dragged.
.setGridStrokeXVisibility(UIVisibilityModes.whenDragged)
Furthermore, this other method call makes it so that the Chart Marker can not be dragged, which results in the X grid stroke never being visible.
.setDraggingMode(UIDraggingModes.notDraggable)
Here are some examples of styling different parts of the Chart Marker properly:
In my highcharts, I already have a legend at the bottom left of the graph but want to add a custom status indicator for the entire graph. It's going to be a colored oval with a colored dot and a status on it like in the picture.
Should I be trying to use a custom legend or something else? I don't need to hide/show abiliity of the legend so maybe I'm thinking a label is more appropriate but it seems like those only go in the graph. I want something on the top right of the graph. I'm looking through the API to see what else is available but haven't found one that suites my needs.
edit-
seems like I might have to do "chart.renderer.text" but I'm not sure how to convert and make it work in typescript http://jsfiddle.net/phpdeveloperrahul/HW7Rm/
function (chart) {
var point = chart.series[0].data[8],
text = chart.renderer.text(
'Max',
point.plotX + chart.plotLeft + 10,
point.plotY + chart.plotTop - 10
).attr({
zIndex: 5
}).add(),
box = text.getBBox();
chart.renderer.rect(box.x - 5, box.y - 5, box.width + 10, box.height + 10, 5)
.attr({
fill: '#FFFFEF',
stroke: 'gray',
'stroke-width': 1,
zIndex: 4
})
.add();
});
The best way to add a custom element inside the legend is to use the legend.labelFormatter.
events: {
render() {
let chart = this,
legendAttr = chart.legend.box.getBBox(),
padding = 5;
chart.plus = chart.renderer.text('| +', chart.legend.box.parentGroup.alignAttr.translateX + legendAttr.width + padding, chart.spacingBox.height + padding / 2).attr({
cursor: 'pointer',
}).css({
fontSize: 20
}).on(
"click",
function() {
alert('plus was clicked')
}
).add()
}
}
API References:
https://api.highcharts.com/highcharts/legend.labelFormatter,
Demo: https://jsfiddle.net/BlackLabel/yu7qm9jx/1/
I decided to just get rid of the title and add custom css to the top of it.
I need to show the label values inside the Highcharts bar chart. It can be implemented using dataLabels.Formatter function.
But when the bar is in consist-able size the labels are shown inside the bar and it is looking good. In some cases, the bar is very small in size comparing to the label.
Please see the code pen here, https://codepen.io/JGSpark/pen/YzzBydv?editors=1010
The last bar is very small and 40 is showing outside. As the color: 'white' is commonly used for all the labels it is showing in white though it is in outside.
How can I change the color of the label if it is showing out?
In this example, I need to change the color of label 40 to black. Any suggestions?
You need to add custom formatter which will check the size of yAxis value and will change the color of label accordingly:
formatter: function() {
var max = this.series.yAxis.max,
color = this.y / max < 0.05 ? 'black' : 'white'; // 5% width
return '<p style="color: ' + color + '">' + this.y + ' M</p>';
},
If your chart is not a dynamically created you can set the dataLabels.color for the particular point.
{
y: 40,
dataLabels: {
color: 'black'
}
}
Demo
API
EDIT
Another solution which I can suggest is to add a functionality inside the chart.events.load which will filter if dataLabels is aligned to left or right and set wanted color - it will work if more labels will be outside the column bar.
events: {
load() {
let chart = this,
series = chart.series;
series[0].points.forEach(p => {
if (p.dataLabel.alignOptions.align === 'left') {
p.dataLabel.css({
color: 'black'
})
}
})
}
}
Demo
API
we use the highchart control with Angular and bootstrap.
To adjust the vertical space between the chart and the legend (both are rendered by highchart as svg elements), we set the y property of the legend on page load (in the controller) like this:
$scope.chartContracts = {
options: {
chart: {
type: 'pie',
marginBottom: 50
},
legend : {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom',
x: 0,
y: 4,
Now in one of the Bootstraps layouts, the spacing (y) should be -10 in stead of 4 because for some reason an extra spacing is added.
So it should be based on media query or something similar I guess?
The question is how to do this... I tried with css but I can't seem to style SVG elements (they are called <g>)?
You can check window width and then return correct value.
var wWidth = $(window).width(),
value;
if(wWidth < 400) {
value = 5;
} else {
value = 10;
}
//scope
y: value