You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.5 KiB
135 lines
4.5 KiB
import {bisector, tickStep} from "d3-array"; |
|
import {interpolateNumber as reinterpolate} from "d3-interpolate"; |
|
import {timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeMillisecond} from "d3-time"; |
|
import {timeFormat} from "d3-time-format"; |
|
import {map} from "./array"; |
|
import {default as continuous, copy, deinterpolateLinear as deinterpolate} from "./continuous"; |
|
import nice from "./nice"; |
|
|
|
var durationSecond = 1000, |
|
durationMinute = durationSecond * 60, |
|
durationHour = durationMinute * 60, |
|
durationDay = durationHour * 24, |
|
durationWeek = durationDay * 7, |
|
durationMonth = durationDay * 30, |
|
durationYear = durationDay * 365; |
|
|
|
function date(t) { |
|
return new Date(t); |
|
} |
|
|
|
function number(t) { |
|
return t instanceof Date ? +t : +new Date(+t); |
|
} |
|
|
|
export function calendar(year, month, week, day, hour, minute, second, millisecond, format) { |
|
var scale = continuous(deinterpolate, reinterpolate), |
|
invert = scale.invert, |
|
domain = scale.domain; |
|
|
|
var formatMillisecond = format(".%L"), |
|
formatSecond = format(":%S"), |
|
formatMinute = format("%I:%M"), |
|
formatHour = format("%I %p"), |
|
formatDay = format("%a %d"), |
|
formatWeek = format("%b %d"), |
|
formatMonth = format("%B"), |
|
formatYear = format("%Y"); |
|
|
|
var tickIntervals = [ |
|
[second, 1, durationSecond], |
|
[second, 5, 5 * durationSecond], |
|
[second, 15, 15 * durationSecond], |
|
[second, 30, 30 * durationSecond], |
|
[minute, 1, durationMinute], |
|
[minute, 5, 5 * durationMinute], |
|
[minute, 15, 15 * durationMinute], |
|
[minute, 30, 30 * durationMinute], |
|
[ hour, 1, durationHour ], |
|
[ hour, 3, 3 * durationHour ], |
|
[ hour, 6, 6 * durationHour ], |
|
[ hour, 12, 12 * durationHour ], |
|
[ day, 1, durationDay ], |
|
[ day, 2, 2 * durationDay ], |
|
[ week, 1, durationWeek ], |
|
[ month, 1, durationMonth ], |
|
[ month, 3, 3 * durationMonth ], |
|
[ year, 1, durationYear ] |
|
]; |
|
|
|
function tickFormat(date) { |
|
return (second(date) < date ? formatMillisecond |
|
: minute(date) < date ? formatSecond |
|
: hour(date) < date ? formatMinute |
|
: day(date) < date ? formatHour |
|
: month(date) < date ? (week(date) < date ? formatDay : formatWeek) |
|
: year(date) < date ? formatMonth |
|
: formatYear)(date); |
|
} |
|
|
|
function tickInterval(interval, start, stop, step) { |
|
if (interval == null) interval = 10; |
|
|
|
// If a desired tick count is specified, pick a reasonable tick interval |
|
// based on the extent of the domain and a rough estimate of tick size. |
|
// Otherwise, assume interval is already a time interval and use it. |
|
if (typeof interval === "number") { |
|
var target = Math.abs(stop - start) / interval, |
|
i = bisector(function(i) { return i[2]; }).right(tickIntervals, target); |
|
if (i === tickIntervals.length) { |
|
step = tickStep(start / durationYear, stop / durationYear, interval); |
|
interval = year; |
|
} else if (i) { |
|
i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; |
|
step = i[1]; |
|
interval = i[0]; |
|
} else { |
|
step = Math.max(tickStep(start, stop, interval), 1); |
|
interval = millisecond; |
|
} |
|
} |
|
|
|
return step == null ? interval : interval.every(step); |
|
} |
|
|
|
scale.invert = function(y) { |
|
return new Date(invert(y)); |
|
}; |
|
|
|
scale.domain = function(_) { |
|
return arguments.length ? domain(map.call(_, number)) : domain().map(date); |
|
}; |
|
|
|
scale.ticks = function(interval, step) { |
|
var d = domain(), |
|
t0 = d[0], |
|
t1 = d[d.length - 1], |
|
r = t1 < t0, |
|
t; |
|
if (r) t = t0, t0 = t1, t1 = t; |
|
t = tickInterval(interval, t0, t1, step); |
|
t = t ? t.range(t0, t1 + 1) : []; // inclusive stop |
|
return r ? t.reverse() : t; |
|
}; |
|
|
|
scale.tickFormat = function(count, specifier) { |
|
return specifier == null ? tickFormat : format(specifier); |
|
}; |
|
|
|
scale.nice = function(interval, step) { |
|
var d = domain(); |
|
return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) |
|
? domain(nice(d, interval)) |
|
: scale; |
|
}; |
|
|
|
scale.copy = function() { |
|
return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format)); |
|
}; |
|
|
|
return scale; |
|
} |
|
|
|
export default function() { |
|
return calendar(timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeMillisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); |
|
}
|
|
|