UNPKG

d3-radial-axis

Version:
148 lines (144 loc) 6.79 kB
import { lineRadial, curveNatural } from 'd3-shape'; import { scaleLinear } from 'd3-scale'; function identity(x) { return x; } function translate(x, y) { return "translate(" + x + "," + y + ")"; } function center(scale) { var offset = scale.bandwidth() / 2; if (scale.round()) offset = Math.round(offset); return function (d) { return scale(d) + offset; }; } function entering() { return !this.__axis; } function radialAxis(angleScale, startRadius, endRadius, outer) { var tickArguments = [], tickValues = null, tickFormat = null, tickSizeInner = 6, tickSizeOuter = 6, tickPadding = 12; function angleTransform(angle, radius) { return translate.apply(translate, polar2cart(angle, radius)); } function polar2cart(angle, r) { return [Math.sin(angle) * r, -Math.cos(angle) * r]; } function axis(context) { var isSpiral = endRadius !== undefined && startRadius !== endRadius; endRadius = !isSpiral ? startRadius : endRadius; var values = tickValues == null ? angleScale.ticks ? angleScale.ticks.apply(angleScale, tickArguments) : angleScale.domain() : tickValues, format = tickFormat == null ? angleScale.tickFormat ? angleScale.tickFormat.apply(angleScale, tickArguments) : identity : tickFormat, spacing = Math.max(tickSizeInner, 0) + tickPadding, radiusScale = angleScale.copy().range([startRadius, endRadius]), angleRange = angleScale.range(), anglePos = (angleScale.bandwidth ? center : identity)(angleScale.copy()), selection = context.selection ? context.selection() : context, path = selection.selectAll(".domain").data([null]), tick = selection.selectAll(".tick").data(values, angleScale).order(), tickExit = tick.exit(), tickEnter = tick.enter().append("g").attr("class", "tick"), line = tick.select("line"), text = tick.select("text"); path = path.merge(path.enter().insert("path", ".tick").attr("class", "domain").attr("stroke", "#000")); tick = tick.merge(tickEnter); line = line.merge(tickEnter.append("line").attr("stroke", "#000")); text = text.merge(tickEnter.append("text").attr("fill", "#000").attr("dy", ".35em").attr("text-anchor", "middle")); if (context !== selection) { path = path.transition(context); tick = tick.transition(context); line = line.transition(context); text = text.transition(context); tickExit = tickExit.transition(context).attr("opacity", 0).attr("transform", function (d) { return isFinite(anglePos(d)) ? angleTransform(anglePos(d), radiusScale(d)) : this.getAttribute("transform"); }); tickEnter.attr("opacity", 0).attr("transform", function (d) { var p = this.parentNode.__axis; return angleTransform(p && isFinite(p = p(d)) ? p : anglePos(d), radiusScale(d)); }); } tickExit.remove(); function getTickPath(angle, r) { return 'M' + polar2cart(angle, r + tickSizeOuter * (outer ? 1 : -1)).join(',') + 'L' + polar2cart(angle, r).join(','); } function getArcPath(startAngle, endAngle, r) { return 'M' + polar2cart(startAngle, r).join(',') + (Math.abs(endAngle - startAngle) >= 2 * Math.PI // Full-circle ? 'A' + [r, r, 0, 1, 1].concat(polar2cart(startAngle + Math.PI, r)).join(',') + 'A' + [r, r, 0, 1, 1].concat(polar2cart(startAngle, r)).join(',') : '') + 'A' + [r, r, 0, Math.abs(endAngle - startAngle) % (2 * Math.PI) > Math.PI ? 1 : 0, // Large arc flag endAngle > startAngle ? 1 : 0 // Sweep (clock-wise) flag ].concat(polar2cart(endAngle, r)).join(','); } function getSpiralPath(startAngle, endAngle, startR, endR) { var numPoints = (endAngle - startAngle) / (Math.PI * 2) * 40; // 40 points per 360deg var lineGen = lineRadial().angle(scaleLinear().range([startAngle, endAngle])).radius(scaleLinear().range([startR, endR])).curve(curveNatural); return 'M' + polar2cart(startAngle, startR).join(',') + lineGen(scaleLinear().ticks(numPoints)); } path.attr('d', (isSpiral ? getSpiralPath : getArcPath)(angleRange[0], angleRange[1], startRadius, endRadius) + getTickPath(angleRange[0], startRadius) + getTickPath(angleRange[1], endRadius)); tick.attr("opacity", 1).attr("transform", function (d) { return angleTransform(anglePos(d), radiusScale(d)); }); line.attr('x1', 0).attr('y1', 0).attr('x2', function (d) { return polar2cart(anglePos(d), tickSizeInner)[0] * (outer ? 1 : -1); }).attr('y2', function (d) { return polar2cart(anglePos(d), tickSizeInner)[1] * (outer ? 1 : -1); }); text.attr('x', function (d) { return polar2cart(anglePos(d), spacing)[0] * (outer ? 1 : -1); }).attr('y', function (d) { return polar2cart(anglePos(d), spacing)[1] * (outer ? 1 : -1); }).text(format); selection.filter(entering).attr("fill", "none").attr("font-size", 10).attr("font-family", "sans-serif"); selection.each(function () { this.__axis = anglePos; }); } axis.angleScale = function (_) { return arguments.length ? (angleScale = _, axis) : angleScale; }; axis.radius = function (_) { return arguments.length ? (startRadius = endRadius = +_, axis) : startRadius; }; axis.startRadius = function (_) { return arguments.length ? (startRadius = +_, axis) : startRadius; }; axis.endRadius = function (_) { return arguments.length ? (endRadius = +_, axis) : endRadius; }; axis.ticks = function () { return tickArguments = Array.prototype.slice.call(arguments), axis; }; axis.tickArguments = function (_) { return arguments.length ? (tickArguments = _ == null ? [] : Array.prototype.slice.call(_), axis) : tickArguments.slice(); }; axis.tickValues = function (_) { return arguments.length ? (tickValues = _ == null ? null : Array.prototype.slice.call(_), axis) : tickValues && tickValues.slice(); }; axis.tickFormat = function (_) { return arguments.length ? (tickFormat = _, axis) : tickFormat; }; axis.tickSize = function (_) { return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; }; axis.tickSizeInner = function (_) { return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; }; axis.tickSizeOuter = function (_) { return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; }; axis.tickPadding = function (_) { return arguments.length ? (tickPadding = +_, axis) : tickPadding; }; return axis; } function axisRadialInner(angleScale, startRadius, endRadius) { return radialAxis(angleScale, startRadius, endRadius, false); } function axisRadialOuter(angleScale, startRadius, endRadius) { return radialAxis(angleScale, startRadius, endRadius, true); } export { axisRadialInner, axisRadialOuter };