Skip to content

Commit

Permalink
feat(calendar): add month legend to CalendarD3 component
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Benitte committed May 11, 2016
1 parent d972002 commit 49a7130
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 67 deletions.
141 changes: 89 additions & 52 deletions src/components/charts/calendar/CalendarD3.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,55 +62,6 @@ class CalendarD3 extends Component {
daySpacing
});


// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Years
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
const yearLegends = wrapper.selectAll('.nivo_calendar_year_legend').data(years);

const yearLabelRotation = direction === DIRECTION_HORIZONTAL ? -90 : 0;

yearLegends.enter()
.append('text')
.text(d => d)
.classed('nivo_calendar_year_legend', true)
.attr('text-anchor', 'middle')
.attr('transform', (d, i) => {
let x = 0;
let y = 0;

if (direction === DIRECTION_HORIZONTAL) {
x = -8;
y = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
} else {
x = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
y = -8;
}

return `translate(${x},${y}) rotate(${yearLabelRotation})`;
})
;

yearLegends
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.attr('transform', (d, i) => {
let x = 0;
let y = 0;

if (direction === DIRECTION_HORIZONTAL) {
x = -8;
y = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
} else {
x = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
y = -8;
}

return `translate(${x},${y}) rotate(${yearLabelRotation})`;
})
;

// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Days
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
Expand Down Expand Up @@ -152,9 +103,9 @@ class CalendarD3 extends Component {
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Months
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
const monthNodes = wrapper.selectAll('.nivo_calendar_month').data(months, d => d.date);
const monthPaths = wrapper.selectAll('.nivo_calendar_month').data(months, d => d.date);

monthNodes.enter()
monthPaths.enter()
.append('path')
.attr('class', 'nivo_calendar_month')
.style({
Expand All @@ -166,7 +117,7 @@ class CalendarD3 extends Component {
.attr('d', d => d.path)
;

monthNodes
monthPaths
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
Expand All @@ -178,6 +129,92 @@ class CalendarD3 extends Component {
})
.attr('d', d => d.path)
;


// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Month legends
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
const monthLegends = wrapper.selectAll('.nivo_calendar_month_legend').data(months, d => d.date);
const monthLegendFormat = d3.time.format('%b');

monthLegends.enter()
.append('text')
.classed('nivo_calendar_month_legend', true)
.text(d => monthLegendFormat(d.date))
.attr('text-anchor', 'middle')
.attr('transform', d => {
if (direction === DIRECTION_HORIZONTAL) {
return `translate(${d.bbox.x + d.bbox.width / 2},${d.bbox.y - 8 - 10})`;
}

return `translate(${d.bbox.x - 8 - 10},${d.bbox.y + d.bbox.height / 2}) rotate(-90)`;
})
.style('opacity', 0)
;

monthLegends
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.delay(d => (d.date.getMonth() + 1) * 30 * transitionStaggering)
.attr('transform', d => {
if (direction === DIRECTION_HORIZONTAL) {
return `translate(${d.bbox.x + d.bbox.width / 2},${d.bbox.y - 8})`;
}

return `translate(${d.bbox.x - 8},${d.bbox.y + d.bbox.height / 2}) rotate(-90)`;
})
.style('opacity', 1)
;


// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Year legends
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————
const yearLegends = wrapper.selectAll('.nivo_calendar_year_legend').data(years);

const yearLabelRotation = direction === DIRECTION_HORIZONTAL ? -90 : 0;

yearLegends.enter()
.append('text')
.text(d => d)
.classed('nivo_calendar_year_legend', true)
.attr('text-anchor', 'middle')
.attr('transform', (d, i) => {
let x = 0;
let y = 0;

if (direction === DIRECTION_HORIZONTAL) {
x = -8;
y = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
} else {
x = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
y = -8;
}

return `translate(${x},${y}) rotate(${yearLabelRotation})`;
})
;

yearLegends
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.attr('transform', (d, i) => {
let x = 0;
let y = 0;

if (direction === DIRECTION_HORIZONTAL) {
x = -8;
y = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
} else {
x = (7 * (cellSize + daySpacing) + yearSpacing) * i + 3.5 * (cellSize + daySpacing);
y = -8;
}

return `translate(${x},${y}) rotate(${yearLabelRotation})`;
})
;
}

componentWillMount() {
Expand Down
43 changes: 28 additions & 15 deletions src/lib/charts/calendar/CalendarLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import _ from 'lodash';
import { DIRECTION_HORIZONTAL } from '../../../constants/directions';


const monthPathGenerator = ({ date, cellSize, yearIndex, yearSpacing, daySpacing, direction }) => {
const monthPathAndBBox = ({ date, cellSize, yearIndex, yearSpacing, daySpacing, direction }) => {
const t1 = new Date(date.getFullYear(), date.getMonth() + 1, 0); // first day of next month
const d0 = date.getDay(); // first day of month
const w0 = d3.time.weekOfYear(date); // first week of month
const d1 = t1.getDay(); // last day of month
const w1 = d3.time.weekOfYear(t1); // last week of month

// offset according to year index
let xO = 0;
let yO = 0;
const yearOffset = yearIndex * (7 * (cellSize + daySpacing) + yearSpacing);
Expand All @@ -29,23 +30,35 @@ const monthPathGenerator = ({ date, cellSize, yearIndex, yearSpacing, daySpacing
xO = yearOffset;
}

let path;
let bbox = { x: xO, y: yO, width: 0, height: 0 };
if (direction === DIRECTION_HORIZONTAL) {
return [
path = [
`M${xO + (w0 + 1) * (cellSize + daySpacing)},${yO + d0 * (cellSize + daySpacing)}`,
`H${xO + w0 * (cellSize + daySpacing)}V${yO + 7 * (cellSize + daySpacing)}`,
`H${xO + w1 * (cellSize + daySpacing)}V${yO + (d1 + 1) * (cellSize + daySpacing)}`,
`H${xO + (w1 + 1) * (cellSize + daySpacing)}V${yO}`,
`H${xO + (w0 + 1) * (cellSize + daySpacing)}Z`
].join('');

bbox.x = xO + w0 * (cellSize + daySpacing);
bbox.width = (w1 + 1) * (cellSize + daySpacing) - bbox.x;
bbox.height = 7 * (cellSize + daySpacing);
} else {
path = [
`M${xO + d0 * (cellSize + daySpacing)},${yO + (w0 + 1) * (cellSize + daySpacing)}`,
`H${xO}V${yO + (w1 + 1) * (cellSize + daySpacing)}`,
`H${xO + (d1 + 1) * (cellSize + daySpacing)}V${yO + w1 * (cellSize + daySpacing)}`,
`H${xO + 7 * (cellSize + daySpacing)}V${yO + w0 * (cellSize + daySpacing)}`,
`H${xO + d0 * (cellSize + daySpacing)}Z`
].join('');

bbox.y = yO + w0 * (cellSize + daySpacing);
bbox.width = 7 * (cellSize + daySpacing);
bbox.height = (w1 + 1) * (cellSize + daySpacing) - bbox.y;
}

return [
`M${xO + d0 * (cellSize + daySpacing)},${yO + (w0 + 1) * (cellSize + daySpacing)}`,
`H${xO}V${yO + (w1 + 1) * (cellSize + daySpacing)}`,
`H${xO + (d1 + 1) * (cellSize + daySpacing)}V${yO + w1 * (cellSize + daySpacing)}`,
`H${xO + 7 * (cellSize + daySpacing)}V${yO + w0 * (cellSize + daySpacing)}`,
`H${xO + d0 * (cellSize + daySpacing)}Z`
].join('');
return { path, bbox };
};


Expand Down Expand Up @@ -128,17 +141,17 @@ const CalendarLayout = () => {

months = months.concat(d3.time.months(yearStart, yearEnd)
.map(monthDate => {
return {
date: monthDate,
path: monthPathGenerator({
return _.assign(
{ date: monthDate },
monthPathAndBBox({
date: monthDate,
direction,
yearIndex: i,
yearSpacing,
daySpacing,
cellSize
}),
};
cellSize,
})
);
})
);
});
Expand Down

0 comments on commit 49a7130

Please sign in to comment.