Skip to content

Commit

Permalink
feat(radar): Intent to ship radar.direction.clockwise (#543)
Browse files Browse the repository at this point in the history
Implementation of the radar type draw direction

Fix #464
Close #543
  • Loading branch information
netil authored Aug 16, 2018
1 parent f2fdecc commit f17fa7e
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 34 deletions.
3 changes: 3 additions & 0 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@ var demos = {
},
level: {
depth: 4
},
direction: {
clockwise: true
}
}
}
Expand Down
26 changes: 26 additions & 0 deletions spec/shape/shape.radar-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ describe("SHAPE RADAR", () => {
});

describe("default radar", () => {
let points;

before(() => {
args = {
data: {
Expand Down Expand Up @@ -112,5 +114,29 @@ describe("SHAPE RADAR", () => {
expect(old[i].height).to.be.above(resized.height);
});
});

it("set options radar.direction.clockwise=true", () => {
// retrieve point data for next the next test
points = [];

chart.$.main.selectAll(`.${CLASS.chartRadars} .${CLASS.axis} text`)
.each(function() {
points.push([+this.getAttribute("x"), +this.getAttribute("y")]);
});

args.radar.direction = {
clockwise: true
};
});

it("check for direction", () => {
const texts = chart.$.main.selectAll(`.${CLASS.chartRadars} .${CLASS.axis} text`);

texts.each(function(d, i) {
const newPoints = [+this.getAttribute("x"), +this.getAttribute("y")];

expect(points[i === 0 ? 0 : (points.length - i)]).to.deep.equal(newPoints);
});
});
});
});
5 changes: 5 additions & 0 deletions src/config/Options.js
Original file line number Diff line number Diff line change
Expand Up @@ -2644,6 +2644,7 @@ export default class Options {
* @property {Number} [radar.axis.max=undefined] The max value of axis. If not given, it'll take the max value from the given data.
* @property {Boolean} [radar.axis.line.show=true] Show or hide axis line.
* @property {Boolean} [radar.axis.text.show=true] Show or hide axis text.
* @property {Boolean} [radar.direction.clockwise=false] Set the direction to be drawn.
* @property {Number} [radar.level.depth=3] Set the level depth.
* @property {Boolean} [radar.level.show=true] Show or hide level.
* @property {Function} [radar.level.text.format=(x) => (x % 1 === 0 ? x : x.toFixed(2))] Set format function for the level value.
Expand All @@ -2660,6 +2661,9 @@ export default class Options {
* show: false
* }
* },
* direction: {
* clockwise: true
* },
* level: {
* show: false,
* text: {
Expand All @@ -2682,6 +2686,7 @@ export default class Options {
radar_level_text_format: x => (x % 1 === 0 ? x : x.toFixed(2)),
radar_level_text_show: true,
radar_size_ratio: 0.87,
radar_direction_clockwise: false,

/**
* Show rectangles inside the chart.<br><br>
Expand Down
73 changes: 39 additions & 34 deletions src/shape/radar.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import {
} from "d3-array";
import ChartInternal from "../internals/ChartInternal";
import CLASS from "../config/classes";
import {extend, isEmpty} from "../internals/util";
import {extend, isDefined, isEmpty, isUndefined, toArray} from "../internals/util";

/**
* Get the position value
* @param {Boolean} isClockwise If the direction is clockwise
* @param {String} type Coordinate type 'x' or 'y'
* @param {Number} edge Number of edge
* @param {Number} pos The indexed position
Expand All @@ -24,11 +25,12 @@ import {extend, isEmpty} from "../internals/util";
* @return {number}
* @private
*/
function getPosition(type, edge, pos, range, ratio = 1) {
function getPosition(isClockwise, type, edge, pos, range, ratio) {
const index = isClockwise && pos > 0 ? edge - pos : pos;
const r = 2 * Math.PI;
const func = type === "x" ? Math.sin : Math.cos;

return range * (1 - ratio * func(pos * r / edge));
return range * (1 - ratio * func(index * r / edge));
}

// cache key
Expand Down Expand Up @@ -80,6 +82,25 @@ extend(ChartInternal.prototype, {
$$.generateRadarPoints();
},

getRadarPosition(type, index, range, ratio) {
const $$ = this;
const config = $$.config;
const [width, height] = $$.getRadarSize();
const edge = config.axis_x_categories.length;
const isClockwise = config.radar_direction_clockwise;

const pos = toArray(type).map(v => getPosition(
isClockwise,
v,
edge,
index,
isDefined(range) ? range : (type === "x" ? width : height),
ratio || config.radar_size_ratio
));

return pos.length === 1 ? pos[0] : pos;
},

/**
* Generate data points
* @private
Expand All @@ -89,29 +110,21 @@ extend(ChartInternal.prototype, {
const config = $$.config;
const targets = $$.data.targets;

const edge = config.axis_x_categories.length;
const [width, height] = $$.getRadarSize();
const points = $$.getCache(cacheKey) || {};
const size = points.size;
const size = points._size;

// recalculate position only when the previous dimension has been changed
if (!size || (size.width !== width && size.height !== height)) {
const getRatio = v => (parseFloat(Math.max(v, 0)) / $$.maxValue) * config.radar_size_ratio;

targets.forEach(d => {
const point = [];

d.values.forEach((v, i) => {
point.push([
getPosition("x", edge, i, width, getRatio(v.value)),
getPosition("y", edge, i, height, getRatio(v.value))
]);
});

points[d.id] = point;
points[d.id] = d.values.map((v, i) => (
$$.getRadarPosition(["x", "y"], i, undefined, getRatio(v.value))
));
});

points.size = {width, height};
points._size = {width, height};
$$.addCache(cacheKey, points);
}
},
Expand Down Expand Up @@ -166,11 +179,10 @@ extend(ChartInternal.prototype, {

// Generate points
const points = levelData.map(v => {
const pos = [];

d3Range(0, edge).forEach(i => {
pos.push(`${getPosition("x", edge, i, levelRatio[v])},${getPosition("y", edge, i, levelRatio[v])}`);
});
const range = levelRatio[v];
const pos = d3Range(0, edge).map(i => (
$$.getRadarPosition(["x", "y"], i, range, 1)).join(",")
);

return pos.join(" ");
});
Expand Down Expand Up @@ -214,23 +226,16 @@ extend(ChartInternal.prototype, {
// update level text position
if (showText) {
radarLevels.selectAll("text")
.attr("x", function(d) {
return +this.textContent === 0 ?
width : points[d].split(",")[0];
})
.attr("y", function() {
return +this.textContent === 0 ? height : 0;
});
.attr("x", d => (isUndefined(d) ? width : points[d].split(",")[0]))
.attr("y", d => (isUndefined(d) ? height : 0));
}
},

updateRadarAxes() {
const $$ = this;
const config = $$.config;
const [width, height] = $$.getRadarSize();
const ratio = config.radar_size_ratio;
const categories = config.axis_x_categories;
const edge = categories.length;

let axis = $$.radars.axes.selectAll("g")
.data(categories);
Expand All @@ -250,8 +255,8 @@ extend(ChartInternal.prototype, {
axis.select("line")
.attr("x1", width)
.attr("y1", height)
.attr("x2", (d, i) => getPosition("x", edge, i, width, ratio))
.attr("y2", (d, i) => getPosition("y", edge, i, height, ratio));
.attr("x2", (d, i) => $$.getRadarPosition("x", i))
.attr("y2", (d, i) => $$.getRadarPosition("y", i));
}

// axis text
Expand All @@ -261,8 +266,8 @@ extend(ChartInternal.prototype, {
.attr("dy", ".5em")
.text(d => d)
.datum((d, i) => ({index: i}))
.attr("x", (d, i) => getPosition("x", edge, i, width))
.attr("y", (d, i) => getPosition("y", edge, i, height));
.attr("x", (d, i) => $$.getRadarPosition("x", i, undefined, 1))
.attr("y", (d, i) => $$.getRadarPosition("y", i, undefined, 1));
}

$$.bindEvent();
Expand Down

0 comments on commit f17fa7e

Please sign in to comment.