Skip to content

Commit

Permalink
feat(line): fix line slices for time scales
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte authored and Raphaël Benitte committed Aug 30, 2018
1 parent 31c06c0 commit 82e03d3
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 158 deletions.
28 changes: 13 additions & 15 deletions packages/line/src/LineSlices.js
Expand Up @@ -21,20 +21,18 @@ const LineSlices = ({
tooltipFormat,
}) => (
<g>
{slices.map(slice => {
return (
<LineSlicesItem
key={slice.id}
slice={slice}
height={height}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
tooltipFormat={tooltipFormat}
tooltip={tooltip}
/>
)
})}
{slices.map(slice => (
<LineSlicesItem
key={slice.id}
slice={slice}
height={height}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
tooltipFormat={tooltipFormat}
tooltip={tooltip}
/>
))}
</g>
)

Expand All @@ -49,7 +47,7 @@ LineSlices.propTypes = {
x: PropTypes.number.isRequired,
data: PropTypes.arrayOf(
PropTypes.shape({
normalized: PropTypes.shape({
data: PropTypes.shape({
x: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string,
Expand Down
2 changes: 1 addition & 1 deletion packages/line/src/LineSlicesItem.js
Expand Up @@ -42,7 +42,7 @@ const LineSlicesItem = ({ slice, height, showTooltip, hideTooltip, isHover }) =>
x={-20}
width={40}
height={height}
fill="#000"
fill="#F00"
fillOpacity={0}
onMouseEnter={showTooltip}
onMouseMove={showTooltip}
Expand Down
1 change: 1 addition & 0 deletions packages/line/stories/line.stories.js
Expand Up @@ -131,6 +131,7 @@ stories.add(
xScale={{
type: 'time',
format: '%Y-%m-%d',
precision: 'day',
}}
yScale={{
type: 'linear',
Expand Down
146 changes: 144 additions & 2 deletions packages/line/tests/__snapshots__/Line.test.js.snap
Expand Up @@ -6008,7 +6008,78 @@ exports[`should render a basic line chart 1`] = `
strokeWidth={2}
/>
</g>
<g />
<g>
<g
transform="translate(0, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(125, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(250, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(375, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(500, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
</g>
<g>
<g
style={
Expand Down Expand Up @@ -6830,7 +6901,78 @@ exports[`should support multiple lines 1`] = `
strokeWidth={2}
/>
</g>
<g />
<g>
<g
transform="translate(0, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(125, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(250, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(375, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
<g
transform="translate(500, 0)"
>
<rect
fill="#F00"
fillOpacity={0}
height={300}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
width={40}
x={-20}
/>
</g>
</g>
<g>
<g
style={
Expand Down
52 changes: 26 additions & 26 deletions packages/scales/src/compute.js
Expand Up @@ -7,13 +7,14 @@
* file that was distributed with this source code.
*/
import uniq from 'lodash/uniq'
import uniqBy from 'lodash/uniqBy'
import sortBy from 'lodash/sortBy'
import last from 'lodash/last'
import isDate from 'lodash/isDate'
import { timeParse } from 'd3-time-format'
import { linearScale } from './linearScale'
import { pointScale } from './pointScale'
import { timeScale } from './timeScale'
import { createDateNormalizer } from './timeHelpers'

export const getOtherAxis = axis => (axis === 'x' ? 'y' : 'x')

Expand All @@ -23,14 +24,7 @@ export const compareDateValues = (a, b) => a.getTime() === b.getTime()
export const computeXYScalesForSeries = (_series, xScaleSpec, yScaleSpec, width, height) => {
const series = _series.map(serie => ({
...serie,
data: serie.data.map(d => ({
data: d,
normalized: {
...d,
x: d.x,
y: d.y,
},
})),
data: serie.data.map(d => ({ data: d })),
}))

let xy = generateSeriesXY(series, xScaleSpec, yScaleSpec)
Expand All @@ -49,20 +43,20 @@ export const computeXYScalesForSeries = (_series, xScaleSpec, yScaleSpec, width,
d.position = {
x:
xScale.stacked === true
? d.normalized.xStacked === null
? d.data.xStacked === null
? null
: xScale(d.normalized.xStacked)
: d.normalized.x === null
: xScale(d.data.xStacked)
: d.data.x === null
? null
: xScale(d.normalized.x),
: xScale(d.data.x),
y:
yScale.stacked === true
? d.normalized.yStacked === null
? d.data.yStacked === null
? null
: yScale(d.normalized.yStacked)
: d.normalized.y === null
: yScale(d.data.yStacked)
: d.data.y === null
? null
: yScale(d.normalized.y),
: yScale(d.data.y),
}
})
})
Expand All @@ -86,43 +80,49 @@ export const generateSeriesXY = (series, xScaleSpec, yScaleSpec) => ({
y: generateSeriesAxis(series, 'y', yScaleSpec),
})

/**
* Normalize data according to scale type, (time => Date, linear => Number)
* compute sorted unique values and min/max.
*/
export const generateSeriesAxis = (series, axis, scaleSpec) => {
if (scaleSpec.type === 'linear') {
series.forEach(serie => {
serie.data.forEach(d => {
d.normalized[axis] = d.data[axis] === null ? null : parseFloat(d.data[axis])
d.data[axis] = d.data[axis] === null ? null : parseFloat(d.data[axis])
})
})
} else if (scaleSpec.type === 'time' && scaleSpec.format !== 'native') {
const parseTime = timeParse(scaleSpec.format)
const parseTime = createDateNormalizer(scaleSpec)
series.forEach(serie => {
serie.data.forEach(d => {
d.normalized[axis] = d.data[axis] === null ? null : parseTime(d.data[axis])
d.data[axis] = d.data[axis] === null ? null : parseTime(d.data[axis])
})
})
}

let all = []
series.forEach(serie => {
serie.data.forEach(d => {
all.push(d.normalized[axis])
all.push(d.data[axis])
})
})
all = uniq(all)

let min, max
if (scaleSpec.type === 'linear') {
all = uniq(all)
all = sortBy(all, v => v)
min = Math.min(...all)
max = Math.max(...all)
} else if (scaleSpec.type === 'time') {
all = uniqBy(all, v => v.getTime())
all = all
.slice(0)
.sort((a, b) => b - a)
.reverse()
min = all[0]
max = last(all)
} else {
all = uniq(all)
min = all[0]
max = last(all)
}
Expand All @@ -138,11 +138,11 @@ export const stackAxis = (axis, otherType, xy, series) => {
const compare = isDate(v) ? compareDateValues : compareValues
const stack = []
series.forEach(serie => {
const datum = serie.data.find(d => compare(d.normalized[otherAxis], v))
const datum = serie.data.find(d => compare(d.data[otherAxis], v))
let value = null
let stackValue = null
if (datum !== undefined) {
value = datum.normalized[axis]
value = datum.data[axis]
if (value !== null) {
const head = last(stack)
if (head === undefined) {
Expand All @@ -151,7 +151,7 @@ export const stackAxis = (axis, otherType, xy, series) => {
stackValue = head + value
}
}
datum.normalized[`${axis}Stacked`] = stackValue
datum.data[`${axis}Stacked`] = stackValue
}
stack.push(stackValue)
all.push(stackValue)
Expand All @@ -177,7 +177,7 @@ export const computeAxisSlices = (axis, data) => {
}
const compare = isDate(v) ? compareDateValues : compareValues
data.series.forEach(serie => {
const datum = serie.data.find(d => compare(d.normalized[otherAxis], v))
const datum = serie.data.find(d => compare(d.data[otherAxis], v))
if (datum !== undefined) {
slice.data.push({
...datum,
Expand Down

0 comments on commit 82e03d3

Please sign in to comment.