How can I resize Arc in highcharts? - highcharts

My goal is to draw a curved line with arrows on both ends.
I am trying to recreate the curved dotted line/arrows at the bottom of this graphic.
https://www.epa.gov/sites/production/files/2019-07/active_cases_under_review-7_1_19-boxes.png
So far I have a curved line (originally an arc) that needs to be smaller.
I've various sizing for attributes and css nothing has worked.
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 300px"></div>
var renderer;
renderer = new Highcharts.Renderer(
$('#container')[0],
400,
300
);
renderer.arc(200, 150, -100, -100, -Math.PI, 0)
.attr({
stroke: '#D3D3D3',
'stroke-width': 2,
dashstyle: 'dash'
})
.add();

To create a curved line with arrows on both ends it will be better to use a combination of renderer.path and renderer.symbol('triangle'). I've created an example for you with horizontal arrows, test it and change the way it works as you like.
var arrWidth = 14,
arrHeight = 25,
startX = 80,
startY = 200,
endX = 200,
endY = 100,
renderer;
renderer = new Highcharts.Renderer(
$('#container')[0],
800,
800
);
renderer.symbol('triangle', startX - arrWidth/2, startY - arrHeight, arrWidth, arrHeight)
.attr({
fill: '#D3D3D3',
rotation: -90,
rotationOriginX: startX,
rotationOriginY: startY
}).add();
renderer.symbol('triangle', endX - arrWidth/2, endY - arrHeight, arrWidth, arrHeight)
.attr({
fill: '#D3D3D3',
rotation: 90,
rotationOriginX: endX,
rotationOriginY: endY
}).add();
renderer.path([
'M',
startX,
startY,
'C',
(startX + endX) / 2,
startY,
(startX + endX) / 2,
endY,
endX,
endY
]).attr({
stroke: '#D3D3D3',
'stroke-width': 2,
dashstyle: 'dash'
}).add();
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 300px"></div>
Demo:
https://jsfiddle.net/BlackLabel/prz5w9ox/1/
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#symbol
https://api.highcharts.com/class-reference/Highcharts.SymbolDictionary

Related

how to draw an arc with offset and rotation

I want to draw an arc。 the startAngle is 0, and the spanAngle is 90. the arc has an offset as offset{x:-50,y:50} .
var arcoffset = new Konva.Arc({
x: 200 - 50,
y: 200 + 50,
innerRadius: 70,
outerRadius: 70,
angle: 90,
fill: 'yellow',
stroke: 'green',
strokeWidth: 4,
offset: {
x: -50,
y: 50
}
});
var arcoffsetRotate = new Konva.Arc({
x: 200 - 50,
y: 200 + 50,
innerRadius: 70,
outerRadius: 70,
angle: 90,
fill: 'yellow',
stroke: 'blue',
strokeWidth: 4,
offset: {
x: -50,
y: 50
},
rotationDeg:-90
});
the position of arcoffsetRotate is changed which is not what I want. how can i change the startAngle without the center changed in this case?
Your mistake is confusing the shape offset in with the shape position. You are applying the offset value to the position AND the offset.
The difference is described here in the Konva docs.
Below is a working snippet that shows the effect of 'not' moving the origin with the offset values, and moving position and offset at same time.
If you are trying to draw the arcs so that they make a semi-circle, then you need to use the same position for both arcs, and remove the offset parameter.
If that is not the issue please explain further what you are trying to achieve.
var stage = new Konva.Stage({container: 'container', width: 500, height: 500})
var layer = new Konva.Layer();
stage.add(layer)
function drawArc(pos, posOffset, offset, color, deg) {
var arc = new Konva.Arc({
x: pos.x - posOffset.x,
y: pos.y + posOffset.y,
innerRadius: 70,
outerRadius: 70,
angle: 90,
stroke: color,
strokeWidth: 4,
offset: {
x: offset.x,
y: offset.y
},
rotationDeg: deg
});
var r = new Konva.Rect({
x: pos.x, // + offset.x,
y: pos.y, // + offset.y,
width: arc.size().width,
height: arc.size().height,
stroke: color,
strokeWidth: 1,
offset: {
x: offset.x,
y: offset.y
},
rotationDeg:deg
})
var c = new Konva.Circle({
x: pos.x - posOffset.x,
y: pos.y + posOffset.y,
radius: 5,
fill: color,
offset: {
x: offset.x,
y: offset.y
},
rotationDeg:deg
})
layer.add(arc)
layer.add(r)
layer.add(c)
}
var left = 0
stage.draw();
$('#left').on('click', function(){
layer.destroyChildren();
drawArc({x:200, y:200}, {x:0, y:0}, {x:0, y:0}, 'cyan', 0)
left = left - 1
var offset = {x:left, y:0}
var posOffset = ($('#chk').prop('checked') ? {x:left, y:0} : {x:0, y:0})
drawArc({x:200, y:200}, posOffset, offset, 'magenta', -90)
stage.draw();
})
$('#right').on('click', function(){
layer.destroyChildren();
drawArc({x:200, y:200}, {x:0, y:0}, {x:0, y:0}, 'cyan', 0)
left = left + 1
drawArc({x:200, y:200}, {x:left, y:0}, 'magenta', -90)
stage.draw();
})
$('#reset').on('click', function(){
drawArc({x:200, y:200}, {x:0, y:0}, {x:0, y:0}, 'cyan', 0)
drawArc({x:200, y:200}, {x:0, y:0}, {x:0, y:0}, 'magenta', -90)
stage.draw();
})
$('#reset').trigger('click')
#container {
width: 500px;
height: 500px;
background-color: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/3.2.5/konva.min.js"></script>
<button id='reset'>Reset</button>
<button id='left'>Move offset 1 pixel to left</button>
<button id='right'>Move offset 1 pixel to right</button>
<input type='checkbox' id='chk'/><label for='chk'> Apply offset to position</label>
<div id='container'>
</div>

