From 2f89b2fc19be93d93df79496125e52d0c75f3586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Tue, 28 Aug 2018 17:28:25 +0100 Subject: [PATCH 1/7] Have extract getAxis() and getDecimalFormat() --- build/g-axis.js | 24 ++++++++++++------------ src/utils.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/xDate.js | 27 +++++++-------------------- src/xLinear.js | 33 +++++++-------------------------- src/xOrdinal.js | 13 +++++++------ src/yDate.js | 28 +++++++--------------------- src/yLinear.js | 33 +++++++-------------------------- src/yOrdinal.js | 13 ++++++------- 8 files changed, 97 insertions(+), 118 deletions(-) create mode 100644 src/utils.js diff --git a/build/g-axis.js b/build/g-axis.js index 2ecf772..03616fc 100644 --- a/build/g-axis.js +++ b/build/g-axis.js @@ -150,7 +150,7 @@ return (rem * 0.9); }; - const getVerticle = (axisAlign, vertAlign) => ({ + const getVertical = (axisAlign, vertAlign) => ({ toptop: 0 - (rem), topmiddle: 0, topbottom: 0 + (rem), @@ -169,7 +169,7 @@ .attr('class', 'axis xAxis'); axisLabel.append('text') - .attr('y', getVerticle(align, defaultLabel.vert)) + .attr('y', getVertical(align, defaultLabel.vert)) .attr('x', getHorizontal(defaultLabel.hori)) .text(defaultLabel.tag); @@ -569,7 +569,7 @@ return (rem * 0.9); }; - const getVerticle = (axisAlign, vertAlign) => ({ + const getVertical = (axisAlign, vertAlign) => ({ toptop: 0 - (rem), topmiddle: 0, topbottom: 0 + (rem), @@ -585,7 +585,7 @@ }[hori]); axisLabel.append('text') - .attr('y', getVerticle(align, defaultLabel.vert)) + .attr('y', getVertical(align, defaultLabel.vert)) .attr('x', getHorizontal(defaultLabel.hori)) .text(defaultLabel.tag); @@ -779,7 +779,7 @@ return (rem * 0.9); }; - const getVerticle = (axisAlign, vertAlign) => ({ + const getVertical = (axisAlign, vertAlign) => ({ toptop: 0 - (rem), topmiddle: 0, topbottom: 0 + (rem), @@ -807,7 +807,7 @@ axisLabel.append('text') - .attr('y', getVerticle(align, defaultLabel.vert)) + .attr('y', getVertical(align, defaultLabel.vert)) .attr('x', getHorizontal(defaultLabel.hori)) .text(defaultLabel.tag); @@ -1037,7 +1037,7 @@ const axisLabel = parent.append('g') .attr('class', 'axis xAxis'); - const getVerticle = vert => ({ + const getVertical = vert => ({ top: plotHeight - plotHeight, middle: plotHeight / 2, bottom: plotHeight, @@ -1060,7 +1060,7 @@ }[axisAlign + horiAlign]); axisLabel.append('text') - .attr('y', getVerticle(defaultLabel.vert)) + .attr('y', getVertical(defaultLabel.vert)) .attr('x', getHorizontal(align, defaultLabel.hori)) .text(defaultLabel.tag); @@ -1283,7 +1283,7 @@ const axisLabel = parent.append('g') .attr('class', 'axis xAxis'); - const getVerticle = vert => ({ + const getVertical = vert => ({ top: plotHeight - plotHeight, middle: plotHeight / 2, bottom: plotHeight, @@ -1306,7 +1306,7 @@ }[axisAlign + horiAlign]); axisLabel.append('text') - .attr('y', getVerticle(defaultLabel.vert)) + .attr('y', getVertical(defaultLabel.vert)) .attr('x', getHorizontal(align, defaultLabel.hori)) .text(defaultLabel.tag); @@ -1587,7 +1587,7 @@ const axisLabel = parent.append('g') .attr('class', 'axis xAxis'); - const getVerticle = vert => ({ + const getVertical = vert => ({ top: plotHeight - plotHeight, middle: plotHeight / 2, bottom: plotHeight, @@ -1610,7 +1610,7 @@ }[axisAlign + horiAlign]); axisLabel.append('text') - .attr('y', getVerticle(defaultLabel.vert)) + .attr('y', getVertical(defaultLabel.vert)) .attr('x', getHorizontal(align, defaultLabel.hori)) .text(defaultLabel.tag); diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..524857c --- /dev/null +++ b/src/utils.js @@ -0,0 +1,44 @@ +/** + * @file + * Shared code + */ + +import * as d3 from 'd3'; + +export const getDecimalFormat = (span) => { + if (span >= 0.5) { + return d3.format('.1f'); + } else if (span < 0.5) { + return d3.format('.2f'); + } else if (span <= 0.011) { + return d3.format('.3f'); + } else if (span < 0.0011) { + return d3.format('.4f'); + } else if (span < 0.00011) { + return d3.format('.5f'); + } else if (span < 0.000011) { + return d3.format('.6f'); + } else if (isNaN(span)) { + throw new Error('Span value is not a number'); + } + + return null; +}; + +export const getAxis = (alignment) => { + try { + return { + top: d3.axisTop(), + bottom: d3.axisBottom(), + left: d3.axisLeft(), + right: d3.axisRight(), + }[alignment]; + } catch (e) { + throw new Error('Invalid axis specified.'); + } +}; + +export const convertToPointScale = scale => d3 + .scalePoint() + .domain(scale.domain()) + .range(scale.range()); diff --git a/src/xDate.js b/src/xDate.js index 790e07b..87a8a59 100644 --- a/src/xDate.js +++ b/src/xDate.js @@ -1,4 +1,10 @@ +/** + * @file + * Date x-axes + */ + import * as d3 from 'd3'; +import { getAxis, convertToPointScale } from './utils'; export default function xaxisDate() { let banding; @@ -28,28 +34,9 @@ export default function xaxisDate() { function axis(parent) { const plotWidth = plotDim[0]; const plotHeight = plotDim[1]; - - function getAxis(alignment) { - if (intraday) { - const newDomain = scale.domain(); - const newRange = scale.range(); - scale = d3 - .scalePoint() - .domain(newDomain) - .range(newRange); - return { - top: d3.axisTop(), - bottom: d3.axisBottom(), - }[alignment]; - } - return { - top: d3.axisTop(), - bottom: d3.axisBottom(), - }[alignment]; - } - const xAxis = getAxis(align); if (intraday) { + scale = convertToPointScale(scale); xAxis .tickSize(tickSize) .tickFormat(tickFormat(interval)) diff --git a/src/xLinear.js b/src/xLinear.js index a57b4d4..e6aefc1 100644 --- a/src/xLinear.js +++ b/src/xLinear.js @@ -1,4 +1,10 @@ +/** + * @file + * Linear x-axes + */ + import * as d3 from 'd3'; +import { getDecimalFormat, getAxis } from './utils'; export default function () { let banding; @@ -21,13 +27,6 @@ export default function () { let tickValues; let customFormat = false; - function getAxis(alignment) { - return { - top: d3.axisTop(), - bottom: d3.axisBottom(), - }[alignment]; - } - function axis(parent) { let deciCheck = false; const span = scale.domain()[1] - scale.domain()[0]; @@ -46,25 +45,7 @@ export default function () { scale = newScale; } - let deciFormat; - if (span >= 0.5) { - deciFormat = d3.format('.1f'); - } - if (span < 0.5) { - deciFormat = d3.format('.2f'); - } - if (span <= 0.011) { - deciFormat = d3.format('.3f'); - } - if (span < 0.0011) { - deciFormat = d3.format('.4f'); - } - if (span < 0.00011) { - deciFormat = d3.format('.5f'); - } - if (span < 0.000011) { - deciFormat = d3.format('.6f'); - } + const deciFormat = getDecimalFormat(span); const numberFormat = d3.format(','); const xAxis = getAxis(align) diff --git a/src/xOrdinal.js b/src/xOrdinal.js index 82cf1ae..3c8814e 100644 --- a/src/xOrdinal.js +++ b/src/xOrdinal.js @@ -1,4 +1,10 @@ +/** + * @file + * Ordinal x-axes + */ + import * as d3 from 'd3'; +import { getAxis } from './utils'; export default function xAxisOrdinal() { let banding; @@ -200,11 +206,6 @@ export default function xAxisOrdinal() { xLabel = d; return axis; }; - function getAxis(alignment) { - return { - top: d3.axisTop(), - bottom: d3.axisBottom(), - }[alignment]; - } + return axis; } diff --git a/src/yDate.js b/src/yDate.js index f316e0d..ad60b4f 100644 --- a/src/yDate.js +++ b/src/yDate.js @@ -1,4 +1,10 @@ +/** + * @file + * Date y-axes + */ + import * as d3 from 'd3'; +import { getAxis, convertToPointScale } from './utils'; export default function () { let banding; @@ -29,29 +35,9 @@ export default function () { function axis(parent) { const plotWidth = plotDim[0]; const plotHeight = plotDim[1]; - - function getAxis(alignment) { - if (intraday) { - console.log('intraday axis'); // eslint-disable-line - const newDomain = scale.domain(); - const newRange = scale.range(); - scale = d3 - .scalePoint() - .domain(newDomain) - .range(newRange); - return { - left: d3.axisLeft(), - right: d3.axisRight(), - }[alignment]; - } - return { - left: d3.axisLeft(), - right: d3.axisRight(), - }[alignment]; - } - const yAxis = getAxis(align); if (intraday) { + scale = convertToPointScale(scale); yAxis .tickSize(tickSize) .tickFormat(tickFormat(interval)) diff --git a/src/yLinear.js b/src/yLinear.js index 7181bf5..570e082 100644 --- a/src/yLinear.js +++ b/src/yLinear.js @@ -1,4 +1,10 @@ +/** + * @file + * Linear y-axes + */ + import * as d3 from 'd3'; +import { getDecimalFormat, getAxis } from './utils'; export default function () { let banding; @@ -40,25 +46,7 @@ export default function () { scale.range(newRange); } - let deciFormat; - if (span >= 0.5) { - deciFormat = d3.format('.1f'); - } - if (span < 0.5) { - deciFormat = d3.format('.2f'); - } - if (span <= 0.011) { - deciFormat = d3.format('.3f'); - } - if (span < 0.0011) { - deciFormat = d3.format('.4f'); - } - if (span < 0.00011) { - deciFormat = d3.format('.5f'); - } - if (span < 0.000011) { - deciFormat = d3.format('.6f'); - } + const deciFormat = getDecimalFormat(span); const numberFormat = d3.format(','); const yAxis = getAxis(align) @@ -214,13 +202,6 @@ export default function () { yLabel.selectAll('.domain').remove(); } - function getAxis(alignment) { - return { - left: d3.axisLeft(), - right: d3.axisRight(), - }[alignment]; - } - axis.align = (d) => { if (!d) return align; align = d; diff --git a/src/yOrdinal.js b/src/yOrdinal.js index 1f9be5d..38341c9 100644 --- a/src/yOrdinal.js +++ b/src/yOrdinal.js @@ -1,4 +1,10 @@ +/** + * @file + * Ordinal y-axes + */ + import * as d3 from 'd3'; +import { getAxis } from './utils'; export default function () { let banding; @@ -20,13 +26,6 @@ export default function () { let frameName; let invert = false; - function getAxis(alignment) { - return { - left: d3.axisLeft(), - right: d3.axisRight(), - }[alignment]; - } - function axis(parent) { const plotWidth = plotDim[0]; const plotHeight = plotDim[1]; From 8e577e2bcc77e4311bb82cf5c5900e7119f611ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Tue, 28 Aug 2018 18:41:18 +0100 Subject: [PATCH 2/7] Moved: getHorizontal, getVertical, calcOffset, default labels, label ID setter, lots of time stuff --- src/utils.js | 228 ++++++++++++++++++++++++++++++++++++++++++++- src/xDate.js | 243 +++++++----------------------------------------- src/xLinear.js | 65 +++++-------- src/xOrdinal.js | 63 +++++-------- src/yDate.js | 176 +++-------------------------------- src/yLinear.js | 22 ++--- src/yOrdinal.js | 10 +- 7 files changed, 331 insertions(+), 476 deletions(-) diff --git a/src/utils.js b/src/utils.js index 524857c..e50dfaf 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ /** * @file - * Shared code + * Code shared between multiple axes */ import * as d3 from 'd3'; @@ -38,7 +38,231 @@ export const getAxis = (alignment) => { } }; -export const convertToPointScale = scale => d3 +export const convertToPointScale = scale => + d3 .scalePoint() .domain(scale.domain()) .range(scale.range()); + +export const getTimeTicks = intvl => + ({ + century: d3.timeYear.every(100), + jubilee: d3.timeYear.every(50), + decade: d3.timeYear.every(10), + lustrum: d3.timeYear.every(5), + years: d3.timeYear.every(1), + fiscal: d3.timeYear.every(1), + quarters: d3.timeYear.every(1), + months: d3.timeMonth.every(1), + weeks: d3.timeWeek.every(1), + daily: d3.timeDay.every(1), + days: d3.timeDay.every(1), + hours: d3.timeHour.every(1), + }[intvl]); + +export const getTimeTicksMinor = intvl => + ({ + century: d3.timeYear.every(10), + jubilee: d3.timeYear.every(10), + decade: d3.timeYear.every(1), + lustrum: d3.timeYear.every(1), + years: d3.timeMonth.every(1), + fiscal: d3.timeMonth.every(1), + quarters: d3.timeMonth.every(3), + months: d3.timeDay.every(1), + weeks: d3.timeDay.every(1), + daily: d3.timeHour.every(1), + days: d3.timeHour.every(1), + hours: d3.timeMinute.every(1), + }[intvl]); + +export const getTimeTickFormat = (intvl, { fullYear, scale }) => { + const formatFullYear = d3.timeFormat('%Y'); + const formatYear = d3.timeFormat('%y'); + const formatMonth = d3.timeFormat('%b'); + const formatWeek = d3.timeFormat('%W'); + const formatDay = d3.timeFormat('%d'); + const formatHour = d3.timeFormat('%H:%M'); + + return { + century: d3.timeFormat('%Y'), + jubilee(d, i) { + const format = checkCentury(d, i); + return format; + }, + decade(d, i) { + const format = checkCentury(d, i); + return format; + }, + lustrum(d, i) { + const format = checkCentury(d, i); + return format; + }, + years(d, i) { + const format = checkCentury(d, i); + return format; + }, + fiscal(d, i) { + const format = getFiscal(d, i); + return format; + }, + quarters(d, i) { + const format = getQuarters(d, i); + return format; + }, + months(d, i) { + const format = checkMonth(d, i); + return format; + }, + weeks(d, i) { + const format = getWeek(d, i); + return format; + }, + days(d, i) { + const format = getDays(d, i); + return format; + }, + daily(d, i) { + const format = getDaily(d, i); + return format; + }, + hours(d, i) { + const format = getHours(d, i); + return format; + }, + }[intvl]; + + function getHours(d, i) { + if (d.getHours() === 1 || i === 0) { + return `${formatHour(d)} ${formatDay(d)}`; + } + return formatHour(d); + } + + function getDays(d, i) { + if (d.getDate() === 1 || i === 0) { + return `${formatDay(d)} ${formatMonth(d)}`; + } + return formatDay(d); + } + + function getDaily(d, i) { + const last = scale.domain().length - 1; + if (i === 0) { + return `${formatDay(d)} ${formatMonth(d)}`; + } + if (d.getDate() === 1) { + return `${formatMonth(d)}`; + } + if (d.getDay() === 5) { + return `${formatDay(d)}`; + } + if (i === last) { + return formatDay(d); + } + return ''; + } + + function getWeek(d) { + if (d.getDate() < 9) { + return `${formatWeek(d)} ${formatMonth(d)}`; + } + return formatWeek(d); + } + + function getQuarters(d, i) { + if (d.getMonth() < 3 && i < 4) { + return `Q1 ${formatFullYear(d)}`; + } + if (d.getMonth() < 3) { + return 'Q1'; + } + if (d.getMonth() >= 3 && d.getMonth() < 6) { + return 'Q2'; + } + if (d.getMonth() >= 6 && d.getMonth() < 9) { + return 'Q3'; + } + if (d.getMonth() >= 9 && d.getMonth() < 12) { + return 'Q4'; + } + throw new Error('Invalid quarter'); + } + + function checkMonth(d, i) { + if (d.getMonth() === 0 || i === 0) { + const newYear = d3.timeFormat('%b %Y'); + return newYear(d); + } + return formatMonth(d); + } + + function checkCentury(d, i) { + if (fullYear || +formatFullYear(d) % 100 === 0 || i === 0) { + return formatFullYear(d); + } + return formatYear(d); + } + function getFiscal(d, i) { + if (fullYear || +formatFullYear(d) % 100 === 0 || i === 0) { + return `${formatFullYear(d)}/${Number(formatYear(d)) + 1}`; + } + return `${formatYear(d)}/${Number(formatYear(d)) + 1}`; + } +}; + +export const setLabelIds = ({ selection, frameName, axis }) => { + selection + .selectAll(`.axis.${axis.toLowerCase()}Axis text`) + .attr('id', `${frameName}${axis.toLowerCase()}Label`); + + selection + .selectAll(`.axis.${axis.toLowerCase()}Axis line`) + .attr('id', `${frameName}${axis.toLowerCase()}Tick`); +}; + +export const getDefaultXAxisLabel = label => ({ + tag: label.tag, + hori: label.hori || 'middle', + vert: label.vert || 'bottom', + anchor: label.anchor || 'middle', + rotate: label.rotate || 0, +}); + +export const getDefaultYAxisLabel = label => ({ + tag: label.tag, + hori: label.hori || 'left', + vert: label.vert || 'middle', + anchor: label.anchor || 'middle', + rotate: label.rotate || -90, +}); + +export const calcOffset = ({ tickSize, rem }) => { + if (tickSize > 0 && tickSize < rem) { + return tickSize + (rem * 0.8); // prettier-ignore + } + return (rem * 0.9); // prettier-ignore +}; + +export const getVertical = ({ + axisAlign, + vertAlign, + plotHeight, + rem, + tickSize, +}) => + ({ + toptop: 0 - rem, + topmiddle: 0, + topbottom: 0 + rem, + bottomtop: plotHeight, + bottommiddle: plotHeight + calcOffset({ rem, tickSize }), + bottombottom: plotHeight + calcOffset({ rem, tickSize }) + (rem * 1.1), // prettier-ignore + }[axisAlign + vertAlign]); + +export const getHorizontal = ({ hori, plotWidth }) => + ({ + left: plotWidth - plotWidth, + middle: plotWidth / 2, + right: plotWidth, + }[hori]); diff --git a/src/xDate.js b/src/xDate.js index 87a8a59..e3d0dfa 100644 --- a/src/xDate.js +++ b/src/xDate.js @@ -4,7 +4,17 @@ */ import * as d3 from 'd3'; -import { getAxis, convertToPointScale } from './utils'; +import { + convertToPointScale, + getAxis, + getDefaultXAxisLabel, + getTimeTickFormat, + getTimeTicks, + getTimeTicksMinor, + getVertical, + getHorizontal, + setLabelIds, +} from './utils'; export default function xaxisDate() { let banding; @@ -39,7 +49,7 @@ export default function xaxisDate() { scale = convertToPointScale(scale); xAxis .tickSize(tickSize) - .tickFormat(tickFormat(interval)) + .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) .scale(scale); xAxis.tickValues( scale.domain().filter((d, i) => { @@ -56,10 +66,10 @@ export default function xaxisDate() { } else { xAxis .tickSize(tickSize) - // .ticks(getTicks(interval)) - .tickFormat(tickFormat(interval)) + // .ticks(getTimeTicks(interval)) + .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) .scale(scale); - let newTicks = scale.ticks(getTicks(interval)); + let newTicks = scale.ticks(getTimeTicks(interval)); const dayCheck = scale.domain()[0].getDate(); const monthCheck = scale.domain()[0].getMonth(); if (dayCheck !== 1 && monthCheck !== 0) { @@ -88,7 +98,7 @@ export default function xaxisDate() { } else { xMinor .tickSize(minorTickSize) - .ticks(getTicksMinor(interval)) + .ticks(getTimeTicksMinor(interval)) .tickFormat('') .scale(scale); } @@ -121,12 +131,7 @@ export default function xaxisDate() { } if (frameName) { - xLabel - .selectAll('.axis.xAxis text') - .attr('id', `${frameName}xLabel`); - xLabel - .selectAll('.axis.xAxis line') - .attr('id', `${frameName}xTick`); + setLabelIds({ selection: xLabel, axis: 'x', frameName }); if (minorAxis) { xLabelMinor .selectAll('.axis.xAxis line') @@ -135,42 +140,26 @@ export default function xaxisDate() { } if (label) { - const defaultLabel = { - tag: label.tag, - hori: label.hori || 'middle', - vert: label.vert || 'bottom', - anchor: label.anchor || 'middle', - rotate: label.rotate || 0, - }; + const defaultLabel = getDefaultXAxisLabel(label); const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - const calcOffset = () => { - if (tickSize > 0 && tickSize < rem) { - return tickSize + (rem * 0.8); // prettier-ignore - } - return rem * 0.9; - }; - const getVertical = (axisAlign, vertAlign) => - ({ - toptop: 0 - rem, - topmiddle: 0, - topbottom: 0 + rem, - bottomtop: plotHeight, - bottommiddle: plotHeight + calcOffset(), - bottombottom: plotHeight + calcOffset() + (rem * 1.1), // prettier-ignore - }[axisAlign + vertAlign]); - - const getHorizontal = hori => - ({ - left: plotWidth - plotWidth, - middle: plotWidth / 2, - right: plotWidth, - }[hori]); axisLabel .append('text') - .attr('y', getVertical(align, defaultLabel.vert)) - .attr('x', getHorizontal(defaultLabel.hori)) + .attr( + 'y', + getVertical({ + axisAlign: align, + vertAlign: defaultLabel.vert, + plotHeight, + rem, + tickSize, + }), + ) + .attr( + 'x', + getHorizontal({ hori: defaultLabel.hori, plotWidth }), + ) .text(defaultLabel.tag); const text = axisLabel.selectAll('text'); @@ -198,7 +187,7 @@ export default function xaxisDate() { })) .filter((d, i) => i % 2 === 0); - console.log('bands', bands); + // console.log('bands', bands); bandHolder .selectAll('rect') @@ -214,172 +203,6 @@ export default function xaxisDate() { xLabel.selectAll('.domain').remove(); } - function getTicks(intvl) { - return { - century: d3.timeYear.every(100), - jubilee: d3.timeYear.every(50), - decade: d3.timeYear.every(10), - lustrum: d3.timeYear.every(5), - years: d3.timeYear.every(1), - fiscal: d3.timeYear.every(1), - quarters: d3.timeYear.every(1), - months: d3.timeMonth.every(1), - weeks: d3.timeWeek.every(1), - daily: d3.timeDay.every(1), - days: d3.timeDay.every(1), - hours: d3.timeHour.every(1), - }[intvl]; - } - function getTicksMinor(intvl) { - return { - century: d3.timeYear.every(10), - jubilee: d3.timeYear.every(10), - decade: d3.timeYear.every(1), - lustrum: d3.timeYear.every(1), - years: d3.timeMonth.every(1), - fiscal: d3.timeMonth.every(1), - quarters: d3.timeMonth.every(3), - months: d3.timeDay.every(1), - weeks: d3.timeDay.every(1), - daily: d3.timeHour.every(1), - days: d3.timeHour.every(1), - hours: d3.timeMinute.every(1), - }[intvl]; - } - - function tickFormat(intvl) { - const formatFullYear = d3.timeFormat('%Y'); - const formatYear = d3.timeFormat('%y'); - const formatMonth = d3.timeFormat('%b'); - const formatWeek = d3.timeFormat('%W'); - const formatDay = d3.timeFormat('%d'); - const formatHour = d3.timeFormat('%H:%M'); - return { - century: d3.timeFormat('%Y'), - jubilee(d, i) { - const format = checkCentury(d, i); - return format; - }, - decade(d, i) { - const format = checkCentury(d, i); - return format; - }, - lustrum(d, i) { - const format = checkCentury(d, i); - return format; - }, - years(d, i) { - const format = checkCentury(d, i); - return format; - }, - fiscal(d, i) { - const format = getFiscal(d, i); - return format; - }, - quarters(d, i) { - const format = getQuarters(d, i); - return format; - }, - months(d, i) { - const format = checkMonth(d, i); - return format; - }, - weeks(d, i) { - const format = getWeek(d, i); - return format; - }, - days(d, i) { - const format = getDays(d, i); - return format; - }, - daily(d, i) { - const format = getDaily(d, i); - return format; - }, - hours(d, i) { - const format = getHours(d, i); - return format; - }, - }[intvl]; - - function getHours(d, i) { - if (d.getHours() === 1 || i === 0) { - return `${formatHour(d)} ${formatDay(d)}`; - } - return formatHour(d); - } - - function getDays(d, i) { - if (d.getDate() === 1 || i === 0) { - return `${formatDay(d)} ${formatMonth(d)}`; - } - return formatDay(d); - } - - function getDaily(d, i) { - const last = scale.domain().length - 1; - if (i === 0) { - return `${formatDay(d)} ${formatMonth(d)}`; - } - if (d.getDate() === 1) { - return `${formatMonth(d)}`; - } - if (d.getDay() === 5) { - return `${formatDay(d)}`; - } - if (i === last) { - return formatDay(d); - } - return ''; - } - - function getWeek(d) { - if (d.getDate() < 9) { - return `${formatWeek(d)} ${formatMonth(d)}`; - } - return formatWeek(d); - } - - function getQuarters(d, i) { - if (d.getMonth() < 3 && i < 4) { - return `Q1 ${formatFullYear(d)}`; - } - if (d.getMonth() < 3) { - return 'Q1'; - } - if (d.getMonth() >= 3 && d.getMonth() < 6) { - return 'Q2'; - } - if (d.getMonth() >= 6 && d.getMonth() < 9) { - return 'Q3'; - } - if (d.getMonth() >= 9 && d.getMonth() < 12) { - return 'Q4'; - } - throw new Error('Invalid quarter'); - } - - function checkMonth(d, i) { - if (d.getMonth() === 0 || i === 0) { - const newYear = d3.timeFormat('%b %Y'); - return newYear(d); - } - return formatMonth(d); - } - - function checkCentury(d, i) { - if (fullYear || +formatFullYear(d) % 100 === 0 || i === 0) { - return formatFullYear(d); - } - return formatYear(d); - } - function getFiscal(d, i) { - if (fullYear || +formatFullYear(d) % 100 === 0 || i === 0) { - return `${formatFullYear(d)}/${Number(formatYear(d)) + 1}`; - } - return `${formatYear(d)}/${Number(formatYear(d)) + 1}`; - } - } axis.align = (d) => { align = d; return axis; diff --git a/src/xLinear.js b/src/xLinear.js index e6aefc1..62a7904 100644 --- a/src/xLinear.js +++ b/src/xLinear.js @@ -4,7 +4,14 @@ */ import * as d3 from 'd3'; -import { getDecimalFormat, getAxis } from './utils'; +import { + getAxis, + getDecimalFormat, + getDefaultXAxisLabel, + getHorizontal, + getVertical, + setLabelIds, +} from './utils'; export default function () { let banding; @@ -92,53 +99,29 @@ export default function () { .classed('baseline', true); if (frameName) { - xLabel - .selectAll('.axis.xAxis text') - .attr('id', `${frameName}xLabel`); - xLabel - .selectAll('.axis.xAxis line') - .attr('id', `${frameName}xTick`); + setLabelIds({ selection: xLabel, axis: 'x', frameName }); } if (label) { - const defaultLabel = { - tag: label.tag, - hori: label.hori || 'middle', - vert: label.vert || 'bottom', - anchor: label.anchor || 'middle', - rotate: label.rotate || 0, - }; - + const defaultLabel = getDefaultXAxisLabel(label); const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - const calcOffset = () => { - if (tickSize > 0 && tickSize < rem) { - return tickSize + (rem * 0.8); // prettier-ignore - } - return (rem * 0.9); // prettier-ignore - }; - - const getVertical = (axisAlign, vertAlign) => - ({ - toptop: 0 - rem, - topmiddle: 0, - topbottom: 0 + rem, - bottomtop: plotHeight, - bottommiddle: plotHeight + calcOffset(), - bottombottom: plotHeight + calcOffset() + (rem * 1.1), // prettier-ignore - }[axisAlign + vertAlign]); - - const getHorizontal = hori => - ({ - left: plotWidth - plotWidth, - middle: plotWidth / 2, - right: plotWidth, - }[hori]); - axisLabel .append('text') - .attr('y', getVertical(align, defaultLabel.vert)) - .attr('x', getHorizontal(defaultLabel.hori)) + .attr( + 'y', + getVertical({ + axisAlign: align, + vertAlign: defaultLabel.vert, + plotHeight, + rem, + tickSize, + }), + ) + .attr( + 'x', + getHorizontal({ hori: defaultLabel.hori, plotWidth }), + ) .text(defaultLabel.tag); const text = axisLabel.selectAll('text'); diff --git a/src/xOrdinal.js b/src/xOrdinal.js index 3c8814e..63ea695 100644 --- a/src/xOrdinal.js +++ b/src/xOrdinal.js @@ -4,7 +4,13 @@ */ import * as d3 from 'd3'; -import { getAxis } from './utils'; +import { + getAxis, + getDefaultXAxisLabel, + getHorizontal, + getVertical, + setLabelIds, +} from './utils'; export default function xAxisOrdinal() { let banding; @@ -50,53 +56,30 @@ export default function xAxisOrdinal() { .call(xAxis); if (frameName) { - xLabel - .selectAll('.axis.xAxis text') - .attr('id', `${frameName}xLabel`); - xLabel - .selectAll('.axis.xAxis line') - .attr('id', `${frameName}xTick`); + setLabelIds({ selection: xLabel, axis: 'x', frameName }); } if (label) { - const calcOffset = () => { - if (tickSize > 0 && tickSize < rem) { - return tickSize + (rem * 0.8); // prettier-ignore - } - return (rem * 0.9); // prettier-ignore - }; - - const getVertical = (axisAlign, vertAlign) => - ({ - toptop: 0 - rem, - topmiddle: 0, - topbottom: 0 + rem, - bottomtop: plotHeight, - bottommiddle: plotHeight + calcOffset(), - bottombottom: plotHeight + calcOffset() + (rem * 1.1), // prettier-ignore - }[axisAlign + vertAlign]); - - const getHorizontal = hori => - ({ - left: plotWidth - plotWidth, - middle: plotWidth / 2, - right: plotWidth, - }[hori]); - - const defaultLabel = { - tag: label.tag, - hori: label.hori || 'middle', - vert: label.vert || 'bottom', - anchor: label.anchor || 'middle', - rotate: label.rotate || 0, - }; + const defaultLabel = getDefaultXAxisLabel(label); const axisLabel = parent.append('g').attr('class', 'axis xAxis'); axisLabel .append('text') - .attr('y', getVertical(align, defaultLabel.vert)) - .attr('x', getHorizontal(defaultLabel.hori)) + .attr( + 'y', + getVertical({ + axisAlign: align, + vertAlign: defaultLabel.vert, + plotHeight, + rem, + tickSize, + }), + ) + .attr( + 'x', + getHorizontal({ hori: defaultLabel.hori, plotWidth }), + ) .text(defaultLabel.tag); const text = axisLabel.selectAll('text'); diff --git a/src/yDate.js b/src/yDate.js index ad60b4f..b5b7df0 100644 --- a/src/yDate.js +++ b/src/yDate.js @@ -4,7 +4,15 @@ */ import * as d3 from 'd3'; -import { getAxis, convertToPointScale } from './utils'; +import { + getAxis, + convertToPointScale, + getDefaultYAxisLabel, + getTimeTickFormat, + getTimeTicks, + getTimeTicksMinor, + setLabelIds, +} from './utils'; export default function () { let banding; @@ -40,7 +48,7 @@ export default function () { scale = convertToPointScale(scale); yAxis .tickSize(tickSize) - .tickFormat(tickFormat(interval)) + .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) .scale(scale); yAxis.tickValues( scale.domain().filter((d, i) => { @@ -58,9 +66,9 @@ export default function () { yAxis .tickSize(tickSize) // .ticks(getTicks(interval)) - .tickFormat(tickFormat(interval)) + .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) .scale(scale); - let newTicks = scale.ticks(getTicks(interval)); + let newTicks = scale.ticks(getTimeTicks(interval)); const dayCheck = scale.domain()[0].getDate(); const monthCheck = scale.domain()[0].getMonth(); if (dayCheck !== 1 && monthCheck !== 0) { @@ -89,7 +97,7 @@ export default function () { } else { yMinor .tickSize(minorTickSize) - .ticks(getTicksMinor(interval)) + .ticks(getTimeTicksMinor(interval)) .tickFormat('') .scale(scale); } @@ -147,12 +155,7 @@ export default function () { } if (frameName) { - yLabel - .selectAll('.axis.yAxis text') - .attr('id', `${frameName}yLabel`); - yLabel - .selectAll('.axis.yAxis line') - .attr('id', `${frameName}xTick`); + setLabelIds({ selection: yLabel, axis: 'y', frameName }); if (minorAxis) { yLabelMinor .selectAll('.axis.yAxis line') @@ -160,13 +163,7 @@ export default function () { } } if (label) { - const defaultLabel = { - tag: label.tag, - hori: label.hori || 'left', - vert: label.vert || 'middle', - anchor: label.anchor || 'middle', - rotate: label.rotate || -90, - }; + const defaultLabel = getDefaultYAxisLabel(label); const axisLabel = parent.append('g').attr('class', 'axis xAxis'); @@ -246,149 +243,6 @@ export default function () { yLabel.selectAll('.domain').remove(); } - function getTicks(intvl) { - return { - century: d3.timeYear.every(100), - jubilee: d3.timeYear.every(50), - decade: d3.timeYear.every(10), - lustrum: d3.timeYear.every(5), - years: d3.timeYear.every(1), - fiscal: d3.timeYear.every(1), - quarters: d3.timeYear.every(1), - months: d3.timeMonth.every(1), - weeks: d3.timeWeek.every(1), - days: d3.timeDay.every(1), - hours: d3.timeHour.every(1), - }[intvl]; - } - function getTicksMinor(intvl) { - return { - century: d3.timeYear.every(10), - jubilee: d3.timeYear.every(10), - decade: d3.timeYear.every(1), - lustrum: d3.timeYear.every(1), - years: d3.timeMonth.every(1), - fiscal: d3.timeMonth.every(1), - quarters: d3.timeMonth.every(3), - months: d3.timeDay.every(1), - weeks: d3.timeDay.every(1), - days: d3.timeHour.every(1), - hours: d3.timeMinute.every(1), - }[intvl]; - } - - function tickFormat(intvl) { - const formatFullYear = d3.timeFormat('%Y'); - const formatYear = d3.timeFormat('%y'); - const formatMonth = d3.timeFormat('%b'); - const formatWeek = d3.timeFormat('%W'); - const formatDay = d3.timeFormat('%d'); - const formatHour = d3.timeFormat('%H:%M'); - return { - century: d3.timeFormat('%Y'), - jubilee(d, i) { - const format = checkCentury(d, i); - return format; - }, - decade(d, i) { - const format = checkCentury(d, i); - return format; - }, - lustrum(d, i) { - const format = checkCentury(d, i); - return format; - }, - years(d, i) { - const format = checkCentury(d, i); - return format; - }, - fiscal(d, i) { - const format = getFiscal(d, i); - return format; - }, - quarters(d, i) { - const format = getQuarters(d, i); - return format; - }, - months(d, i) { - const format = checkMonth(d, i); - return format; - }, - weeks(d, i) { - const format = getWeek(d, i); - return format; - }, - days(d, i) { - const format = getDays(d, i); - return format; - }, - hours(d, i) { - const format = getHours(d, i); - return format; - }, - }[intvl]; - - function getHours(d, i) { - if (d.getHours() === 1 || i === 0) { - return `${formatHour(d)} ${formatDay(d)}`; - } - return formatHour(d); - } - - function getDays(d, i) { - if (d.getDate() === 1 || i === 0) { - return `${formatDay(d)} ${formatMonth(d)}`; - } - return formatDay(d); - } - - function getWeek(d) { - if (d.getDate() < 9) { - return `${formatWeek(d)} ${formatMonth(d)}`; - } - return formatWeek(d); - } - - function getQuarters(d, i) { - if (d.getMonth() < 3 && i < 4) { - return `Q1 ${formatFullYear(d)}`; - } - if (d.getMonth() < 3) { - return 'Q1'; - } - if (d.getMonth() >= 3 && d.getMonth() < 6) { - return 'Q2'; - } - if (d.getMonth() >= 6 && d.getMonth() < 9) { - return 'Q3'; - } - if (d.getMonth() >= 9 && d.getMonth() < 12) { - return 'Q4'; - } - throw new Error('Invalid quarter'); - } - - function checkMonth(d, i) { - if (d.getMonth() === 0 || i === 0) { - const newYear = d3.timeFormat('%b %Y'); - return newYear(d); - } - return formatMonth(d); - } - - function checkCentury(d, i) { - if (fullYear || +formatFullYear(d) % 100 === 0 || i === 0) { - return formatFullYear(d); - } - return formatYear(d); - } - function getFiscal(d, i) { - if (fullYear || +formatFullYear(d) % 100 === 0 || i === 0) { - return `${formatFullYear(d)}/${Number(formatYear(d)) + 1}`; - } - return `${formatYear(d)}/${Number(formatYear(d)) + 1}`; - } - } axis.align = (d) => { align = d; return axis; diff --git a/src/yLinear.js b/src/yLinear.js index 570e082..e7a393c 100644 --- a/src/yLinear.js +++ b/src/yLinear.js @@ -4,7 +4,12 @@ */ import * as d3 from 'd3'; -import { getDecimalFormat, getAxis } from './utils'; +import { + getAxis, + getDecimalFormat, + getDefaultYAxisLabel, + setLabelIds, +} from './utils'; export default function () { let banding; @@ -105,22 +110,11 @@ export default function () { } if (frameName) { - yLabel - .selectAll('.axis.yAxis text') - .attr('id', `${frameName}yLabel`); - yLabel - .selectAll('.axis.yAxis line') - .attr('id', `${frameName}yTick`); + setLabelIds({ selection: yLabel, axis: 'y', frameName }); } if (label) { - const defaultLabel = { - tag: label.tag, - hori: label.hori || 'left', - vert: label.vert || 'middle', - anchor: label.anchor || 'middle', - rotate: label.rotate || -90, - }; + const defaultLabel = getDefaultYAxisLabel(label); const axisLabel = parent.append('g').attr('class', 'axis xAxis'); diff --git a/src/yOrdinal.js b/src/yOrdinal.js index 38341c9..75872d0 100644 --- a/src/yOrdinal.js +++ b/src/yOrdinal.js @@ -4,7 +4,7 @@ */ import * as d3 from 'd3'; -import { getAxis } from './utils'; +import { getAxis, getDefaultYAxisLabel } from './utils'; export default function () { let banding; @@ -67,13 +67,7 @@ export default function () { } if (label) { - const defaultLabel = { - tag: label.tag, - hori: label.hori || 'left', - vert: label.vert || 'middle', - anchor: label.anchor || 'middle', - rotate: label.rotate || -90, - }; + const defaultLabel = getDefaultYAxisLabel(label); const axisLabel = parent.append('g').attr('class', 'axis xAxis'); From b83fa5ed6bae37084c5185bbe2fad35b07c3ea3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Tue, 28 Aug 2018 19:01:22 +0100 Subject: [PATCH 3/7] All the horizontal and vertical getter funcs --- src/utils.js | 72 ++++++++++++++++++++++++++++++++++++------------- src/xDate.js | 22 +++++++-------- src/xLinear.js | 27 +++++++++---------- src/xOrdinal.js | 12 ++++----- src/yDate.js | 45 +++++++++++++------------------ src/yLinear.js | 43 ++++++++++++----------------- src/yOrdinal.js | 48 +++++++++++++++------------------ 7 files changed, 137 insertions(+), 132 deletions(-) diff --git a/src/utils.js b/src/utils.js index e50dfaf..ec2bb0c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -237,32 +237,66 @@ export const getDefaultYAxisLabel = label => ({ rotate: label.rotate || -90, }); -export const calcOffset = ({ tickSize, rem }) => { - if (tickSize > 0 && tickSize < rem) { - return tickSize + (rem * 0.8); // prettier-ignore - } - return (rem * 0.9); // prettier-ignore -}; - -export const getVertical = ({ - axisAlign, - vertAlign, - plotHeight, - rem, - tickSize, -}) => - ({ +export const getXVertical = ({ align, vert, plotHeight, rem, tickSize }) => { + const calcOffset = () => { + if (tickSize > 0 && tickSize < rem) { + return tickSize + (rem * 0.8); // prettier-ignore + } + return (rem * 0.9); // prettier-ignore + }; + return { toptop: 0 - rem, topmiddle: 0, topbottom: 0 + rem, bottomtop: plotHeight, - bottommiddle: plotHeight + calcOffset({ rem, tickSize }), - bottombottom: plotHeight + calcOffset({ rem, tickSize }) + (rem * 1.1), // prettier-ignore - }[axisAlign + vertAlign]); + bottommiddle: plotHeight + calcOffset(), + bottombottom: plotHeight + calcOffset() + (rem * 1.1), // prettier-ignore + }[align + vert]; +}; -export const getHorizontal = ({ hori, plotWidth }) => +export const getXHorizontal = ({ hori, plotWidth }) => ({ left: plotWidth - plotWidth, middle: plotWidth / 2, right: plotWidth, }[hori]); + +export const getYVertical = ({ vert, plotHeight }) => + ({ + top: plotHeight - plotHeight, + middle: plotHeight / 2, + bottom: plotHeight, + }[vert]); + +export const getYHorizontal = ({ + align, + hori, + plotWidth, + rem, + tickSize, + labelWidth, +}) => { + const calcOffset = () => { + if (tickSize > 0 && tickSize < rem) { + return tickSize / 2; + } + return 0; + }; + + // prettier-ignore + return ({ + leftleft: 0 - (labelWidth + (rem * 0.6)), + leftmiddle: 0 - (labelWidth / 2) - calcOffset(), + leftright: rem * 0.7, + rightleft: plotWidth - labelWidth, + rightmiddle: plotWidth + (labelWidth / 2) + (rem * 0.5) + calcOffset(), + rightright: plotWidth + (rem) + calcOffset(), + }[align + hori]); +}; + +export const getBandWidth = ({ index, bands, plotWidth, scale }) => { + if (index === bands.length - 1) { + return plotWidth - scale(bands[index]); + } + return scale(bands[index + 1]) - scale(bands[index]); +}; diff --git a/src/xDate.js b/src/xDate.js index e3d0dfa..0b77f6e 100644 --- a/src/xDate.js +++ b/src/xDate.js @@ -7,12 +7,13 @@ import * as d3 from 'd3'; import { convertToPointScale, getAxis, + getBandWidth, getDefaultXAxisLabel, getTimeTickFormat, getTimeTicks, getTimeTicksMinor, - getVertical, - getHorizontal, + getXVertical, + getXHorizontal, setLabelIds, } from './utils'; @@ -148,9 +149,9 @@ export default function xaxisDate() { .append('text') .attr( 'y', - getVertical({ - axisAlign: align, - vertAlign: defaultLabel.vert, + getXVertical({ + align, + vert: defaultLabel.vert, plotHeight, rem, tickSize, @@ -158,7 +159,7 @@ export default function xaxisDate() { ) .attr( 'x', - getHorizontal({ hori: defaultLabel.hori, plotWidth }), + getXHorizontal({ hori: defaultLabel.hori, plotWidth }), ) .text(defaultLabel.tag); @@ -174,16 +175,11 @@ export default function xaxisDate() { } if (banding) { let bands = xAxis.tickValues(); - const getBandWidth = (index) => { - if (index === bands.length - 1) { - return plotWidth - scale(bands[index]); - } - return scale(bands[index + 1]) - scale(bands[index]); - }; + bands = bands .map((d, i) => ({ date: d, - width: getBandWidth(i), + width: getBandWidth({ index: i, bands, plotWidth, scale }), })) .filter((d, i) => i % 2 === 0); diff --git a/src/xLinear.js b/src/xLinear.js index 62a7904..6f24292 100644 --- a/src/xLinear.js +++ b/src/xLinear.js @@ -6,10 +6,11 @@ import * as d3 from 'd3'; import { getAxis, + getBandWidth, getDecimalFormat, getDefaultXAxisLabel, - getHorizontal, - getVertical, + getXHorizontal, + getXVertical, setLabelIds, } from './utils'; @@ -110,9 +111,9 @@ export default function () { .append('text') .attr( 'y', - getVertical({ - axisAlign: align, - vertAlign: defaultLabel.vert, + getXVertical({ + align, + vert: defaultLabel.vert, plotHeight, rem, tickSize, @@ -120,7 +121,7 @@ export default function () { ) .attr( 'x', - getHorizontal({ hori: defaultLabel.hori, plotWidth }), + getXHorizontal({ hori: defaultLabel.hori, plotWidth }), ) .text(defaultLabel.tag); @@ -136,20 +137,18 @@ export default function () { } if (banding) { - const getBandWidth = (index, bands) => { - if (index === bands.length - 1) { - return plotWidth - scale(bands[index]); - } - return scale(bands[index + 1]) - scale(bands[index]); - }; - const bands = (tickValues ? xAxis.tickValues() : scale.ticks(numTicks) ) .map((d, i, a) => ({ pos: d, - width: getBandWidth(i, a), + width: getBandWidth({ + index: i, + bands: a, + plotWidth, + scale, + }), })) .filter((d, i) => i % 2 === 0); diff --git a/src/xOrdinal.js b/src/xOrdinal.js index 63ea695..4ecf193 100644 --- a/src/xOrdinal.js +++ b/src/xOrdinal.js @@ -7,8 +7,8 @@ import * as d3 from 'd3'; import { getAxis, getDefaultXAxisLabel, - getHorizontal, - getVertical, + getXHorizontal, + getXVertical, setLabelIds, } from './utils'; @@ -68,9 +68,9 @@ export default function xAxisOrdinal() { .append('text') .attr( 'y', - getVertical({ - axisAlign: align, - vertAlign: defaultLabel.vert, + getXVertical({ + align, + vert: defaultLabel.vert, plotHeight, rem, tickSize, @@ -78,7 +78,7 @@ export default function xAxisOrdinal() { ) .attr( 'x', - getHorizontal({ hori: defaultLabel.hori, plotWidth }), + getXHorizontal({ hori: defaultLabel.hori, plotWidth }), ) .text(defaultLabel.tag); diff --git a/src/yDate.js b/src/yDate.js index b5b7df0..53030a9 100644 --- a/src/yDate.js +++ b/src/yDate.js @@ -5,12 +5,14 @@ import * as d3 from 'd3'; import { - getAxis, convertToPointScale, + getAxis, getDefaultYAxisLabel, getTimeTickFormat, getTimeTicks, getTimeTicksMinor, + getYHorizontal, + getYVertical, setLabelIds, } from './utils'; @@ -167,34 +169,23 @@ export default function () { const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - const getVertical = vert => - ({ - top: plotHeight - plotHeight, - middle: plotHeight / 2, - bottom: plotHeight, - }[vert]); - - const calcOffset = () => { - if (tickSize > 0 && tickSize < rem) { - return tickSize / 2; - } - return 0; - }; - - // prettier-ignore - const getHorizontal = (axisAlign, horiAlign) => ({ - leftleft: 0 - (labelWidth + (rem * 0.6)), - leftmiddle: 0 - (labelWidth / 2) - calcOffset(), - leftright: rem * 0.7, - rightleft: plotWidth - labelWidth, - rightmiddle: plotWidth + (labelWidth / 2) + (rem * 0.5) + calcOffset(), - rightright: plotWidth + (rem) + calcOffset(), - }[axisAlign + horiAlign]); - axisLabel .append('text') - .attr('y', getVertical(defaultLabel.vert)) - .attr('x', getHorizontal(align, defaultLabel.hori)) + .attr( + 'y', + getYVertical({ vert: defaultLabel.vert, plotHeight }), + ) + .attr( + 'x', + getYHorizontal({ + align, + hori: defaultLabel.hori, + plotWidth, + rem, + tickSize, + labelWidth, + }), + ) .text(defaultLabel.tag); // The following doesn't appear to be used anywhere: diff --git a/src/yLinear.js b/src/yLinear.js index e7a393c..1e7f13d 100644 --- a/src/yLinear.js +++ b/src/yLinear.js @@ -8,6 +8,8 @@ import { getAxis, getDecimalFormat, getDefaultYAxisLabel, + getYHorizontal, + getYVertical, setLabelIds, } from './utils'; @@ -118,34 +120,23 @@ export default function () { const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - const getVertical = vert => - ({ - top: plotHeight - plotHeight, - middle: plotHeight / 2, - bottom: plotHeight, - }[vert]); - - const calcOffset = () => { - if (tickSize > 0 && tickSize < rem) { - return tickSize / 2; - } - return 0; - }; - - // prettier-ignore - const getHorizontal = (axisAlign, horiAlign) => ({ - leftleft: 0 - (labelWidth + (rem * 0.6)), - leftmiddle: 0 - (labelWidth / 2) - calcOffset(), - leftright: rem * 0.7, - rightleft: plotWidth - labelWidth, - rightmiddle: plotWidth + (labelWidth / 2) + (rem * 0.5) + calcOffset(), - rightright: plotWidth + (rem) + calcOffset(), - }[axisAlign + horiAlign]); - axisLabel .append('text') - .attr('y', getVertical(defaultLabel.vert)) - .attr('x', getHorizontal(align, defaultLabel.hori)) + .attr( + 'y', + getYVertical({ vert: defaultLabel.vert, plotHeight }), + ) + .attr( + 'x', + getYHorizontal({ + align, + hori: defaultLabel.hori, + plotWidth, + rem, + tickSize, + labelWidth, + }), + ) .text(defaultLabel.tag); const text = axisLabel.selectAll('text'); diff --git a/src/yOrdinal.js b/src/yOrdinal.js index 75872d0..cb88427 100644 --- a/src/yOrdinal.js +++ b/src/yOrdinal.js @@ -4,7 +4,12 @@ */ import * as d3 from 'd3'; -import { getAxis, getDefaultYAxisLabel } from './utils'; +import { + getAxis, + getYHorizontal, + getYVertical, + getDefaultYAxisLabel, +} from './utils'; export default function () { let banding; @@ -71,34 +76,23 @@ export default function () { const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - const getVertical = vert => - ({ - top: plotHeight - plotHeight, - middle: plotHeight / 2, - bottom: plotHeight, - }[vert]); - - const calcOffset = () => { - if (tickSize > 0 && tickSize < rem) { - return tickSize / 2; - } - return 0; - }; - - // prettier-ignore - const getHorizontal = (axisAlign, horiAlign) => ({ - leftleft: 0 - (labelWidth + (rem * 0.6)), - leftmiddle: 0 - (labelWidth / 2) - calcOffset(), - leftright: rem * 0.7, - rightleft: plotWidth - labelWidth, - rightmiddle: plotWidth + (labelWidth / 2) + (rem * 0.5) + calcOffset(), - rightright: plotWidth + (rem) + calcOffset(), - }[axisAlign + horiAlign]); - axisLabel .append('text') - .attr('y', getVertical(defaultLabel.vert)) - .attr('x', getHorizontal(align, defaultLabel.hori)) + .attr( + 'y', + getYVertical({ vert: defaultLabel.vert, plotHeight }), + ) + .attr( + 'x', + getYHorizontal({ + align, + hori: defaultLabel.hori, + plotWidth, + rem, + tickSize, + labelWidth, + }), + ) .text(defaultLabel.tag); const text = axisLabel.selectAll('text'); From 4d6d52aaffe9fd80c34fa325cf30badea657baa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Wed, 29 Aug 2018 12:15:21 +0100 Subject: [PATCH 4/7] Moving label generation to own function --- src/utils.js | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ src/xDate.js | 117 +++++++++++------------------------------- src/xLinear.js | 73 ++++++++------------------ src/xOrdinal.js | 48 ++++------------- src/yDate.js | 117 +++++++++++------------------------------- src/yLinear.js | 76 ++++++++------------------- src/yOrdinal.js | 49 ++++-------------- 7 files changed, 258 insertions(+), 355 deletions(-) diff --git a/src/utils.js b/src/utils.js index ec2bb0c..3826f1d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -300,3 +300,136 @@ export const getBandWidth = ({ index, bands, plotWidth, scale }) => { } return scale(bands[index + 1]) - scale(bands[index]); }; + +export const formatNumber = ( + d, + { divisor, numberFormat, deciFormat, deciCheck, logScale }, +) => { + const checkDecimal = Number.isInteger(d / divisor); + if (checkDecimal === false) { + deciCheck = true; + } + if (d / divisor === 0) { + return numberFormat(d / divisor); + } + if (logScale) { + return numberFormat(d / divisor); + } + if (deciCheck) { + return deciFormat(d / divisor); + } + return numberFormat(d / divisor); +}; + +export const generateDateTickValues = ({ + intraday, + scale, + interval, + endTicks, +}) => { + if (intraday) { + // prettier-ignore + return scale + .domain() + .filter( + (d, i) => + (i > 0 + ? d.getDay() !== + new Date(scale.domain()[i - 1]).getDay() + : d.getDay()), + ); + } + + let newTicks = scale.ticks(getTimeTicks(interval)); + const dayCheck = scale.domain()[0].getDate(); + const monthCheck = scale.domain()[0].getMonth(); + + if (dayCheck !== 1 && monthCheck !== 0) { + newTicks.unshift(scale.domain()[0]); + } + + if ( + interval === 'lustrum' || + interval === 'decade' || + interval === 'jubilee' || + interval === 'century' + ) { + newTicks.push(d3.timeYear(scale.domain()[1])); + } + + if (endTicks) { + newTicks = scale.domain(); + } + + return newTicks; +}; + +export const generateLabels = ( + axis, + { label, plotHeight, parent, align, plotWidth, rem, tickSize, labelWidth }, +) => { + const axisLabel = parent.append('g'); + const defaultLabel = + axis === 'x' + ? getDefaultXAxisLabel(label) + : getDefaultYAxisLabel(label); + + switch (axis) { + case 'x': + axisLabel + .attr('class', 'axis xAxis') + .append('text') + .attr( + 'y', + getXVertical({ + align, + vert: defaultLabel.vert, + plotHeight, + rem, + tickSize, + }), + ) + .attr( + 'x', + getXHorizontal({ hori: defaultLabel.hori, plotWidth }), + ) + .text(defaultLabel.tag); + break; + case 'y': + axisLabel.attr('class', 'axis xAxis'); + + axisLabel + .append('text') + .attr( + 'y', + getYVertical({ vert: defaultLabel.vert, plotHeight }), + ) + .attr( + 'x', + getYHorizontal({ + align, + hori: defaultLabel.hori, + plotWidth, + rem, + tickSize, + labelWidth, + }), + ) + .text(defaultLabel.tag); + break; + default: + throw new Error('No axis direction specified'); + } + + const text = axisLabel.selectAll('text'); + const width = text.node().getBBox().width / 2; + const height = text.node().getBBox().height / 2; + const textX = text.node().getBBox().x + width; + const textY = text.node().getBBox().y + height; + text.attr( + 'transform', + `rotate(${defaultLabel.rotate}, ${textX}, ${textY})`, + ).style('text-anchor', defaultLabel.anchor); +}; + +export const generateBanding = () => {}; diff --git a/src/xDate.js b/src/xDate.js index 0b77f6e..ea151dc 100644 --- a/src/xDate.js +++ b/src/xDate.js @@ -6,14 +6,12 @@ import * as d3 from 'd3'; import { convertToPointScale, + generateDateTickValues, + generateLabels, getAxis, getBandWidth, - getDefaultXAxisLabel, getTimeTickFormat, - getTimeTicks, getTimeTicksMinor, - getXVertical, - getXHorizontal, setLabelIds, } from './utils'; @@ -46,62 +44,31 @@ export default function xaxisDate() { const plotWidth = plotDim[0]; const plotHeight = plotDim[1]; const xAxis = getAxis(align); + if (intraday) { scale = convertToPointScale(scale); - xAxis - .tickSize(tickSize) - .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) - .scale(scale); - xAxis.tickValues( - scale.domain().filter((d, i) => { - let checkDate; - if (i === 0) { - return d.getDay(); - } - if (i > 0) { - checkDate = new Date(scale.domain()[i - 1]); - } - return d.getDay() !== checkDate.getDay(); + } + + xAxis + .tickSize(tickSize) + .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) + .scale(scale) + .tickValues( + generateDateTickValues({ + intraday, + scale, + interval, + endTicks, }), ); - } else { - xAxis - .tickSize(tickSize) - // .ticks(getTimeTicks(interval)) - .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) - .scale(scale); - let newTicks = scale.ticks(getTimeTicks(interval)); - const dayCheck = scale.domain()[0].getDate(); - const monthCheck = scale.domain()[0].getMonth(); - if (dayCheck !== 1 && monthCheck !== 0) { - newTicks.unshift(scale.domain()[0]); - } - if ( - interval === 'lustrum' || - interval === 'decade' || - interval === 'jubilee' || - interval === 'century' - ) { - newTicks.push(d3.timeYear(scale.domain()[1])); - } - if (endTicks) { - newTicks = scale.domain(); - } - xAxis.tickValues(newTicks); - } - const xMinor = getAxis(align); - if (intraday) { - xMinor - .tickSize(minorTickSize) - .tickFormat('') - .scale(scale); - } else { - xMinor - .tickSize(minorTickSize) - .ticks(getTimeTicksMinor(interval)) - .tickFormat('') - .scale(scale); + const xMinor = getAxis(align) + .tickSize(minorTickSize) + .tickFormat('') + .scale(scale); + + if (!intraday) { + xMinor.ticks(getTimeTicksMinor(interval)); } if (tickValues) { @@ -141,37 +108,15 @@ export default function xaxisDate() { } if (label) { - const defaultLabel = getDefaultXAxisLabel(label); - - const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - - axisLabel - .append('text') - .attr( - 'y', - getXVertical({ - align, - vert: defaultLabel.vert, - plotHeight, - rem, - tickSize, - }), - ) - .attr( - 'x', - getXHorizontal({ hori: defaultLabel.hori, plotWidth }), - ) - .text(defaultLabel.tag); - - const text = axisLabel.selectAll('text'); - const width = text.node().getBBox().width / 2; - const height = text.node().getBBox().height / 2; - const textX = text.node().getBBox().x + width; - const textY = text.node().getBBox().y + height; - text.attr( - 'transform', - `rotate(${defaultLabel.rotate}, ${textX}, ${textY})`, - ).style('text-anchor', defaultLabel.anchor); + generateLabels('x', { + align, + label, + parent, + plotHeight, + plotWidth, + rem, + tickSize, + }); } if (banding) { let bands = xAxis.tickValues(); diff --git a/src/xLinear.js b/src/xLinear.js index 6f24292..bb20c7b 100644 --- a/src/xLinear.js +++ b/src/xLinear.js @@ -5,12 +5,11 @@ import * as d3 from 'd3'; import { + formatNumber, + generateLabels, getAxis, getBandWidth, getDecimalFormat, - getDefaultXAxisLabel, - getXHorizontal, - getXVertical, setLabelIds, } from './utils'; @@ -36,7 +35,7 @@ export default function () { let customFormat = false; function axis(parent) { - let deciCheck = false; + const deciCheck = false; const span = scale.domain()[1] - scale.domain()[0]; const plotWidth = plotDim[0]; const plotHeight = plotDim[1]; @@ -60,24 +59,15 @@ export default function () { .tickSize(tickSize) .ticks(numTicks) .scale(scale) - .tickFormat(formatNumber); - - function formatNumber(d) { - const checkDecimal = Number.isInteger(d / divisor); - if (checkDecimal === false) { - deciCheck = true; - } - if (d / divisor === 0) { - return numberFormat(d / divisor); - } - if (logScale) { - return numberFormat(d / divisor); - } - if (deciCheck) { - return deciFormat(d / divisor); - } - return numberFormat(d / divisor); - } + .tickFormat(d => + formatNumber(d, { + divisor, + numberFormat, + deciFormat, + deciCheck, + logScale, + }), + ); if (tickValues) { xAxis.tickValues(tickValues); @@ -104,36 +94,15 @@ export default function () { } if (label) { - const defaultLabel = getDefaultXAxisLabel(label); - const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - - axisLabel - .append('text') - .attr( - 'y', - getXVertical({ - align, - vert: defaultLabel.vert, - plotHeight, - rem, - tickSize, - }), - ) - .attr( - 'x', - getXHorizontal({ hori: defaultLabel.hori, plotWidth }), - ) - .text(defaultLabel.tag); - - const text = axisLabel.selectAll('text'); - const width = text.node().getBBox().width / 2; - const height = text.node().getBBox().height / 2; - const textX = text.node().getBBox().x + width; - const textY = text.node().getBBox().y + height; - text.attr( - 'transform', - `rotate(${defaultLabel.rotate}, ${textX}, ${textY})`, - ).style('text-anchor', defaultLabel.anchor); + generateLabels('x', { + align, + label, + parent, + plotHeight, + plotWidth, + rem, + tickSize, + }); } if (banding) { diff --git a/src/xOrdinal.js b/src/xOrdinal.js index 4ecf193..e2b339e 100644 --- a/src/xOrdinal.js +++ b/src/xOrdinal.js @@ -4,13 +4,7 @@ */ import * as d3 from 'd3'; -import { - getAxis, - getDefaultXAxisLabel, - getXHorizontal, - getXVertical, - setLabelIds, -} from './utils'; +import { generateLabels, getAxis, setLabelIds } from './utils'; export default function xAxisOrdinal() { let banding; @@ -60,37 +54,15 @@ export default function xAxisOrdinal() { } if (label) { - const defaultLabel = getDefaultXAxisLabel(label); - - const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - - axisLabel - .append('text') - .attr( - 'y', - getXVertical({ - align, - vert: defaultLabel.vert, - plotHeight, - rem, - tickSize, - }), - ) - .attr( - 'x', - getXHorizontal({ hori: defaultLabel.hori, plotWidth }), - ) - .text(defaultLabel.tag); - - const text = axisLabel.selectAll('text'); - const width = text.node().getBBox().width / 2; - const height = text.node().getBBox().height / 2; - const textX = text.node().getBBox().x + width; - const textY = text.node().getBBox().y + height; - text.attr( - 'transform', - `rotate(${defaultLabel.rotate}, ${textX}, ${textY})`, - ).style('text-anchor', defaultLabel.anchor); + generateLabels('x', { + align, + label, + parent, + plotHeight, + plotWidth, + rem, + tickSize, + }); } if (banding) { diff --git a/src/yDate.js b/src/yDate.js index 53030a9..63d929e 100644 --- a/src/yDate.js +++ b/src/yDate.js @@ -6,13 +6,11 @@ import * as d3 from 'd3'; import { convertToPointScale, + generateDateTickValues, + generateLabels, getAxis, - getDefaultYAxisLabel, getTimeTickFormat, - getTimeTicks, getTimeTicksMinor, - getYHorizontal, - getYVertical, setLabelIds, } from './utils'; @@ -48,60 +46,27 @@ export default function () { const yAxis = getAxis(align); if (intraday) { scale = convertToPointScale(scale); - yAxis - .tickSize(tickSize) - .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) - .scale(scale); - yAxis.tickValues( - scale.domain().filter((d, i) => { - let checkDate; - if (i === 0) { - return d.getDay(); - } - if (i > 0) { - checkDate = new Date(scale.domain()[i - 1]); - } - return d.getDay() !== checkDate.getDay(); + } + yAxis + .tickSize(tickSize) + .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) + .scale(scale) + .tickValues( + generateDateTickValues({ + intraday, + scale, + interval, + endTicks, }), ); - } else { - yAxis - .tickSize(tickSize) - // .ticks(getTicks(interval)) - .tickFormat(getTimeTickFormat(interval, { fullYear, scale })) - .scale(scale); - let newTicks = scale.ticks(getTimeTicks(interval)); - const dayCheck = scale.domain()[0].getDate(); - const monthCheck = scale.domain()[0].getMonth(); - if (dayCheck !== 1 && monthCheck !== 0) { - newTicks.unshift(scale.domain()[0]); - } - if ( - interval === 'lustrum' || - interval === 'decade' || - interval === 'jubilee' || - interval === 'century' - ) { - newTicks.push(d3.timeYear(scale.domain()[1])); - } - if (endTicks) { - newTicks = scale.domain(); - } - yAxis.tickValues(newTicks); - } - const yMinor = getAxis(align); - if (intraday) { - yMinor - .tickSize(minorTickSize) - .tickFormat('') - .scale(scale); - } else { - yMinor - .tickSize(minorTickSize) - .ticks(getTimeTicksMinor(interval)) - .tickFormat('') - .scale(scale); + const yMinor = getAxis(align) + .tickSize(minorTickSize) + .tickFormat('') + .scale(scale); + + if (!intraday) { + yMinor.ticks(getTimeTicksMinor(interval)); } if (tickValues) { @@ -165,38 +130,16 @@ export default function () { } } if (label) { - const defaultLabel = getDefaultYAxisLabel(label); - - const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - - axisLabel - .append('text') - .attr( - 'y', - getYVertical({ vert: defaultLabel.vert, plotHeight }), - ) - .attr( - 'x', - getYHorizontal({ - align, - hori: defaultLabel.hori, - plotWidth, - rem, - tickSize, - labelWidth, - }), - ) - .text(defaultLabel.tag); - - // The following doesn't appear to be used anywhere: - - // const text = axisLabel.selectAll('text'); - // const width = (text.node().getBBox().width) / 2; - // const height = (text.node().getBBox().height) / 2; - // const textX = text.node().getBBox().x + width; - // const textY = text.node().getBBox().y + height; - // text.attr('transform', 'rotate(' + (defaultLabel.rotate) + ', ' + textX + ', ' + textY + ')') - // .style('text-anchor', defaultLabel.anchor); + generateLabels('y', { + align, + label, + labelWidth, + parent, + plotHeight, + plotWidth, + rem, + tickSize, + }); } if (banding) { diff --git a/src/yLinear.js b/src/yLinear.js index 1e7f13d..b8e5fd4 100644 --- a/src/yLinear.js +++ b/src/yLinear.js @@ -5,11 +5,10 @@ import * as d3 from 'd3'; import { + formatNumber, + generateLabels, getAxis, getDecimalFormat, - getDefaultYAxisLabel, - getYHorizontal, - getYVertical, setLabelIds, } from './utils'; @@ -36,7 +35,7 @@ export default function () { let customFormat = false; function axis(parent) { - let deciCheck = false; + const deciCheck = false; const span = scale.domain()[1] - scale.domain()[0]; const plotWidth = plotDim[0]; const plotHeight = plotDim[1]; @@ -59,24 +58,15 @@ export default function () { const yAxis = getAxis(align) .ticks(numTicks) .scale(scale) - .tickFormat(formatNumber); - - function formatNumber(d) { - const checkDecimal = Number.isInteger(d / divisor); - if (checkDecimal === false) { - deciCheck = true; - } - if (d / divisor === 0) { - return numberFormat(d / divisor); - } - if (logScale) { - return numberFormat(d / divisor); - } - if (deciCheck) { - return deciFormat(d / divisor); - } - return numberFormat(d / divisor); - } + .tickFormat(d => + formatNumber(d, { + divisor, + numberFormat, + deciFormat, + deciCheck, + logScale, + }), + ); if (tickValues) { yAxis.tickValues(tickValues); @@ -116,38 +106,16 @@ export default function () { } if (label) { - const defaultLabel = getDefaultYAxisLabel(label); - - const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - - axisLabel - .append('text') - .attr( - 'y', - getYVertical({ vert: defaultLabel.vert, plotHeight }), - ) - .attr( - 'x', - getYHorizontal({ - align, - hori: defaultLabel.hori, - plotWidth, - rem, - tickSize, - labelWidth, - }), - ) - .text(defaultLabel.tag); - - const text = axisLabel.selectAll('text'); - const width = text.node().getBBox().width / 2; - const height = text.node().getBBox().height / 2; - const textX = text.node().getBBox().x + width; - const textY = text.node().getBBox().y + height; - text.attr( - 'transform', - `rotate(${defaultLabel.rotate}, ${textX}, ${textY})`, - ).style('text-anchor', defaultLabel.anchor); + generateLabels('y', { + align, + label, + labelWidth, + parent, + plotHeight, + plotWidth, + rem, + tickSize, + }); } if (banding) { diff --git a/src/yOrdinal.js b/src/yOrdinal.js index cb88427..fc3092d 100644 --- a/src/yOrdinal.js +++ b/src/yOrdinal.js @@ -4,12 +4,7 @@ */ import * as d3 from 'd3'; -import { - getAxis, - getYHorizontal, - getYVertical, - getDefaultYAxisLabel, -} from './utils'; +import { generateLabels, getAxis } from './utils'; export default function () { let banding; @@ -72,38 +67,16 @@ export default function () { } if (label) { - const defaultLabel = getDefaultYAxisLabel(label); - - const axisLabel = parent.append('g').attr('class', 'axis xAxis'); - - axisLabel - .append('text') - .attr( - 'y', - getYVertical({ vert: defaultLabel.vert, plotHeight }), - ) - .attr( - 'x', - getYHorizontal({ - align, - hori: defaultLabel.hori, - plotWidth, - rem, - tickSize, - labelWidth, - }), - ) - .text(defaultLabel.tag); - - const text = axisLabel.selectAll('text'); - const width = text.node().getBBox().width / 2; - const height = text.node().getBBox().height / 2; - const textX = text.node().getBBox().x + width; - const textY = text.node().getBBox().y + height; - text.attr( - 'transform', - `rotate(${defaultLabel.rotate}, ${textX}, ${textY})`, - ).style('text-anchor', defaultLabel.anchor); + generateLabels('y', { + align, + label, + labelWidth, + parent, + plotHeight, + plotWidth, + rem, + tickSize, + }); } if (banding) { From 9b487377443be70092242cc2046c8d89d4b205a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Wed, 29 Aug 2018 13:08:56 +0100 Subject: [PATCH 5/7] Moving banding code to own function. Hope to hell I didn't break anything... --- src/utils.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++- src/xDate.js | 31 +++++++++++---------------- src/xLinear.js | 13 ++---------- src/xOrdinal.js | 16 ++------------ src/yDate.js | 26 ++++++++--------------- src/yLinear.js | 19 +++++++---------- src/yOrdinal.js | 23 ++++++++------------ 7 files changed, 97 insertions(+), 87 deletions(-) diff --git a/src/utils.js b/src/utils.js index 3826f1d..f0c8358 100644 --- a/src/utils.js +++ b/src/utils.js @@ -432,4 +432,58 @@ export const generateLabels = ( ).style('text-anchor', defaultLabel.anchor); }; -export const generateBanding = () => {}; +export const generateBanding = ( + direction, + { parent, bands, scale, plotHeight, plotWidth, labelWidth, align, rem }, +) => { + switch (direction) { + case 'x': + parent + .append('g') + .attr('class', 'highlights') + .selectAll('rect') + .data(bands) + .enter() + .append('rect') + .attr('y', 0) + .attr('height', plotHeight) + .attr('x', (d) => { + if (scale.step) { + const yOffset = + (scale.step() / 100) * (scale.paddingInner() * 100); + return scale(d.pos) - (yOffset / 2); // prettier-ignore + } + return scale(d.pos); + }) + .attr('width', scale.step ? scale.step() : d => d.width); + break; + case 'y': + parent + .append('g') + .attr('class', 'highlights') + .selectAll('rect') + .data(bands) + .enter() + .append('rect') + .attr('x', 0) + .attr('width', () => { + if (align === 'left' || !rem) { + return plotWidth - labelWidth; + } + return plotWidth - labelWidth - rem; + }) + .attr('y', (d) => { + // prettier-ignore + if (scale.step) { + const yOffset = (scale.step() / 100) + * (scale.paddingInner() * 100); + return scale(d.pos) - (yOffset / 2); + } + return scale(d.pos); + }) + .attr('height', scale.step ? scale.step() : d => d.height); + break; + default: + throw new Error('No axis direction specified for banding'); + } +}; diff --git a/src/xDate.js b/src/xDate.js index ea151dc..2784a9c 100644 --- a/src/xDate.js +++ b/src/xDate.js @@ -6,6 +6,7 @@ import * as d3 from 'd3'; import { convertToPointScale, + generateBanding, generateDateTickValues, generateLabels, getAxis, @@ -79,8 +80,6 @@ export default function xaxisDate() { xAxis.tickFormat(customFormat); } - const bandHolder = parent.append('g').attr('class', 'highlights'); - xLabel = parent .append('g') .attr('class', 'axis xAxis axis baseline') @@ -119,26 +118,20 @@ export default function xaxisDate() { }); } if (banding) { - let bands = xAxis.tickValues(); - - bands = bands - .map((d, i) => ({ - date: d, - width: getBandWidth({ index: i, bands, plotWidth, scale }), + const bands = xAxis + .tickValues() + .map((d, i, a) => ({ + pos: d, + width: getBandWidth({ + index: i, + bands: a, + plotWidth, + scale, + }), })) .filter((d, i) => i % 2 === 0); - // console.log('bands', bands); - - bandHolder - .selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('y', 0) - .attr('height', plotHeight) - .attr('x', d => scale(d.date)) - .attr('width', d => d.width); + generateBanding('x', { parent, bands, plotHeight, scale }); } xLabel.selectAll('.domain').remove(); diff --git a/src/xLinear.js b/src/xLinear.js index bb20c7b..a2517d1 100644 --- a/src/xLinear.js +++ b/src/xLinear.js @@ -6,6 +6,7 @@ import * as d3 from 'd3'; import { formatNumber, + generateBanding, generateLabels, getAxis, getBandWidth, @@ -77,8 +78,6 @@ export default function () { xAxis.tickFormat(customFormat); } - const bandHolder = parent.append('g').attr('class', 'highlights'); - xLabel = parent .append('g') .attr('class', 'axis xAxis') @@ -121,15 +120,7 @@ export default function () { })) .filter((d, i) => i % 2 === 0); - bandHolder - .selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('y', 0) - .attr('height', plotHeight) - .attr('x', d => scale(d.pos)) - .attr('width', d => d.width); + generateBanding('x', { parent, bands, plotHeight, scale }); } xLabel diff --git a/src/xOrdinal.js b/src/xOrdinal.js index e2b339e..de36635 100644 --- a/src/xOrdinal.js +++ b/src/xOrdinal.js @@ -4,7 +4,7 @@ */ import * as d3 from 'd3'; -import { generateLabels, getAxis, setLabelIds } from './utils'; +import { generateBanding, generateLabels, getAxis, setLabelIds } from './utils'; export default function xAxisOrdinal() { let banding; @@ -42,8 +42,6 @@ export default function xAxisOrdinal() { scale.paddingInner(0.2); } - const bandHolder = parent.append('g').attr('class', 'highlights'); - xLabel = parent .append('g') .attr('class', 'axis xAxis') @@ -73,17 +71,7 @@ export default function xAxisOrdinal() { })) .filter((d, i) => i % 2 === 1); - const yOffset = (scale.step() / 100) * (scale.paddingInner() * 100); // prettier-ignore - - // prettier-ignore - bandHolder.selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('y', 0) - .attr('height', plotHeight) - .attr('x', d => scale(d.pos) - (yOffset / 2)) - .attr('width', scale.step()); + generateBanding('x', { parent, bands, plotHeight, scale }); } xLabel.selectAll('.domain').remove(); diff --git a/src/yDate.js b/src/yDate.js index 63d929e..a519ecf 100644 --- a/src/yDate.js +++ b/src/yDate.js @@ -6,6 +6,7 @@ import * as d3 from 'd3'; import { convertToPointScale, + generateBanding, generateDateTickValues, generateLabels, getAxis, @@ -77,8 +78,6 @@ export default function () { yAxis.tickFormat(customFormat); } - const bandHolder = parent.append('g').attr('class', 'highlights'); - yLabel = parent .append('g') .attr('class', 'axis yAxis axis baseline') @@ -153,25 +152,18 @@ export default function () { const bands = yAxis .tickValues() .map((d, i, a) => ({ - date: d, + pos: d, height: getBandWidth(i, a), })) .filter((d, i) => i % 2 === 0); - bandHolder - .selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('x', 0) - .attr('width', () => { - if (align === 'left ') { - return plotWidth - labelWidth; - } - return plotWidth - labelWidth - rem; - }) - .attr('y', d => scale(d.date)) - .attr('height', d => d.height); + generateBanding('y', { + parent, + bands, + scale, + plotWidth, + labelWidth, + }); } yLabel.selectAll('.domain').remove(); diff --git a/src/yLinear.js b/src/yLinear.js index b8e5fd4..5ab4d40 100644 --- a/src/yLinear.js +++ b/src/yLinear.js @@ -6,6 +6,7 @@ import * as d3 from 'd3'; import { formatNumber, + generateBanding, generateLabels, getAxis, getDecimalFormat, @@ -76,8 +77,6 @@ export default function () { yAxis.tickFormat(customFormat); } - const bandHolder = parent.append('g').attr('class', 'highlights'); - yLabel = parent .append('g') .attr('class', 'axis yAxis') @@ -136,15 +135,13 @@ export default function () { })) .filter((d, i) => i % 2 === 0); - bandHolder - .selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('x', 0) - .attr('width', plotWidth - labelWidth) - .attr('y', d => scale(d.pos)) - .attr('height', d => d.height); + generateBanding('y', { + parent, + bands, + scale, + plotWidth, + labelWidth, + }); } yLabel diff --git a/src/yOrdinal.js b/src/yOrdinal.js index fc3092d..a897342 100644 --- a/src/yOrdinal.js +++ b/src/yOrdinal.js @@ -4,7 +4,7 @@ */ import * as d3 from 'd3'; -import { generateLabels, getAxis } from './utils'; +import { generateBanding, generateLabels, getAxis } from './utils'; export default function () { let banding; @@ -45,8 +45,6 @@ export default function () { scale.paddingInner(0.2); } - const bandHolder = parent.append('g').attr('class', 'highlights'); - yLabel = parent .append('g') .attr('class', 'axis yAxis') @@ -87,17 +85,14 @@ export default function () { })) .filter((d, i) => i % 2 === 0); - const yOffset = (scale.step() / 100) * (scale.paddingInner() * 100); // prettier-ignore - - // prettier-ignore - bandHolder.selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('x', 0) - .attr('width', plotWidth - labelWidth) - .attr('y', d => scale(d.pos) - (yOffset / 2)) - .attr('height', scale.step()); + generateBanding('y', { + parent, + bands, + scale, + plotWidth, + labelWidth, + align, + }); } yLabel.selectAll('.domain').remove(); From 92ab94666634c34c087ffed08b3415b138d51500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Wed, 29 Aug 2018 13:16:50 +0100 Subject: [PATCH 6/7] Simplifying logic a bit more. --- src/utils.js | 60 ++++++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/src/utils.js b/src/utils.js index f0c8358..c1dba05 100644 --- a/src/utils.js +++ b/src/utils.js @@ -436,51 +436,33 @@ export const generateBanding = ( direction, { parent, bands, scale, plotHeight, plotWidth, labelWidth, align, rem }, ) => { + const selection = parent + .append('g') + .attr('class', 'highlights') + .selectAll('rect') + .data(bands) + .enter() + .append('rect') + .attr(direction, 0); + + const yOffset = scale.step + ? ((scale.step() / 100) * (scale.paddingInner() * 100)) / 2 + : 0; + switch (direction) { case 'x': - parent - .append('g') - .attr('class', 'highlights') - .selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('y', 0) + selection .attr('height', plotHeight) - .attr('x', (d) => { - if (scale.step) { - const yOffset = - (scale.step() / 100) * (scale.paddingInner() * 100); - return scale(d.pos) - (yOffset / 2); // prettier-ignore - } - return scale(d.pos); - }) + .attr('x', d => scale(d.pos) - yOffset) .attr('width', scale.step ? scale.step() : d => d.width); break; case 'y': - parent - .append('g') - .attr('class', 'highlights') - .selectAll('rect') - .data(bands) - .enter() - .append('rect') - .attr('x', 0) - .attr('width', () => { - if (align === 'left' || !rem) { - return plotWidth - labelWidth; - } - return plotWidth - labelWidth - rem; - }) - .attr('y', (d) => { - // prettier-ignore - if (scale.step) { - const yOffset = (scale.step() / 100) - * (scale.paddingInner() * 100); - return scale(d.pos) - (yOffset / 2); - } - return scale(d.pos); - }) + // prettier-ignore + selection + .attr('width', () => (align === 'left' || !rem + ? plotWidth - labelWidth + : plotWidth - labelWidth - rem)) + .attr('y', d => scale(d.pos) - yOffset) .attr('height', scale.step ? scale.step() : d => d.height); break; default: From a0b13b23d31c8c251cf249f283122f1664cba4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Wed, 29 Aug 2018 13:20:13 +0100 Subject: [PATCH 7/7] Reverting built file for easier diff --- build/g-axis.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/build/g-axis.js b/build/g-axis.js index 03616fc..2ecf772 100644 --- a/build/g-axis.js +++ b/build/g-axis.js @@ -150,7 +150,7 @@ return (rem * 0.9); }; - const getVertical = (axisAlign, vertAlign) => ({ + const getVerticle = (axisAlign, vertAlign) => ({ toptop: 0 - (rem), topmiddle: 0, topbottom: 0 + (rem), @@ -169,7 +169,7 @@ .attr('class', 'axis xAxis'); axisLabel.append('text') - .attr('y', getVertical(align, defaultLabel.vert)) + .attr('y', getVerticle(align, defaultLabel.vert)) .attr('x', getHorizontal(defaultLabel.hori)) .text(defaultLabel.tag); @@ -569,7 +569,7 @@ return (rem * 0.9); }; - const getVertical = (axisAlign, vertAlign) => ({ + const getVerticle = (axisAlign, vertAlign) => ({ toptop: 0 - (rem), topmiddle: 0, topbottom: 0 + (rem), @@ -585,7 +585,7 @@ }[hori]); axisLabel.append('text') - .attr('y', getVertical(align, defaultLabel.vert)) + .attr('y', getVerticle(align, defaultLabel.vert)) .attr('x', getHorizontal(defaultLabel.hori)) .text(defaultLabel.tag); @@ -779,7 +779,7 @@ return (rem * 0.9); }; - const getVertical = (axisAlign, vertAlign) => ({ + const getVerticle = (axisAlign, vertAlign) => ({ toptop: 0 - (rem), topmiddle: 0, topbottom: 0 + (rem), @@ -807,7 +807,7 @@ axisLabel.append('text') - .attr('y', getVertical(align, defaultLabel.vert)) + .attr('y', getVerticle(align, defaultLabel.vert)) .attr('x', getHorizontal(defaultLabel.hori)) .text(defaultLabel.tag); @@ -1037,7 +1037,7 @@ const axisLabel = parent.append('g') .attr('class', 'axis xAxis'); - const getVertical = vert => ({ + const getVerticle = vert => ({ top: plotHeight - plotHeight, middle: plotHeight / 2, bottom: plotHeight, @@ -1060,7 +1060,7 @@ }[axisAlign + horiAlign]); axisLabel.append('text') - .attr('y', getVertical(defaultLabel.vert)) + .attr('y', getVerticle(defaultLabel.vert)) .attr('x', getHorizontal(align, defaultLabel.hori)) .text(defaultLabel.tag); @@ -1283,7 +1283,7 @@ const axisLabel = parent.append('g') .attr('class', 'axis xAxis'); - const getVertical = vert => ({ + const getVerticle = vert => ({ top: plotHeight - plotHeight, middle: plotHeight / 2, bottom: plotHeight, @@ -1306,7 +1306,7 @@ }[axisAlign + horiAlign]); axisLabel.append('text') - .attr('y', getVertical(defaultLabel.vert)) + .attr('y', getVerticle(defaultLabel.vert)) .attr('x', getHorizontal(align, defaultLabel.hori)) .text(defaultLabel.tag); @@ -1587,7 +1587,7 @@ const axisLabel = parent.append('g') .attr('class', 'axis xAxis'); - const getVertical = vert => ({ + const getVerticle = vert => ({ top: plotHeight - plotHeight, middle: plotHeight / 2, bottom: plotHeight, @@ -1610,7 +1610,7 @@ }[axisAlign + horiAlign]); axisLabel.append('text') - .attr('y', getVertical(defaultLabel.vert)) + .attr('y', getVerticle(defaultLabel.vert)) .attr('x', getHorizontal(align, defaultLabel.hori)) .text(defaultLabel.tag);