Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var d3co = {};
- (function(ns){
- ns.axis = axis;
- ns.axes = axes;
- function axis() {
- var scale = d3.scale.linear(),
- orient = Math.PI/2, // default: "bottom"
- tickAngle = Math.PI/2, // angle between axis and ticks (affects labels and legend too)
- shift = 0, // translation along ticks
- legend = null,
- tickMajorSize = 6,
- tickMinorSize = 6,
- tickEndSize = 6,
- tickPadding = 3,
- tickArguments_ = [10],
- tickValues = null,
- tickFormat_,
- tickSubdivide = 0;
- function axis(g) {
- g.each(function() {
- var g = d3.select(this);
- // Ticks, or domain values for ordinal scales.
- var ticks = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain()) : tickValues,
- tickFormat = tickFormat_ == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String) : tickFormat_;
- // Minor ticks.
- var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide),
- subtick = g.selectAll(".minor").data(subticks, String),
- subtickEnter = subtick.enter().insert("line", "g").attr("class", "tick minor").style("opacity", 1e-6),
- subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(),
- subtickUpdate = d3.transition(subtick).style("opacity", 1);
- // Major ticks.
- var tick = g.selectAll("g").data(ticks, String),
- tickEnter = tick.enter().insert("g", "path").style("opacity", 1e-6),
- tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(),
- tickUpdate = d3.transition(tick).style("opacity", 1),
- tickTransform;
- // Domain.
- var range = d3_scaleRange(scale),
- path = g.selectAll(".domain").data([0]),
- pathEnter = path.enter().append("path").attr("class", "domain"),
- pathUpdate = d3.transition(path);
- // Geometry for ticks, labels, legend
- var U = d3_svg_axisUnitVector(orient),
- tickU = d3_svg_axisUnitVector(orient + tickAngle),
- labelDist = Math.max(tickMajorSize, 0) + tickPadding,
- m = ((tickAngle / (2*Math.PI)) % 1 + 1) % 1 < .5 ? -1: 1,
- labelU = { x: (tickU.x+m*U.y)/2, y: (tickU.y-m*U.x)/2 };
- var halfRange = (range[0] + range[1])/2,
- orientDeg = orient * 180 / Math.PI,
- legendDist = labelDist + 3*tickPadding,
- leg = g.selectAll("g.axisLegend").data([legend]);
- // Stash a snapshot of the new scale, and retrieve the old snapshot.
- var scale1 = scale.copy(),
- scale0 = this.__chart__ || scale1;
- this.__chart__ = scale1;
- // shift group
- d3.transition(g).attr("transform", "translate("+shift*tickU.x+","+shift*tickU.y+")");
- tickEnter.append("line").attr("class", "tick");
- tickEnter.append("text");
- subtickEnter.attr("x2", tickMinorSize * tickU.x).attr("y2", tickMinorSize * tickU.y);
- subtickUpdate.attr("x2", tickMinorSize * tickU.x).attr("y2", tickMinorSize * tickU.y);
- tickEnter.select("line").attr("x2", tickMajorSize * tickU.x).attr("y2", tickMajorSize * tickU.y);
- tickEnter.select("text").attr("x", labelDist * labelU.x).attr("y", labelDist * labelU.y);
- tickUpdate.select("line").attr("x2", tickMajorSize * tickU.x).attr("y2", tickMajorSize * tickU.y);
- tickUpdate.select("text").text(tickFormat)
- .attr("x", labelDist * labelU.x).attr("y", labelDist * labelU.y).attr("dy", (labelU.y + 1) * .35 + "em")
- .attr("text-anchor", (Math.abs(labelU.y) > .5) ? "middle" : ((labelU.x > 0) ? "start": "end") );
- pathUpdate.attr("d", " M " + (range[0]*U.x + tickEndSize*tickU.x) + " " + (range[0]*U.y + tickEndSize*tickU.y) + " L " + range[0]*U.x + " " + range[0]*U.y + " L " + range[1]*U.x + " " + range[1]*U.y + " " + (range[1]*U.x + tickEndSize*tickU.x) + " " + (range[1]*U.y + tickEndSize*tickU.y));
- tickTransform = function(selection, scale) {
- selection.attr("transform", function(d) { var r = scale(d); return "translate("+r*U.x+","+r*U.y+")"; });
- };
- // For quantitative scales:
- // - enter new ticks from the old scale
- // - exit old ticks to the new scale
- if (scale.ticks) {
- tickEnter.call(tickTransform, scale0);
- tickUpdate.call(tickTransform, scale1);
- tickExit.call(tickTransform, scale1);
- subtickEnter.call(tickTransform, scale0);
- subtickUpdate.call(tickTransform, scale1);
- subtickExit.call(tickTransform, scale1);
- }
- // For ordinal scales:
- // - any entering ticks are undefined in the old scale
- // - any exiting ticks are undefined in the new scale
- // Therefore, we only need to transition updating ticks.
- else {
- var dx = scale1.rangeBand() / 2, x = function(d) { return scale1(d) + dx; };
- tickEnter.call(tickTransform, x);
- tickUpdate.call(tickTransform, x);
- }
- leg.enter().append("g").attr("class", "axisLegend").append("text");
- leg.attr("transform", "translate("+(halfRange*U.x + (m*U.y*legendDist))+","+(halfRange*U.y+(-m*U.x*legendDist))+")" + "rotate("+(orientDeg + (((orientDeg % 360)+360)%360 > 180 ? 90 : -90))+")")
- .select("text").text(legend).attr("text-anchor", "middle").attr("dy", "0em");
- });
- }
- axis.scale = function(x) {
- if (!arguments.length) return scale;
- scale = x;
- return axis;
- };
- axis.orient = function(x) {
- if (!arguments.length) return orient;
- switch (x) {
- case "bottom": orient = tickAngle = Math.PI/2; break;
- case "top": orient = Math.PI/2; tickAngle = -Math.PI/2; break;
- case "left": orient = Math.PI; tickAngle = Math.PI/2; break;
- case "right": orient = Math.PI; tickAngle = -Math.PI/2; break;
- default: orient = x;
- }
- return axis;
- };
- axis.orientVector = function(v) {
- if (!arguments.length) return d3_svg_axisUnitVector(orient);
- return axis.orient(Math.atan2(v.x,-v.y));
- };
- axis.tickAngle = function(x) {
- if (!arguments.length) return tickAngle;
- tickAngle = x;
- return axis;
- };
- axis.ticks = function() {
- if (!arguments.length) return tickArguments_;
- tickArguments_ = arguments;
- return axis;
- };
- axis.tickValues = function(x) {
- if (!arguments.length) return tickValues;
- tickValues = x;
- return axis;
- };
- axis.tickFormat = function(x) {
- if (!arguments.length) return tickFormat_;
- tickFormat_ = x;
- return axis;
- };
- axis.tickSize = function(x, y, z) {
- if (!arguments.length) return tickMajorSize;
- var n = arguments.length - 1;
- tickMajorSize = +x;
- tickMinorSize = n > 1 ? +y : tickMajorSize;
- tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
- return axis;
- };
- axis.tickPadding = function(x) {
- if (!arguments.length) return tickPadding;
- tickPadding = +x;
- return axis;
- };
- axis.tickSubdivide = function(x) {
- if (!arguments.length) return tickSubdivide;
- tickSubdivide = +x;
- return axis;
- };
- axis.shift = function(x) {
- if (!arguments.length) return shift;
- shift = x;
- return axis;
- };
- axis.legend = function(x) {
- if (!arguments.length) return legend;
- legend = x;
- return axis;
- };
- return axis;
- };
- function d3_svg_axisUnitVector(orient) {
- var a = orient - Math.PI/2; // same as orient + d3_svg_arcOffset;
- return { x: Math.cos(a), y: Math.sin(a) };
- }
- function d3_svg_axisSubdivide(scale, ticks, m) {
- var subticks = [];
- if (m && ticks.length > 1) {
- var extent = d3_scaleExtent(scale.domain()),
- i = -1,
- n = ticks.length,
- d = (ticks[1] - ticks[0]) / ++m,
- j,
- v;
- while (++i < n) {
- for (j = m; --j > 0;) {
- if ((v = +ticks[i] - j * d) >= extent[0]) {
- subticks.push(v);
- }
- }
- }
- for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) {
- subticks.push(v);
- }
- }
- return subticks;
- }
- // copied from d3/scale/scale.js
- function d3_scaleExtent(domain) {
- var start = domain[0], stop = domain[domain.length - 1];
- return start < stop ? [start, stop] : [stop, start];
- }
- function d3_scaleRange(scale) {
- return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
- }
- function axes(){
- var axis1 = ns.axis().orient('bottom'),
- axis2 = ns.axis().orient('right');
- function axes(selection){
- selection.each(function (d, i) {
- var g = d3.select(this),
- a1 = g.selectAll('.axis.axis1').data([0]), a2 = g.selectAll('.axis.axis2').data([0]),
- u1 = axis1.orientVector(), u2 = axis2.orientVector(),
- angle = axis1.orient() - axis2.orient();
- a1.enter().append('g').attr('class', 'axis1 axis');
- a2.enter().append('g').attr('class', 'axis2 axis');
- a1.call(axis1/*.tickAngle(-angle)*/);
- a2.call(axis2/*.tickAngle(angle)*/);
- });
- return selection;
- }
- axes.axis1 = function(x){
- if (!arguments.length) return axis1;
- axis1 = x;
- return axes;
- };
- axes.axis2 = function(x){
- if (!arguments.length) return axis2;
- axis2 = x;
- return axes;
- };
- axes.translate = function(c1, c2){
- var s1 = axis1.scale()(c1), s2 = axis2.scale()(c2),
- u1 = axis1.orientVector(), u2 = axis2.orientVector();
- return { x: s1*u1.x + s2*u2.x, y: s1*u1.y + s2*u2.y };
- };
- return axes;
- }
- })(d3co);
Add Comment
Please, Sign In to add comment