update dimensions of track according to number of categories

This commit is contained in:
Lachlan Kermode
2020-03-20 15:45:09 +01:00
parent 042ff2df15
commit ffb4548fce
9 changed files with 78 additions and 27 deletions

View File

@@ -196,6 +196,14 @@ export function updateTimeRange (timerange) {
}
}
export const UPDATE_DIMENSIONS = 'UPDATE_DIMENSIONS'
export function updateDimensions (dims) {
return {
type: UPDATE_DIMENSIONS,
dims
}
}
export const UPDATE_NARRATIVE = 'UPDATE_NARRATIVE'
export function updateNarrative (narrative) {
return {

View File

@@ -5,8 +5,13 @@ export const colors = {
white: '#fff'
}
export const sizes = {
eventDotR: 5
}
export default {
darkBackground: colors.black,
primaryHighlight: colors.yellow,
secondaryHighlight: colors.white
secondaryHighlight: colors.white,
sizes
}

View File

@@ -37,6 +37,14 @@ class Dashboard extends React.Component {
if (!this.props.app.isMobile) {
this.props.actions.fetchDomain()
.then(domain => this.props.actions.updateDomain(domain))
.then(({ domain }) => {
// modify trackHeight according to number of categories
if (domain.categories.length === 1) {
this.props.actions.updateDimensions({ trackHeight: 30 })
} else if (domain.categories.length >= 4) {
this.props.actions.updateDimensions({ margin_top: 0, trackHeight: 90 })
}
})
}
}

View File

@@ -5,6 +5,7 @@ import * as selectors from '../selectors'
import hash from 'object-hash'
import copy from '../common/data/copy.json'
import { sizes } from '../common/global'
import { formatterWithYear, parseDate } from '../common/utilities'
import Header from './presentational/Timeline/Header'
import Axis from './TimelineAxis.jsx'
@@ -46,12 +47,17 @@ class Timeline extends React.Component {
})
}
if (hash(nextProps.domain.categories) !== hash(this.props.domain.categories)) {
if ((hash(nextProps.domain.categories) !== hash(this.props.domain.categories)) || hash(nextProps.app.timeline.dimensions) != hash(this.props.app.timeline.dimensions)) {
const { trackHeight, margin_top } = nextProps.app.timeline.dimensions
this.setState({
scaleY: this.makeScaleY(nextProps.domain.categories)
scaleY: this.makeScaleY(nextProps.domain.categoriesWithTimeline, trackHeight, margin_top )
})
}
if (nextProps.app.timeline.dimensions.trackHeight !== this.props.app.timeline.dimensions.trackHeight) {
this.computeDims()
}
if (hash(nextProps.app.selected) !== hash(this.props.app.selected)) {
if (!!nextProps.app.selected && nextProps.app.selected.length > 0) {
this.onCenterTime(parseDate(nextProps.app.selected[0].timestamp))
@@ -73,9 +79,13 @@ class Timeline extends React.Component {
.range([this.state.dims.margin_left, this.state.dims.width - this.state.dims.width_controls])
}
makeScaleY (categories) {
const tickHeight = 15
const catsYpos = categories.map((g, i) => (i + 1) * this.state.dims.trackHeight / categories.length + tickHeight / 2)
makeScaleY (categories, trackHeight, marginTop) {
const tickHeight = sizes.eventDotR * 2
const catHeight = trackHeight / (categories.length)
const shiftUp = trackHeight / (categories.length + 1) / 2
const marginShift = marginTop === 0 ? 0 : marginTop
const manualAdjustment = trackHeight <= 60 ? (trackHeight <= 30 ? -8 : -5) : 0
const catsYpos = categories.map((g, i) => ((i + 1) * catHeight) - shiftUp + marginShift + manualAdjustment)
return d3.scaleOrdinal()
.domain(categories)
.range(catsYpos)
@@ -109,13 +119,12 @@ class Timeline extends React.Component {
this.setState({
dims: {
...this.state.dims,
...this.props.app.timeline.dimensions,
width: boundingClient.width
}
},
() => {
this.setState({ scaleX: this.makeScaleX()
})
this.setState({ scaleX: this.makeScaleX() })
})
}
}
@@ -322,6 +331,7 @@ class Timeline extends React.Component {
getCategoryY={this.state.scaleY}
transitionDuration={this.state.transitionDuration}
styles={this.props.ui.styles}
noCategories={this.props.domain.categories && this.props.domain.categories.length}
/>
<Events
datetimes={this.props.domain.datetimes}

View File

@@ -30,7 +30,12 @@ class TimelineCategories extends React.Component {
return (
<React.Fragment>
<g class='tick' style={{strokeWidth}} opacity='0.5' transform={`translate(0,${this.props.getCategoryY(category.category)})`}>
<g
class='tick'
style={{strokeWidth}}
opacity='0.5'
transform={`translate(0,${this.props.getCategoryY(category.category)})`}
>
<line x1={dims.margin_left} x2={dims.width - dims.width_controls} />
</g>
<g class='tick' opacity='1' transform={`translate(0,${this.props.getCategoryY(category.category)})`}>
@@ -41,7 +46,7 @@ class TimelineCategories extends React.Component {
}
render () {
const dims = this.props.dims
const { dims } = this.props
return (
<g class='yAxis'>
@@ -50,7 +55,7 @@ class TimelineCategories extends React.Component {
ref={this.grabRef}
class='drag-grabber'
x={dims.margin_left}
y='20'
y={dims.margin_top}
width={dims.width - dims.margin_left - dims.width_controls}
height={dims.trackHeight}
/>

View File

@@ -2,6 +2,7 @@ import React from 'react'
import DatetimeDot from './DatetimeDot'
import DatetimeBar from './DatetimeBar'
import { getEventOpacity } from '../../../common/utilities'
import { sizes } from '../../../common/global'
// return a list of lists, where each list corresponds to a single category
function getDotsToRender (events) {
@@ -79,7 +80,6 @@ const TimelineEvents = ({
}
const extraRender = customStyles[1]
const eventWidth = 5
return (
<g className='datetime'>
@@ -89,7 +89,7 @@ const TimelineEvents = ({
events={locatedEvents}
x={getDatetimeX(datetime)}
y={getCategoryY(dot.category)}
r={eventWidth}
r={sizes.eventDotR}
styleProps={locatedProps}
extraRender={extraRender}
/>}
@@ -99,7 +99,7 @@ const TimelineEvents = ({
events={unlocatedEvents}
x={getDatetimeX(datetime)}
y={dims.margin_top}
width={eventWidth}
width={(2 * sizes.eventDotR) * 0.9}
height={dims.trackHeight}
styleProps={unlocatedProps}
/>}

View File

@@ -1,13 +1,15 @@
import React from 'react'
import colors from '../../../common/global.js'
import colors, { sizes } from '../../../common/global'
const MARKER_DISPLACED = sizes.eventDotR * 2
const TimelineMarkers = ({
styles,
getEventX,
getCategoryY,
transitionDuration,
selected,
dims
dims,
noCategories
}) => {
function renderMarker (event) {
const isLocated = !!event.latitude && !!event.longitude
@@ -18,8 +20,7 @@ const TimelineMarkers = ({
cy={0}
stroke={styles ? styles.stroke : colors.primaryHighlight}
stroke-opacity='1'
stroke-width={styles ? styles['stroke-width'] : 2}
stroke-linecap=''
stroke-width={styles ? styles['stroke-width'] : 1}
stroke-linejoin='round'
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
style={{
@@ -28,19 +29,18 @@ const TimelineMarkers = ({
'-moz-transition': 'none',
'opacity': 0.9
}}
r='10'
r={sizes.eventDotR * 2}
/>
) : (
<rect
className='timeline-marker'
x={0}
y={-dims.margin_top}
width={4}
y={-dims.margin_top - (noCategories > 2 ? noCategories * MARKER_DISPLACED : MARKER_DISPLACED)}
width={(2 * sizes.eventDotR) * 0.9}
height={dims.trackHeight}
stroke={styles ? styles.stroke : colors.primaryHighlight}
stroke-opacity='1'
stroke-width={styles ? styles['stroke-width'] : 2}
stroke-linecap=''
stroke-width={styles ? styles['stroke-width'] : 1}
stroke-dasharray={styles ? styles['stroke-dasharray'] : '2,2'}
style={{
'transform': `translate(${getEventX(event)}px, 40px)`,
@@ -48,7 +48,6 @@ const TimelineMarkers = ({
'-moz-transition': 'none',
'opacity': 0.9
}}
r='10'
/>
)

View File

@@ -7,6 +7,7 @@ import {
CLEAR_FILTER,
TOGGLE_FILTER,
UPDATE_TIMERANGE,
UPDATE_DIMENSIONS,
UPDATE_NARRATIVE,
INCREMENT_NARRATIVE_CURRENT,
DECREMENT_NARRATIVE_CURRENT,
@@ -152,6 +153,19 @@ function updateTimeRange (appState, action) { // XXX
}
}
function updateDimensions (appState, action) {
return {
...appState,
timeline: {
...appState.timeline,
dimensions: {
...appState.timeline.dimensions,
...action.dims
}
}
}
}
function toggleLanguage (appState, action) {
let otherLanguage = (appState.language === 'es-MX') ? 'en-US' : 'es-MX'
return Object.assign({}, appState, {
@@ -203,6 +217,8 @@ function app (appState = initial.app, action) {
return toggleFilter(appState, action)
case UPDATE_TIMERANGE:
return updateTimeRange(appState, action)
case UPDATE_DIMENSIONS:
return updateDimensions(appState, action)
case UPDATE_NARRATIVE:
return updateNarrative(appState, action)
case INCREMENT_NARRATIVE_CURRENT:

View File

@@ -65,8 +65,8 @@ const initial = {
width_controls: 100,
height_controls: 115,
margin_left: 100,
margin_top: 20,
trackHeight: 80
margin_top: 15,
trackHeight: 60
},
range: [
new Date(2001, 2, 23, 12),