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>
Related
I'm trying to animate the weighing machine i.e. if the user drag and drops the balls on the weights of the machine, the machine should move according to the weights of the balls afterward.
The weighing machine would not be animated from the start but will move when the user puts some balls on either side of the machine.
I'm using konvajs, how can I make this possible?
I used the following approach to solve the above-given problem.
function createCanvas(){
var width = window.innerWidth;
var height = window.innerHeight;
var leftBalls = 0;
var rightBalls = 0;
var tries = 0;
//Initialize stage
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
//Initialize Layer
var layer = new Konva.Layer();
stage.add(layer)
//Create output
var output = new Konva.Text({
x: (width/2)-134,
y: 140,
fontSize: 35,
fontFamily: 'Calibri',
});
layer.add(output);
// win text
var wintext = new Konva.Text({
x: (width/2)-134,
y: 70,
fontSize: 35,
fontFamily: 'Calibri',
});
layer.add(wintext);
// tries box
var triesText1 = new Konva.Text({
x: width-100,
y: 4,
text: "No. of tries",
fontSize: 20,
fontFamily: 'Calibri',
});
layer.add(triesText1);
var triesBox = new Konva.Rect({
x: width-90,
y: 25,
width: 70,
height: 50,
fill: 'white',
stroke: 'black',
strokeWidth: 3,
});
layer.add(triesBox);
var triesText2 = new Konva.Text({
x: width-62,
y: 36,
text: '0',
fontSize: 30,
fontFamily: 'Calibri',
});
layer.add(triesText2);
//Create Weighing Machine
var oval = new Konva.Ellipse({
x: ((width/2))+15,
y: (height-170),
radiusX: 3,
radiusY: 65,
fill: 'black',
stroke: 'black',
strokeWidth: 3,
});
layer.add(oval);
var ovalTwo = new Konva.Ellipse({
x: ((width/2))+15,
y: (height-200),
radiusX: 100,
radiusY: 3,
fill: 'black',
stroke: 'black',
strokeWidth: 3,
});
//layer.add(ovalTwo);
var LineOne = new Konva.Line({
x: (width/2)-47,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,32,75],
});
//layer.add(LineOne);
var LineTwo = new Konva.Line({
x: (width/2)-47,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,-33,73],
});
//layer.add(LineTwo);
var semiCircle1= new Konva.Arc({
x: (width/2)-48,
y: height-130,
innerRadius: 30,
outerRadius: 40,
angle: 180,
fill: 'black',
stroke: 'black',
strokeWidth: 1,
});
//layer.add(semiCircle);
var LineThree = new Konva.Line({
x: (width/2)+91,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,32,75],
});
//layer.add(LineThree);
var LineFour = new Konva.Line({
x: (width/2)+91,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,-33,73],
});
//layer.add(LineFour);
var semiCircle2= new Konva.Arc({
x: (width/2)+89,
y: height-130,
innerRadius: 30,
outerRadius: 40,
angle: 180,
fill: 'black',
stroke: 'black',
strokeWidth: 1,
});
//layer.add(semiCircle);
var wUpperPart = new Konva.Group({
x: 0,
y: 0,
});
wUpperPart.add(semiCircle1,semiCircle2,LineOne,LineTwo,LineThree,LineFour,ovalTwo);
layer.add(wUpperPart)
function moveMachineLeft(){
var tween = new Konva.Tween({
node: wUpperPart,
duration: 2,
rotation: -1.7,
easing: Konva.Easings.BackEaseOut,
onFinish: function () {
writeMessage('tween finished!');
},
});
setTimeout(function () {
tween.play();
}, 10);
}
function moveMachineRight(){
var tween = new Konva.Tween({
node: wUpperPart,
duration: 2,
rotation: 1.7,
easing: Konva.Easings.BackEaseOut,
onFinish: function () {
writeMessage('tween finished!');
},
});
setTimeout(function () {
tween.play();
}, 100);
}
//Create circle
function createCircle(x, y, fill, id) {
var circle = new Konva.Circle({
x: x,
y: y,
radius: 13,
fill: fill,
stroke: 'black',
strokeWidth: 1,
id: id,
draggable: true,
});
layer.add(circle);
var startPos = 0;
circle.on('dragstart',function() {
startPos = stage.getPointerPosition();
});
circle.on('dragend', function() {
const pointerPos = stage.getPointerPosition();
console.log(pointerPos);
console.log((width/2)+70);
console.log((width/2)+111);
if ((pointerPos.x <= (width/2)-33 && pointerPos.x >= (width/2)-85) &&
pointerPos.y<=height-103 && pointerPos.y>=height-155){
leftBalls = circle.id() + leftBalls;
console.log(leftBalls);
}
else if ((pointerPos.x >= (width/2)+67 && pointerPos.x <= (width/2)+111) &&
(pointerPos.y<=height-103 && pointerPos.y>=height-155)){
rightBalls = rightBalls + circle.id();
console.log(rightBalls);
}
if (((startPos.x >= (width/2)+67 && startPos.x <= (width/2)+111) &&
startPos.y<=height-103 && startPos.y>=height-150) &&
!((pointerPos.x >= (width/2)+67 && pointerPos.x <= (width/2)+111) &&
(pointerPos.y<=height-103 && pointerPos.y>=height-155))){
rightBalls = rightBalls - circle.id();
console.log(rightBalls);
}
if (((startPos.x <= (width/2)-33 && startPos.x >= (width/2)-85) &&
startPos.y<=height-103 && startPos.y>=height-150) &&
!((pointerPos.x <= (width/2)-33 && pointerPos.x >= (width/2)-85) &&
(pointerPos.y<=height-103 && pointerPos.y>=height-155))){
leftBalls = leftBalls - circle.id();
console.log(leftBalls);
}
});
return circle;
}
//Create balls
var id = 0;
var thousands = {};
var x = []
var boolean = [];
var i = 0;
for (i = 320; i < 470; i += 30){
x.push(i)
boolean.push(false)
circle = createCircle(i, 70, '#FF0000', 1);
thousands[id] = circle;
id = id + 1;
}
x.push(i);
circle = createCircle(i, 70, '#FF0000', 2);
thousands[id] = circle;
id = id + 1;
i = i + 30;
for (; i < 540; i += 30){
x.push(i)
boolean.push(false)
circle = createCircle(i, 70, '#FF0000', 1);
thousands[id] = circle;
id = id + 1;
}
document.getElementById('calculate').addEventListener(
'click',
function () {
if (leftBalls>rightBalls){
output.text("Left weight is heavier!");
if (leftBalls==2 && rightBalls==1){
wintext.text("You Won!");
}
tries = tries + 1;
triesText2.text(tries);
}
else if (leftBalls<rightBalls){
output.text("Right weight is heavier!");
if (rightBalls==2 && leftBalls==1){
wintext.text("You Won!");
}
tries = tries + 1;
triesText2.text(tries);
}
else if (leftBalls==rightBalls){
output.text("No weight is heavier!");
tries = tries + 1;
triesText2.text(tries);
}
else if ((leftBalls==0) && (rightBalls==0)){
output.text("No weight is filled!");
}
layer.draw();
},
false
);
layer.draw();
}
createCanvas();
document.getElementById('restart').addEventListener(
'click',
function () {
createCanvas();
},
false
);
I'm creating a timeline with Konva and the entire timeline (stage) is draggable on all directions but I have an axis with all the years of the timeline (Konva group) that I want to restrict its movement so that it only moves horizontally.
I can't use dragBoundFunc as it will restrict the movement on all nodes of the timeline.
I tried to change the position of the element using the dragmove event:
stage.on("dragmove", function(evt) {
xaxis.y(0);
});
But the xaxis still moves on all direction while dragging the stage.
I could also use different draggable layers for the axis and the timeline itself, but then when I drag the axis it wouldn't move the timeline and the same if I move the timeline.
As the simplest solution, you can just make sure that the absolute position of your timelime group is the same:
stage.on("dragmove", function(evt) {
// read absolute position
const oldAbs = xaxis.absolutePosition();
// set new absolute position, but make sure x = 0
xaxis.absolutePosition({
x: oldAbs.x,
y: 0
});
});
Here is a slightly more capable version that allows vertical drag of the event layer whilst keeping the time line axis visible for reference. This uses two layers - one to act as the background containing the time line and grid, whilst the second shows the events.
The key technique here is using the dragMove event listener on the draggable event layer to move the background layer in sync horizontally but NOT vertically. Meanwhile the event layer is also constrained with a dragBound function to stop silly UX.
An improvement would be to add clipping to the event layer so that when dragged down it would not obscure the timeline.
var stageWidth = 800,
stageHeight = 300,
timeFrom = 1960,
timeTo = 2060,
timeRange = timeTo - timeFrom,
timeLineWidth = 1000,
timeSteps = 20, // over 100 yrs = 5 year intervals
timeInt = timeRange / timeSteps,
timeLineStep = timeLineWidth / timeSteps,
yearWidth = timeLineWidth / timeRange,
plotHeight = 500,
events = [{
date: 1964,
desc: 'Born',
dist: 10
},
{
date: 1966,
desc: 'England win world cup - still celebrating !',
dist: 20
},
{
date: 1968,
desc: 'Infant school',
dist: 30
},
{
date: 1975,
desc: 'Secondary school',
dist: 50
},
{
date: 1981,
desc: 'Sixth form',
dist: 7
},
{
date: 1983,
desc: 'University',
dist: 30
},
{
date: 1986,
desc: 'Degree, entered IT career',
dist: 50
},
{
date: 1990,
desc: 'Marriage #1',
dist: 0
},
{
date: 1996,
desc: 'Divorce #1',
dist: 0
},
{
date: 1998,
desc: 'Marriage #2 & Son born',
dist: 90
},
{
date: 2000,
desc: 'World did not end',
dist: 20
},
{
date: 2025,
desc: 'Retired ?',
dist: 0
},
{
date: 2044,
desc: 'Enters Duncodin - retirement home for IT workers',
dist: 0
},
{
date: 2054,
desc: 'Star dust',
dist: 0
}
]
function setup() {
// Set up a stage and a shape
stage = new Konva.Stage({
container: 'konva-stage',
width: stageWidth,
height: stageHeight
});
// bgLayer is the background with the grid, timeline and date text.
var bgLayer = new Konva.Layer({
draggable: false
})
stage.add(bgLayer);
for (var i = 0, max = timeSteps; i < max; i = i + 1) {
bgLayer.add(new Konva.Line({
points: [(i * timeLineStep) + 0.5, 0, (i * timeLineStep) + .5, plotHeight],
stroke: 'cyan',
strokeWidth: 1
}))
bgLayer.add(new Konva.Text({
x: (i * timeLineStep) + 4,
y: 260,
text: timeFrom + (timeInt * i),
fontSize: 12,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: 90,
listening: false
}));
}
for (var i = 0, max = plotHeight; i < max; i = i + timeLineStep) {
bgLayer.add(new Konva.Line({
points: [0, i + 0.5, timeLineWidth, i + .5],
stroke: 'cyan',
strokeWidth: 1
}))
}
// add timeline
var timeLine = new Konva.Rect({
x: 0,
y: 245,
height: 1,
width: timeLineWidth,
fill: 'magenta',
listening: false
});
bgLayer.add(timeLine)
// eventLayer contains only the event link line and text.
var eventLayer = new Konva.Layer({
draggable: true,
// the dragBoundFunc returns an object as {x: val, y: val} in which the x is constricted to stop
// the user dragging out of sight, and the y is not allowed to change.
// ! position of bgLayer is moved in x axis in sync with eventLayer via dragMove event
dragBoundFunc: function(pos) {
return {
x: function() {
var retX = pos.x;
if (retX > 20) { // if the left exceeds 20px from left edge of stage
retX = 20;
} else if (retX < (stageWidth - (timeLineWidth + 50))) { // if the right exceeds 50 px from right edge of stage
retX = stageWidth - (timeLineWidth + 50);
}
return retX;
}(),
y: function() {
var retY = pos.y;
if (retY < 0) {
retY = 0;
} else if (retY > 200) {
retY = 200;
}
return retY;
}()
};
}
});
stage.add(eventLayer);
// ! position of bgLayer is moved in x axis in sync with eventLayer via dragMove event of eventLayer.
eventLayer.on('dragmove', function() {
var pos = eventLayer.position();
var bgPos = bgLayer.position();
bgLayer.position({
x: pos.x,
y: bgPos.y
}); // <--- move the bgLayer in sync with the event eventLayer.
stage.draw()
});
for (var i = 0, max = events.length; i < max; i = i + 1) {
var event = events[i];
var link = new Konva.Rect({
x: yearWidth * (event.date - timeFrom),
y: 200 - event.dist,
width: 1,
height: 55 + event.dist,
fill: 'magenta',
listening: false
});
eventLayer.add(link)
var eventLabel = new Konva.Text({
x: yearWidth * (event.date - timeFrom) - 5,
y: 190 - event.dist,
text: event.date + ' - ' + event.desc,
fontSize: 16,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: -90,
listening: false
});
eventLayer.add(eventLabel);
var dragRect = new Konva.Rect({
x: 0,
y: 0,
width: timeLineWidth,
height: 500,
opacity: 0,
fill: 'cyan',
listening: true
});
eventLayer.add(dragRect);
dragRect.moveToTop()
}
stage.draw()
}
var stage, eventLayer;
setup()
.konva-stage {
width: 100%;
height: 100%;
<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/4.0.13/konva.js"></script>
<p>Drag the timeline left & right AND up & down...</p>
<div id="konva-stage"></div>
Just for fun, a stripped down version of my answers showing the ondrag() function without all the timeline frills.
var stage;
function setup() {
// Set up a stage and a shape
stage = new Konva.Stage({
container: 'konva-stage',
width: 600,
height: 300
});
// layer1.
var layer1 = new Konva.Layer({
draggable: false
})
stage.add(layer1);
var ln1 = new Konva.Line({
points: [10, 0, 10, 20, 10, 10, 0, 10, 20, 10],
stroke: 'cyan',
strokeWidth: 4
});
layer1.add(ln1);
var layer2 = new Konva.Layer({
draggable: true,
});
stage.add(layer2);
var ln2 = new Konva.Line({
points: [10, 0, 10, 20, 10, 10, 0, 10, 20, 10],
stroke: 'magenta',
strokeWidth: 4
});
layer2.add(ln2);
// position the crosses on the canvas
ln1.position({
x: 100,
y: 80
});
ln2.position({
x: 100,
y: 40
});
// ! position of layer1 is moved in x axis in sync with layer2 via dragMove event of layer2.
layer2.on('dragmove', function() {
var pos = layer2.position();
var bgPos = layer1.position();
layer1.position({
x: pos.x,
y: bgPos.y
}); // <--- move layer1 in sync with layer2.
stage.draw()
});
stage.draw()
}
setup()
.konva-stage {
width: 100%;
height: 100%;
<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/4.0.13/konva.js"></script>
<p>Drag the upper cross - only one moves vertically whilst the other is contrained in the y-axis. Both move in sync on the x-axis</p>
<div id="konva-stage"></div>
It is not entirely clear what you are asking but I have assumed you want to constrain the drag of the timeline so that it gives good UX. See working snippet below. The majority of the code is setup of the timeline. The important piece is
Include a rect covering the entire timeline that has zero opacity and is listening for mouse events.
Provide the layer with a dragBoundFunc that returns an object as {x: val, y: val} in which the x is constricted to stop the user dragging out of sight horizontally, and the y is not allowed to change. If you think of the rect and the stage as rectangles then the math is not difficult to comprehend. If your timeline is vertical, swap the x & y behaviour.
var stageWidth = 800,
timeFrom = 1960,
timeTo = 2060,
range = timeTo - timeFrom,
timeLineWidth = 1000;
yearWidth = timeLineWidth / range,
events = [{
date: 1964,
desc: 'Born'
},
{
date: 1968,
desc: 'Infant school'
},
{
date: 1975,
desc: 'Secondary school'
},
{
date: 1981,
desc: 'Sixth form'
},
{
date: 1983,
desc: 'University'
},
{
date: 1986,
desc: 'Degree, entered IT career'
},
{
date: 1990,
desc: 'Marriage #1'
},
{
date: 1998,
desc: 'Marriage #2'
},
{
date: 1999,
desc: 'Son born'
},
{
date: 2025,
desc: 'Retired ?'
},
{
date: 2044,
desc: 'Enters Duncodin - retirement home for IT workers'
},
{
date: 2054,
desc: 'Star dust'
}
]
function setup() {
// Set up a stage and a shape
stage = new Konva.Stage({
container: 'konva-stage',
width: stageWidth,
height: 500
});
layer = new Konva.Layer({
draggable: true,
// the dragBoundFunc returns an object as {x: val, y: val} in which the x is constricted to stop
// the user dragging out of sight, and the y is not allowed to change.
dragBoundFunc: function(pos) {
return {
x: function() {
retX = pos.x;
if (retX > 20) {
retX = 20;
} else if (retX < (stageWidth - (timeLineWidth + 50))) {
retX = stageWidth - (timeLineWidth + 50);
}
return retX;
}(),
y: this.absolutePosition().y
};
}
});
stage.add(layer);
// add timeline
var timeLine = new Konva.Rect({
x: 0,
y: 245,
height: 10,
width: timeLineWidth,
fill: 'magenta',
listening: false
});
layer.add(timeLine)
for (var i = 0, max = events.length; i < max; i = i + 1) {
var event = events[i];
var link = new Konva.Rect({
x: yearWidth * (event.date - timeFrom),
y: 200,
width: 5,
height: 55,
fill: 'magenta',
listening: false
});
layer.add(link)
var timeLabel = new Konva.Text({
x: yearWidth * (event.date - timeFrom) + 10,
y: 265,
text: event.date,
fontSize: 16,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: 90,
listening: false
});
layer.add(timeLabel);
var eventLabel = new Konva.Text({
x: yearWidth * (event.date - timeFrom) - 5,
y: 190,
text: event.desc,
fontSize: 16,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: -90,
listening: false
});
layer.add(eventLabel);
var dragRect = new Konva.Rect({
x: 0,
y: 0,
width: timeLineWidth,
height: 500,
opacity: 0,
fill: 'cyan',
listening: true
});
layer.add(dragRect);
dragRect.moveToTop()
}
stage.draw()
}
var stage, layer;
setup()
.konva-stage {
width: 100%;
height: 100%;
<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/4.0.13/konva.js"></script>
<p>Drag the timeline...</p>
<div id="konva-stage"></div>
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
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/
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/