3
votes

I'm reworking a application for a client, and they want to show a chart. They currently use a infragistics chart, and they would love to stop using that, but the layout must remain the same.

this is the layout they want( so labels should be visible, individual bars, ...) chart

So my first option was to try out Chart.js, but I could only get something like this:

Chart2

So basicly the only thing that needs to happen is a way to always show the labels.

The data is provided via angular and is just an array if integers. Using the following directive for the chart: http://jtblin.github.io/angular-chart.js/

My current html:

<canvas id="polar" class="chart chart-polar-area" data="data.values" labels="data.labels" width="200" height="200"
        options="{animateRotate: false}"></canvas>

I found this; How to add label in chart.js for pie chart but I couldn't get it to work

1
@Sabba first is the one I provided in the question, second gonna look into it - Kiwi
Looked into the second one, that's not how they want it, they want it like the first one, so labels should be on the border of the bars. and when the value = 0 it should still show the label - Kiwi
@Kiwi - stackoverflow.com/questions/31209359/… seems close to what you want. - potatopeelings
@potatopeelings yep that seems indeed close, but now I only need to get it to work with the angular-chart version - Kiwi

1 Answers

4
votes

Based on ChartJS: Change the positions of the tooltips


Preview

enter image description here


Converting the above to angular-chart is easy because we are only setting the options. However we need to make 2 minor changes (i.e. set chart and ctx variables from this

// THIS IS REQUIRED AND WAS ADDED
tooltipEvents: [],
onAnimationComplete: function () {
    // THESE 2 LINES ARE NEW
    var chart = this.chart;
    var ctx = this.chart.ctx;

    this.segments.forEach(function (segment) {
        var outerEdge = Chart.Arc.prototype.tooltipPosition.apply({
            // THESE 2 LINES WERE CHANGED
            x: chart.width / 2,
            y: chart.height / 2,
            startAngle: segment.startAngle,
            endAngle: segment.endAngle,
            outerRadius: segment.outerRadius * 2 + 10,
            innerRadius: 0
        })
    ...

The entire code assuming you have the library scripts included looks something like this

HTML

<div ng-app="myApp">
    <div ng-controller="myController">
        <canvas id="polar-area" class="chart chart-polar-area" data="data" labels="labels" options="options"></canvas>
    </div>
</div>

Script

angular.module('myApp', ["chart.js"]);
angular.module('myApp').controller('myController', function ($scope) {
        $scope.labels = ["Download Sales", "In-Store Sales", "Mail-Order Sales", "Tele Sales", "Corporate Sales"];
        $scope.data = [300, 500, 100, 40, 120];
        $scope.options = {
            scaleOverride: true,
            scaleStartValue: 0,
            scaleStepWidth: 40,
            scaleSteps: 10,
            tooltipEvents: [],
            onAnimationComplete: function () {
                var chart = this.chart;
                var ctx = this.chart.ctx;

                this.segments.forEach(function (segment) {
                    var outerEdge = Chart.Arc.prototype.tooltipPosition.apply({
                        x: chart.width / 2,
                        y: chart.height / 2,
                        startAngle: segment.startAngle,
                        endAngle: segment.endAngle,
                        outerRadius: segment.outerRadius * 2 + 10,
                        innerRadius: 0
                    })

                    var normalizedAngle = (segment.startAngle + segment.endAngle) / 2;
                    while (normalizedAngle > 2 * Math.PI) {
                        normalizedAngle -= (2 * Math.PI)
                    }

                    if (normalizedAngle < (Math.PI * 0.4) || (normalizedAngle > Math.PI * 1.5))
                        ctx.textAlign = "start";
                    else if (normalizedAngle > (Math.PI * 0.4) && (normalizedAngle < Math.PI * 0.6)) {
                        outerEdge.y += 5;
                        ctx.textAlign = "center";
                    }
                    else if (normalizedAngle > (Math.PI * 1.4) && (normalizedAngle < Math.PI * 1.6)) {
                        outerEdge.y - 5;
                        ctx.textAlign = "center";
                    }
                    else
                        ctx.textAlign = "end";

                    ctx.fillText(segment.label, outerEdge.x, outerEdge.y);
                })
            }
        }
    }
);

Fiddle - http://jsfiddle.net/tmzpy7Lt/