Just started using Kinetic.js yesterday. I want to draw some text (a label) inside a wedge so that it's placed inside the wedge with a rotation relative to the wedges' angle.
Like so:
Here's my code:
var numSegments = 5; // Number of wedges in circle
var endPos = 0;
//Center of the div container
var center = document.getElementById('canvas_container').offsetWidth * 0.5;
var centerY = document.getElementById('canvas_container').offsetHeight * 0.5;
for (var i = 0; i < numSegments; ++i) {
//Wedge + corresponding label stored in their own group
var group = new Kinetic.Group();
var wedge = new Kinetic.Wedge({
radius: center,
x: center,
y: centerY,
fill: colors[i],
stroke: '#aaaaff',
strokeWidth: 2,
angleDeg: 360 / numSegments,
rotationDeg: endPos,
});
var label = new Kinetic.Label({
x : wedge.getX(),
y : wedge.getY(),
//The rotation value is where I assume I'm going wrong, this
//Is one of many values i've tried.
rotation : (endPos == 0) ? (360 / numSegments) * 0.5 : endPos
});
label.add(new Kinetic.Text({
text : titles[i],
fontFamily: 'Calibri',
fontSize: 26,
fill : 'white',
align: 'center',
listening: false
}));
group.add(wedge);
group.add(label);
WedgeLayer.add(group);
endPos += 360 / numSegments;
}
I've hit a brick wall with this and am looking for anyone to share any insight into how to achieve the desired outcome..
So far the above results are producing this:
Any help would be greatly appreciated, cheers.
A Demo: http://jsfiddle.net/m1erickson/fu5LP/
You calculate the text offset and rotation angle like this:
Calculating the text rotation angle
Track the accumulated angle for each new wedge you add and use that accum. angle to set the text angle.
Adjusting the angle for various accumulated angles helps keep the text from appearing upside down.
If the accumulated angle is between 90 & 270 degrees then set the text angle as the accumulated angle minus 180.
If the accumulated angle is <90 or >270 then set the text angle as the accumulated angle.
Setting the text offset
The offset depends on the radius of the wedge.
But again the offset is adjusted based on the accumulated angle
If the accumulated angle is between 90 & 270 degrees then set the text offsetX to approximately the wedge radius minus 10.
If the accumulated angle is <90 or >270 then set the text offset to approximately negative half of the wedge radius.
Example code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var cx=175;
var cy=175;
var wedgeRadius=140;
var accumAngle=0;
var center = new Kinetic.Circle({
x:cx,
y:cy,
radius:5,
fill: 'red'
});
layer.add(center);
for(var i=0;i<12;i++){
newTextWedge(30,"Element # "+i);
}
function newTextWedge(angle,text){
var wedge = new Kinetic.Wedge({
x: cx,
y: cy,
radius: wedgeRadius,
angleDeg: angle,
stroke: 'gray',
strokeWidth: 1,
rotationDeg:-accumAngle+angle/2
});
layer.add(wedge);
wedge.moveToBottom();
if(accumAngle>90 && accumAngle<270){
var offset={x:wedgeRadius-10,y:7};
var textAngle=accumAngle-180;
}else{
var offset={x:-50,y:7};
var textAngle=accumAngle;
}
var text = new Kinetic.Text({
x:cx,
y:cy,
text:text,
fill: 'red',
offset:offset,
rotationDeg:textAngle
});
layer.add(text);
layer.draw();
accumAngle+=angle;
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>