I have a highchart as below in fiddle
https://jsfiddle.net/fedqvuLp/39/
trying to add different shape name as shown below
{
shape: 'diamond',
color:'black',
type: 'flags',
data: [{
fillColor:'rgb(255, 97, 0)',
x: 1426204800000,
title: 'l1',
}, {
fillColor:'rgb(255, 165, 0)',
x: 1467590400000,
title: 'l2',
}]
}
what should be shape name parameter in the config to get the shape
any documentation helps
Eg: 'pin' is not working
You can define your custom shape by adding a new named function to symbols object in SVGRenderer prototype. For example:
Highcharts.SVGRenderer.prototype.symbols.customSymbol = function(x, y, w, h) {
const x1 = x + w;
const y1 = y + h;
const yBreak = y + 0.75 * h;
return ['M', x, y, 'L', x1, y, x + w, yBreak, x1 / 2, y1, x, yBreak, 'Z'];
}
Live demo: https://jsfiddle.net/BlackLabel/xy6ftpn5/
Docs: https://www.highcharts.com/docs/stock/flag-series
Related
How do I make a button to add a horizontal line with 3 points?
1. Height
2. Beginning
3. The end
As in the example below.
Thank you very much!
enter image description here
You can use Highcharts.SVGRenderer class to add the line. For example:
document.getElementById('addLine').addEventListener('click', function() {
var height = document.getElementById('height').value,
start = document.getElementById('start').value,
end = document.getElementById('end').value,
xAxis = chart.xAxis[0],
x1 = xAxis.toPixels(start),
x2 = xAxis.toPixels(end),
y = chart.yAxis[0].toPixels(height);
chart.renderer.path(['M', x1, y, 'L', x2, y])
.attr({
'stroke-width': 5,
stroke: 'red',
zIndex: 4
})
.add();
});
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4782/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path
I'm trying to add text (TextPath) inside an Arc shape, that is following the curve of en Arc. Making a curved TextPath is easy, however I'm failing to put it on top on Arc shape.
If I set x and y of both objects to for.ex. 100 and 100, they end up in illogical locations, so I'm obviously failing to understand something here. What I'm trying to achieve is shown in attached screenshot - could someone make demo of putting a TextPath on top of en Arc ? Thanks.
what I'm trying to achieve
I slightly modified your demo to remove hardcoded values as much as possible.
You just need to correctly generate an SVG path. You can use some answers from here: How to calculate the SVG Path for an arc (of a circle)
Also, you can use Konva.Path shape to debug the generated path.
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function describeArc(x, y, radius, startAngle, endAngle){
var endAngleOriginal = endAngle;
if(endAngleOriginal - startAngle === 360){
endAngle = 359;
}
var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);
var arcSweep = endAngle - startAngle <= 180 ? "0" : "1";
if(endAngleOriginal - startAngle === 360){
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y, "z"
].join(" ");
}
else{
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y
].join(" ");
}
return d;
}
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
stage.add(layer);
var arc = new Konva.Arc({
x: 250,
y: 250,
innerRadius: 100,
outerRadius: 170,
angle: 260,
rotation: 0,
draggable: true,
fill: 'yellow',
stroke: 'black',
strokeWidth: 4,
offset: 0,
});
layer.add(arc);
var tr1 = new Konva.Transformer({
node: arc,
resizeEnabled: false
});
layer.add(tr1);
var txt = new Konva.TextPath({
x: arc.x(),
y: arc.y(),
draggable: true,
fill: '#333',
fontSize: 22,
fontFamily: 'Arial',
text: "Hello world !",
align: 'center',
data: describeArc(0, 0, (arc.innerRadius() + arc.outerRadius()) / 2, 90, 90 + arc.getAttr("angle")),
});
layer.add(txt);
var tr2 = new Konva.Transformer({
node: txt,
resizeEnabled: false,
});
layer.add(tr2);
const path = new Konva.Path({
x: txt.x(),
y: txt.y(),
data: txt.data(),
stroke: 'red'
});
layer.add(path);
layer.draw();
Demo: https://jsbin.com/muwobaxipe/3/edit?js,output
I am trying to create a reference line that runs through the origin and passes from negative to positive. See an example of what i am trying to achieve - see the threshold line. This threshold line must run through all three x, y coordinates (-1,-45,000), (0.0), (1, 45,000).
enter image description here
Below is my work so far.
http://jsfiddle.net/catio6/rhf6yre5/1/
I've looked at this for reference but have had had no luck after several hours of attempts of replicating this with all three x, y coordinates (-1,-45,000), (0.0), (1, 45,000): http://jsfiddle.net/phpdeveloperrahul/XvjfL/
$(function () {
$('#container').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar']
},
series: [{
data: [29.9, 71.5, 256]
}]
}, function(chart) { // on complete
console.log("chart = ");
console.log(chart);
//chart.renderer.path(['M', 0, 0, 'L', 100, 100, 200, 50, 300, 100])
chart.renderer.path(['M', 75, 223.5,'L', 259, 47])//M 75 223.5 L 593 223.5
.attr({
'stroke-width': 2,
stroke: 'red'
})
.add();
});
});
So Highcharts doesn't have, as far as I know, a way to define a line that goes from/to infinity.
One idea I had to solve this issue for you is dynamically calculate the values for the line series based on your data. The idea is simple: Given the maximum values for X and Y you want to plot, we just need to limit the axis to a certain value that makes sense and calculate the values for the asymptote series in order to make it seems infinite. My algorithm looks like this:
// Get all your other data in a well formated way
let yourData = [
{x: 0.57, y: 72484},
{x: 0.57, y: 10000}
];
// Find which are the maximum x and y values
let maxX = yourData.reduce((max, v) => max > v.x ? max : v.x, -999999999);
let maxY = yourData.reduce((max, v) => max > v.y ? max : v.y, -999999999);
// Now you will limit you X and Y axis to a value that makes sense due the maximum values
// Here I will limit it to 10K above or lower on Y and 2 above or lower on X
let maxXAxis = maxX + 2;
let minXAxis = - (maxX + 2);
let maxYAxis = maxY + 10000;
let minYAxis = -(maxY + 10000);
// Now you need to calculate the values for the Willingness to pay series
let fn = (x) => 45000 * x; // This is the function that defines the Willingness to pay line
// Calculate the series values
let willingnessSeries = [];
for(let i = Math.floor(minXAxis); i <= Math.ceil(maxXAxis); i++) {
willingnessSeries.push([i, fn(i)]);
}
Here is a working fiddle: http://jsfiddle.net/n5xg1970/
I tested with several values for your data and all of them seem to be working ok.
Hope it helps
Regards
Is there a way to add a plotband that has a smooth transition? Before I am using
addPlotLine and
addPlotBand
chart.yAxis[0].removePlotBand('plot-band-1');
chart.yAxis[0].removePlotLine('plot-line-1');
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
chart.yAxis[0].addPlotBand({
from: 100000,
to: y,
color: {
linearGradient: { x1: 1, y1: 1, x2: 1, y2: 0 },
stops: [
[0, 'rgba(46, 230, 0, 0.22)'],
[1, 'rgba(46, 230, 0, 0)'] //down
]
},
id: 'plot-band-1'
});
chart.yAxis[0].addPlotLine({
value: y,
color: 'red',
width: 2,
id: 'plot-line-1'
});
to plot the point on a dynamic chart, but now I am using animate to make the plotting smoother
plotLine = yAxis.plotLinesAndBands[0].svgElem;
d = plotLine.d.split(' ');
newY = yAxis.toPixels(y) - d[2];
plotLine.animate({
translateY: newY
}, 300);
Also I am trying the solution from this Highcharts plotBand animation. however it seems that I am unable to implement it properly.
For your reference here is the code of where is used addPlotLine and addPlotBand and this is the current code style being used. Appreciate your help with this. Thank you.
If you pass path d attribute as an array, you can animate it as a simple shape.
Add the plotband before setiInterval and animate it as the plotline on every interval.
const plotbandPath = plotband.svgElem.d.split(' ')
plotbandPath[7] = plotbandPath[9] = newY
plotband.svgElem.animate({
d: plotbandPath
}, 300)
example: http://jsfiddle.net/sqer2x13/
How would you achieve this (jsFiddle link)
dynamically for the Highcharts "Activity Gauge", so obviously it works there but I had to manually determine the correct x & y coordinates for the labels.
This result is similar to using the "inside" property for column charts, but seems nothing is built-in like that for this chart type (that I've run across at least). One could come close by passing in the same y values as for each series as tick marks on the y-axis (see snippet below) and getting rid of all markings except the number, but then I can't stagger those to be positioned correctly within each series, and for the dataLabel x & y approach I don't know the equation to be able to position the labels based on the series y values dynamically with a callback.
yAxis: {
labels: {
enabled: true,
x: 10, y: -15,
format: '{value} %',
style: {
fontSize: 16,
color: 'black'
}
},
min: 0,
max: 100,
gridLineColor: 'transparent',
lineColor: 'transparent',
minorTickLength: 0,
//tickInterval: 67,
tickPositions: [50, 65, 80], //TRIED TO USE Y-AXIS LABELS BUT COULDN'T STAGGER THEM
tickColor: '#000000',
tickPosition: 'inside',
//tickLength: 50,
tickWidth: 0
},
Any help would be much appreciated, thanks in advance.
Solved via Highcharts support forum:
fiddle
, just call the following function on chart load and redraw events:
function redrawConnectors() {
var chart = this,
cX, cY,
shapeArgs, ang, posX, posY, bBox;
Highcharts.each(chart.series, function(series, j) {
Highcharts.each(series.points, function(point, i) {
if (point.dataLabel) {
bBox = point.dataLabel.getBBox();
shapeArgs = point.shapeArgs;
cX = shapeArgs.x,
cY = shapeArgs.y,
ang = shapeArgs.end;
posX = cX + shapeArgs.r * Math.cos(ang);
posY = cY + shapeArgs.r * Math.sin(ang);
point.dataLabel.attr({
x: posX - bBox.width / 2,
y: posY - bBox.height / 2
});
}
});
});
}