{
let {cast, action} = actress
cast = _.filter(cast, d => d3.timeDay.count(new Date(d.release_date), maxYear) > 0)
action = _.filter(action, d => d3.timeDay.count(new Date(d.release_date), maxYear) > 0)
const birthday = new Date(actress.birthday)
const startAngle = angleScale(birthday)
const width = embroiderySize * dpi
const height = 2.5 * dpi
const svg = d3.select(DOM.svg(width, height))
const minMonths = 3
const maxMonths = 30
const xScale = d3.scaleLinear(
[birthday, maxYear],
[margin.left, width - margin.right],
)
const yScale = d3.scaleSqrt(
d3.extent(cast, d => d.total - d.order),
[height - 2 * margin.bottom, margin.top],
)
const lineGen = d3.line()
.x(d => d.x).y(d => d.y)
.curve(d3.curveBasis)
function calcPaths(birthday, cast, index) {
return _.chain(cast)
.filter(d => d.release_date)
.sortBy(d => new Date(d.release_date))
.map(d => {
const date = new Date(d.release_date)
const mx = xScale(date)
const my = yScale(d.total - d.order)
const offset = maxMonths
const x1 = xScale(d3.timeMonth.offset(date, -offset))
const x2 = xScale(d3.timeMonth.offset(date, offset))
const y1 = height - margin.bottom
const dx = (mx - x1) / 10
const dy = (my - y1) / 2
console.log(mx, dx, my, dy)
return {
path: `
M${x1},${y1}
C${x1 + dx},${y1} ${mx - dx},${my} ${mx},${my}
C${mx + dx},${my} ${x2 - dx},${y1} ${x2},${y1}
`,
color: index ? '#68e8bb' : '#54a7fa',
title: d.title,
}
})
.value()
}
const others = _.differenceBy(cast, action, d => d.id)
const paths = _.chain([action, others])
.map((cast, i) => calcPaths(birthday, cast, i))
// .flatten()
.value()
const dots = _.chain(cast)
.sortBy(d => new Date(d.release_date))
.map(({title, release_date, total, order, genres}) => {
const isAction = _.includes(genres, 'Action')
return {
title: title,
x: xScale(new Date(release_date)),
y: yScale(total - order),
color: !isAction ? '#68e8bb' : '#54a7fa',
lineWidth: !isAction ? 1 : 2,
}
}).groupBy('lineWidth').values().value()
console.log(dots)
// start drawing
// actress
const mountain = svg.append('g').attr('id', 'mountains')
.selectAll('g').data(paths).join('g')
mountain.selectAll('path')
.data(d => d).join('path')
.attr('d', d => d.path)
.attr('id', d => d.title)
.attr('fill', 'none')
.attr('stroke', d => d.color)
// .attr('opacity', 0.5)
// .attr('stroke-width', 2)
const movies = svg.append('g').attr('id', 'movies')
.selectAll('g').data(dots).join('g')
.attr('transform', (d, i) => `translate(0, ${(i + 1) * 5})`)
movies.selectAll('circle')
.data(d => d).join('circle')
.attr('id', d => d.title)
.attr('transform', d => `translate(${d.x}, 0)`)
.attr('fill', 'none')
.attr('stroke', d => d.color)
.attr('stroke-width', d => d.lineWidth)
.attr('r', 3)
svg.append('rect')
.attr('width', width)
.attr('height', height)
.attr('fill', 'none')
.attr('stroke', '#000')
return scrollSVG(svg.node())
}