Highchart dynamically draw Legend marker and trigger mouseover event

I have series legends as scrollbar as demo-ed in this fiddle
http://jsfiddle.net/BlackLabel/kb4gu5rn/
How can I draw series legend marker ("circle"/"square"/"diamond" etc..) instead of line
var $line = $('<div>')
.css({
width: 16,
position: 'absolute',
left: -20,
top: 8,
borderTop: '2px solid ' + (series.visible ? series.color :
options.itemHiddenStyle.color)
})
.appendTo($legendItem);
Also upon hover in this legendItemList I would like to trigger the mouseOver event on the series.. To highlight the series(or data points) in the chart for easy co-visualization
I added this handler, but it doesnt work
$legendItem.hover(function () {
series.onMouseOver();
});
Thanks for your help
You can use Highcharts.SVGRenderer class to add a specific legend marker symbol.
To highlight the series use setState('hover):
var chart = Highcharts.chart({...},
function(chart) {
var options = chart.options.legend,
legend = chart.legend;
/**
* What happens when the user clicks the legend item
*/
function clickItem(series, $legendItem, symbolLine, symbolSVG) {
series.setVisible();
$legendItem.css(
options[series.visible ? 'itemStyle' : 'itemHiddenStyle']
);
symbolLine.attr({
stroke: series.visible ? series.color : options.itemHiddenStyle.color
});
symbolSVG.attr({
fill: series.visible ? series.color : options.itemHiddenStyle.color
});
}
// Create the legend box
var $legend = $('<div>')
.css({
width: 110,
maxHeight: 210,
padding: 10,
position: 'absolute',
overflow: 'auto',
right: 10,
top: 40,
borderColor: options.borderColor,
borderWidth: options.borderWidth,
borderStyle: 'solid',
borderRadius: options.borderRadius
})
.appendTo(chart.container);
$.each(chart.series, function(i, series) {
// crete the legend item
var $legendItem = $('<div>')
.css({
position: 'relative',
marginLeft: 20
})
.css(options[series.visible ? 'itemStyle' : 'itemHiddenStyle'])
.html(series.name)
.appendTo($legend);
// create the line with each series color
var symbolEl = $('<div>');
var renderer = new Highcharts.Renderer(
symbolEl[0],
16,
10
);
var symbolLine = renderer
.path([
'M',
0,
5,
'L',
16,
5
])
.attr({
'stroke-width': 2,
stroke: series.color
})
.add();
var symbolSVG = renderer.symbol(
series.symbol,
3,
0,
10,
10,
Highcharts.merge(series.options.marker, {
width: 10,
height: 10
})
).attr({
fill: series.color
})
.add();
symbolEl.css({
position: 'absolute',
left: -20,
top: 2
}).appendTo($legendItem);
// click handler
$legendItem.hover(function() {
chart.series.forEach(function(s) {
if (s !== series) {
s.setState('inactive');
} else {
series.setState('hover');
}
});
}, function() {
chart.series.forEach(function(s) {
s.setState('normal');
});
});
$legendItem.click(function() {
clickItem(series, $legendItem, symbolLine, symbolSVG);
});
});
});
Live demo: http://jsfiddle.net/BlackLabel/mfvh9ubq/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Series#setState
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#symbol

How to set zindex in konva.js?

I have a problem with the Zindex in konva.js. After I added everything to the layer
I am trying to assign a property to a node for each element separately. But it does not work. For example
for(let i = 0; i<=this.layer['children']; i++){
this.layer['children'][i].setZIndex(someInt);
}
How can i set zindex for all elements in layer?
zIndex in Konva is just index of the element in an array of children of the parent element. So you can't set any number to it and it can not be bigger than children.length - 1.
Working snippet illustrating the getZIndex(), setZIndex(), moveUp() and moveDown() methods of the Kovajs.Shape object. See also example at Konvajs site.
Buttons allow use to move green circle up and down the z-index list by increments of 1, then also to try to move up +10 and down -100. Resulting z-index is shown in text below circles.
// Create the stage
var stage = new Konva.Stage({
container: 'container',
width: $('#container').width(),
height: $('#container').height()
});
// create the layer
var layer = new Konva.Layer();
var data = [ {x: 60, color: 'red'}, {x: 90, color: 'limegreen'}, {x: 120, color: 'gold'}]
var circles = [];
for (var i = 0; i < data.length; i = i + 1){
// create some circles
var circle = new Konva.Circle({
x: data[i].x,
y: 60,
radius: 50,
fill: data[i].color,
stroke: 'black',
strokeWidth: 2
});
layer.add(circle);
circles.push(circle);
}
stage.add(layer);
var green = circles[1];
function sayIndex(){
$('#info').html("Green zIndex=" + circles[1].getZIndex());
}
$('#greenup').on('click', function(){
green.moveUp();
sayIndex();
layer.draw();
})
$('#greendn').on('click', function(){
green.moveDown();
sayIndex();
layer.draw();
})
$('#greenup10').on('click', function(){
var ind = circles[1].getZIndex();
green.setZIndex(ind + 10);
sayIndex();
layer.draw();
})
$('#greendn100').on('click', function(){
var ind = circles[1].getZIndex();
green.setZIndex(ind - 100);
sayIndex();
layer.draw();
})
#container
{
width: 200px;
height: 150px;
border: 1px solid #666;
float: left;
}
#buttons
{
width: 200px;
height: 150px;
border: 1px solid #666;
float: left;
}
#info
{
position: absolute;
left: 20px;
top: 135px;
}
p
{
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.rawgit.com/konvajs/konva/1.6.5/konva.min.js"></script>
<div id="container"></div>
<div id="buttons">
<p><button id='greenup'>Move Green + 1</button></p>
<p><button id='greendn'>Move Green -1</button></p>
<p><button id='greenup10'>Move Green +10</button></p>
<p><button id='greendn100'>Move Green -100</button></p>
<span id='info'></span>
</div>
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#2.4.2/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Shape Layering Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
#buttons {
position: absolute;
left: 10px;
top: 0px;
}
button {
margin-top: 10px;
display: block;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="buttons">
<button id="toTop">
yellow z-index -2
</button>
<button id="toBottom">
yellow -9
</button>
<button id="up">
yellow z-index 1
</button>
<button id="down">
yellow z-index -5
</button>
<button id="zIndex">
Set yellow box zIndex to 3
</button>
</div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
var offsetX = 0;
var offsetY = 0;
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
var yellowBox = null;
for(var n = 0; n < 6; n++) {
// anonymous function to induce scope
(function() {
var i = n;
var box = new Konva.Rect({
x: i * 30 + 210,
y: i * 18 + 40,
width: 100,
height: 50,
fill: colors[i],
stroke: 'black',
strokeWidth: 4,
draggable: true,
name: colors[i]
});
box.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
box.on('mouseout', function() {
document.body.style.cursor = 'default';
});
if(colors[i] === 'yellow') {
yellowBox = box;
}
layer.add(box);
})();
}
stage.add(layer);
// add button event bindings
document.getElementById('toTop').addEventListener('click', function() {
yellowBox.setZIndex(-2);
layer.draw();
}, false);
document.getElementById('toBottom').addEventListener('click', function() {
yellowBox.setZIndex(-9);
layer.draw();
}, false);
document.getElementById('up').addEventListener('click', function() {
yellowBox.setZIndex(1);
layer.draw();
}, false);
document.getElementById('down').addEventListener('click', function() {
yellowBox.setZIndex(-5);
layer.draw();
}, false);
document.getElementById('zIndex').addEventListener('click', function() {
yellowBox.setZIndex(3);
layer.draw();
}, false);
</script>
</body>
</html>
Last
Fun messing with ZIndex code,
the setZIndex is all you need; It will vain the z-index inside Konva.JS
If you would prefer to be able to set the render order of nodes using arbitrary numbers (like CSS, or how it works in most game engines, etc), you can use this fork of Konva. Alternatively, you could also grab & apply just the rejected pull request for this feature if you already have a customized Konva version.
The new feature works by adding a zOrder property to all Nodes, and a special kind of group AbsoluteRenderOrderGroup that reads and understands this property for all children.

Highchart remove decimal places

I am using a highchart pie chart and displaying the data in the centre via.
function(chart1) { // on complete
var xpos = '50%';
var ypos = '50%';
var circleradius = 40;
// Render the circle
chart1.renderer.circle(xpos, ypos, circleradius).attr({
fill: '#fff',
}).add();
// Render the text
chart1.renderer.text(chart1.series[0].data[0].percentage + '%', 62, 80).css({
width: circleradius * 2,
color: '#4572A7',
fontSize: '16px',
textAlign: 'center'
}).attr({
// why doesn't zIndex get the text in front of the chart?
zIndex: 999
}).add();
});
However I would like to prevent displaying any decimal places, currently 33.33333%. I would like to display this as 33%
Is this possible, I know there is a setting allowDecimals but this did not work.
You get original percentage value from point, which it is not rounded. Use JS Math.round function:
chart1.renderer.text(Math.round(chart1.series[0].data[0].percentage) + '%', 62, 80)
.css({
width: circleradius * 2,
color: '#4572A7',
fontSize: '16px',
textAlign: 'center'
})
.attr({
zIndex: 999
})
.add();
Live demo: https://jsfiddle.net/BlackLabel/0z4hLbaw/

Make chart.renderer.path as plotline Highcharts

I just check a post regarding making a label with design using renderer.label and plotline animate (Add design to plotLabel Highcharts). My question is, Is there a way to use chart.renderer.path as the moving horizontal gridline instead of using the common plotline ? I am a bit confuse on how to use the renderer.path. Can you help me with it? Really appreciate your help with this.
const plotband = yAxis.addPlotLine({
value: 66,
color: 'red',
width: 2,
id: 'plot-line-1',
/* label: {
text: 66,
align: 'right',
y: newY,
x: 0
}*/
});
const labelOffset = 15
const plotbandLabel = this.renderer.label((66).toFixed(2), chart.plotLeft + chart.plotWidth - 8, yAxis.toPixels(66) - labelOffset, 'rect').css({
color: '#FFFFFF'
}).attr({
align: 'right',
zIndex: 99,
fill: 'rgba(0, 0, 0, 0.75)',
padding: 8
})
.add()
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
plotLine = yAxis.plotLinesAndBands[0].svgElem;
d = plotLine.d.split(' ');
newY = yAxis.toPixels(y) - d[2];
plotlabel = yAxis.plotLinesAndBands[0].label;
plotbandLabel.animate({
y: yAxis.toPixels(y) - labelOffset
}, {
duration: 400,
step: function() {
this.attr({
text: yAxis.toValue(this.y + labelOffset).toFixed(2)
})
},
complete: function() {
this.attr({
text: y.toFixed(2)
})
}
}),
plotLine.animate({
translateY: newY
}, 400);
Please see this jsfiddle I got from the previous post. http://jsfiddle.net/x8vhp0gr/
Thank you so much
I modified demo provided by you. Now, instead of adding a plot line, path is created.
pathLine = this.renderer.path([
'M',
chart.plotLeft,
initialValue,
'L',
chart.plotWidth + chart.plotLeft,
initialValue
])
.attr({
'stroke-width': 2,
stroke: 'red'
})
.add(svgGroup);
API Reference:
http://api.highcharts.com/highcharts/Renderer.path
Example:
http://jsfiddle.net/a64e5qkq/

Resources