I’ve created an interactive pie chart using James Alvarez’s Draggable Pie Chart plugin I found on Github. I decided to use an image as the label for each pie piece instead of text. I have the pie chart displaying and functioning as intended, but I’m having issues with how the label images are displaying.
The issue is that the label images have to be rotate/translated along with the pie pieces so they have the proper positions, which results in the logos displaying upside down.
What I would like is for everything to stay as-is, but for the logos to always be right-side-up. Is this possible in the canvas element?
Here’s my code: https://jsfiddle.net/uwx3vv7c/
HTML:
<div id="piechart-controls">
<canvas id="piechart" width="400" height="400">Your browser is too old!</canvas>
<div>
<div class="percentWrapper" style="display: inline-block;">
<img src="https://cdn4.iconfinder.com/data/icons/seo-web-15/465/web-user-interface_49-128.png">
<span class="mixPercentage">33%</span>
</div>
<div class="percentWrapper" style="display: inline-block;">
<img src="https://cdn3.iconfinder.com/data/icons/picons-social/57/46-facebook-128.png">
<span class="mixPercentage">33%</span>
</div>
<div class="percentWrapper" style="display: inline-block;">
<img src="https://cdn3.iconfinder.com/data/icons/picons-social/57/43-twitter-128.png">
<span class="mixPercentage">34%</span>
</div>
</div>
</div>
JS:
(function($){
$(window).ready(setupPieChart);
function setupPieChart() {
let proportions = [
{ proportion: 45, format: { image: "https://cdn4.iconfinder.com/data/icons/seo-web-15/465/web-user-interface_49-128.png" }},
{ proportion: 30, format: { image: "https://cdn3.iconfinder.com/data/icons/picons-social/57/46-facebook-128.png" }},
{ proportion: 25, format: { image: "https://cdn3.iconfinder.com/data/icons/picons-social/57/43-twitter-128.png" }}
];
let setup = {
canvas: document.getElementById('piechart'),
radius: 0.9,
collapsing: false,
proportions: proportions,
drawSegment: drawSegmentOutlineOnly,
onchange: onPieChartChange,
minAngle: 1.575
};
let newPie = new DraggablePiechart(setup);
// initial drawing function for pie chart
function drawSegmentOutlineOnly(context, piechart, centerX, centerY, radius, startingAngle, arcSize, format, collapsed) {
if (collapsed) { return; }
// Draw segment
context.save();
let endingAngle = startingAngle + arcSize;
context.beginPath();
context.moveTo(centerX, centerY);
context.arc(centerX, centerY, radius, startingAngle, endingAngle, false);
context.closePath();
context.fillStyle = '#666';
context.fill();
context.stroke();
context.restore();
// Draw image
context.save();
context.translate(centerX, centerY);
context.rotate(startingAngle);
let iconHeight = Math.floor(context.canvas.height / 5);
let iconWidth = Math.floor(context.canvas.width / 5);
let dx = (radius / 2) - (iconWidth/2);
let dy = (radius / 2) - (iconHeight/2);
let flavorImage = new Image();
flavorImage.src = format.image;
context.drawImage(flavorImage, dx, dy, iconWidth, iconHeight);
context.restore();
}
// update the percentages when the pieces are adjusted
function onPieChartChange(piechart) {
let percentages = piechart.getAllSliceSizePercentages();
let percentLabels = $(".mixPercentage");
for (let i = 0; i < percentages.length; i++) {
percentLabels.eq(i).html(percentages[i].toFixed(0) + "%");
}
}
}
})(jQuery);
I’ve tried several things, including:
-
not rotating and translating the images, but that causes them to not display properly
-
using the images as background patterns instead of actually drawing them as part of the canvas context, but it either tiles the image or stretches it to the size of the full pie chart.
Bonus question – any way to center them vertically and horizontally in the pie pieces?
2
Answers
Draw scale, rotated image via its center.
To draw an image rotated and scaled use the following function
If you need to mirror the image, the following function will help, just set the scale for the axis of the image to flip to negative eg
drawImage(ctx,image,100,100,1,-1,0);
draws image upside down.To draw at a center of a pie seg that you draw the outside curve with
Use the first function
Your library gives you the starting angle that you will have to use with the
arc()
method. It also gives you the arcLength and the center coordinates.You already seem to be able to draw the arc segments, but to draw your images, you will need to do some tweaks.
First, you will move your context’s matrix to the center of the pie chart,
then you will find the rotation angle so that you face the middle of the current segment, then move on the Y axis to be in the center position of your image, finally, you will rotate by the inverse of the segment’s rotation to make your images face normally.