d3-axes
Version:
D3 plugin to manage pairs of axes.
160 lines (136 loc) • 3.88 kB
JavaScript
import { gup } from 'd3-gup';
import { closestClassed } from './closest';
function translate(context, v) {
let selection = context.selection ? context.selection() : context
, x = 0
, y = 0
;
let closest = closestClassed(selection, 'axis');
if (selection.classed('x')) {
y = +v;
} else if (selection.classed('y')) {
x = +v;
} else return;
context.attr('transform', `translate(${x} ${y})`);
}
function positionStart(selection, axis) {
translate(selection, axis.scale().range()[0]);
}
function positionEnd(selection, axis) {
translate(selection, axis.scale().range()[1]);
}
function positionOrigin(selection, axis) {
translate(selection, axis.scale()(0));
}
function position(_) {
let n = +_;
if (isNaN(n))
return positionDefault;
return function(selection, axis) {
translate(selection, axis.scale()(n));
};
}
function empty(scale) {
function axis(context) {
}
axis.scale = function(_) {
return arguments.length ? (scale = _, this) : scale;
}
return axis;
}
const positionDefault = positionOrigin;
const container = gup()
.enter(($, id) => $.append("g")
.attr("id", id)
.attr("class", "axes"))
.post(($, id, h, v) => $
.attr("transform", `translate(${h} ${v})`)
)([null]);
const clipPath = gup()
.enter(($, id) => $.append("clipPath")
.attr("id", `${id}-clip-path`)
.call($ => $.append("rect")))
.post(($, id, h, v) => $.select('rect')
.attr("width", h)
.attr("height", v))([null]);
const axis = gup()
.enter(($, axis) => $.append("g")
.attr("class", `${axis} axis`))
.post(($, _, x, y) => $.call(x, y))([null]);
let count = 0;
export function axes(x, y) {
let paddingTop = 20
, paddingRight = 20
, paddingBottom = 20
, paddingLeft = 20
, height = 0
, width = 0
, index = count++
, id = null
;
function axes(context) {
let selection = context.selection ? context.selection() : context
, v = height - paddingTop - paddingBottom
, h = width - paddingRight - paddingLeft
;
x.scale().range([0, h]);
y.scale().range([v, 0]);
let id = axes.id();
context.selectAll(`g#${id}`)
.call(container, id, paddingLeft, paddingTop);
let g = context.select(`g#${id}`);
g.selectAll(`#${id}-clip-path`).call(clipPath, id, h, v);
g.selectAll(".x.axis").call(axis, "x", x, y);
g.selectAll(".y.axis").call(axis, "y", y, x);
}
axes.x = function(_) {
return arguments.length ? (x = _, this) : x;
};
axes.y = function(_) {
return arguments.length ? (y = _, this) : y;
};
axes.padding = function(v, h, b, l) {
switch (arguments.length) {
case 0:
return {
"top": paddingTop,
"right": paddingRight,
"bottom": paddingBottom,
"left": paddingLeft
};
case 1:
h = b = l = v;
break;
case 2:
[ b, l ] = [ v, h ];
break;
case 3:
l = h;
break;
}
[ paddingTop, paddingRight, paddingBottom, paddingLeft ] = [ v, h, b, l ];
return this;
};
axes.height = function(_) {
return arguments.length ? (height = _, this) : height;
};
axes.width = function(_) {
return arguments.length ? (width = _, this) : width;
};
axes.domain = function(_x, _y) {
if (!arguments.length)
return [x.scale().domain(), y.scale().domain()];
if (_x) x.scale().domain(_x);
if (_y) y.scale().domain(_y);
return this;
};
axes.id = function(_) {
return arguments.length ? (id = _, this) : (id || 'axes-' + index);
}
return axes;
}
export { positionStart as axesPositionBottom, positionStart as axesPositionLeft };
export { positionEnd as axesPositionTop, positionEnd as axesPositionRight };
export { positionDefault as axesPositionDefault };
export { position as axesPosition };
export { empty as axesEmpty };