Question

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:

enter image description here

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:

enter image description here

Any help would be greatly appreciated, cheers.

Was it helpful?

Solution

A Demo: http://jsfiddle.net/m1erickson/fu5LP/

enter image description here

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top