Skip to content

Commit

Permalink
Add an option for radar chart to have offsetAngle. Issue chartjs#1012
Browse files Browse the repository at this point in the history
  • Loading branch information
slinhart committed Jul 17, 2016
1 parent ff2a2bf commit 14976b5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 18 deletions.
1 change: 1 addition & 0 deletions docs/05-Radar-Chart.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ scale | Object | [See Scales](#scales) and [Defaults for Radial Linear Scale](#s
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
*elements*.line | Object | | Options for all line elements used on the chart, as defined in the global elements, duplicated here to show Radar chart specific defaults.
*elements.line*.lineTension | Number | 0 | Tension exhibited by lines when calculating splineCurve. Setting to 0 creates straight lines.
offsetAngle | Number | 0 | The number of degrees to rotate the chart clockwise.

You can override these for your `Chart` instance by passing a second argument into the `Radar` method as an object with the keys you want to override.

Expand Down
44 changes: 26 additions & 18 deletions src/scales/scale.radialLinear.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,13 @@ module.exports = function(Chart) {
// 5px to space the text slightly out - similar to what we do in the draw function.
pointPosition = this.getPointPosition(i, largestPossibleRadius);
textWidth = this.ctx.measureText(this.pointLabels[i] ? this.pointLabels[i] : '').width + 5;
if (i === 0 || i === this.getValueCount() / 2) {
// If we're at index zero, or exactly the middle, we're at exactly the top/bottom

// Add quarter circle to make degree 0 mean top of circle
var angleRadians = this.getIndexAngle(i) + (Math.PI / 2);
var angle = (angleRadians * 360 / (2 * Math.PI)) % 360;

if (angle === 0 || angle === 180) {
// At angle 0 and 180, we're at exactly the top/bottom
// of the radar chart, so text will be aligned centrally, so we'll half it and compare
// w/left and right text sizes
halfTextWidth = textWidth / 2;
Expand All @@ -184,13 +189,13 @@ module.exports = function(Chart) {
furthestLeft = pointPosition.x - halfTextWidth;
furthestLeftIndex = i;
}
} else if (i < this.getValueCount() / 2) {
} else if (angle < 180) {
// Less than half the values means we'll left align the text
if (pointPosition.x + textWidth > furthestRight) {
furthestRight = pointPosition.x + textWidth;
furthestRightIndex = i;
}
} else if (i > this.getValueCount() / 2) {
} else {
// More than half the values means we'll right align the text
if (pointPosition.x - textWidth < furthestLeft) {
furthestLeft = pointPosition.x - textWidth;
Expand Down Expand Up @@ -227,9 +232,14 @@ module.exports = function(Chart) {

getIndexAngle: function(index) {
var angleMultiplier = (Math.PI * 2) / this.getValueCount();
// Start from the top instead of right, so remove a quarter of the circle
var offsetAngle = this.chart.options && this.chart.options.offsetAngle ?
this.chart.options.offsetAngle :
0;

var offsetAngleRadians = offsetAngle * Math.PI * 2 / 360;

return index * angleMultiplier - (Math.PI / 2);
// Start from the top instead of right, so remove a quarter of the circle
return index * angleMultiplier - (Math.PI / 2) + offsetAngleRadians;
},
getDistanceFromCenterForValue: function(value) {
var me = this;
Expand Down Expand Up @@ -373,26 +383,24 @@ module.exports = function(Chart) {
ctx.font = pointLabeFont;
ctx.fillStyle = pointLabelFontColor;

var pointLabels = me.pointLabels,
labelsCount = pointLabels.length,
halfLabelsCount = pointLabels.length / 2,
quarterLabelsCount = halfLabelsCount / 2,
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
if (i === 0) {
ctx.textAlign = 'center';
} else if (i === halfLabelsCount) {
var pointLabels = me.pointLabels;

// Add quarter circle to make degree 0 mean top of circle
var angleRadians = this.getIndexAngle(i) + (Math.PI / 2);
var angle = (angleRadians * 360 / (2 * Math.PI)) % 360;

if (angle === 0 || angle === 180) {
ctx.textAlign = 'center';
} else if (i < halfLabelsCount) {
} else if (angle < 180) {
ctx.textAlign = 'left';
} else {
ctx.textAlign = 'right';
}

// Set the correct text baseline based on outer positioning
if (exactQuarter) {
if (angle === 90 || angle === 270) {
ctx.textBaseline = 'middle';
} else if (upperHalf) {
} else if (angle > 270 || angle < 90) {
ctx.textBaseline = 'bottom';
} else {
ctx.textBaseline = 'top';
Expand Down

0 comments on commit 14976b5

Please sign in to comment.