Skip to content

Commit

Permalink
feat(time-slider): improve time slider (#461)
Browse files Browse the repository at this point in the history
* feat(time-slider): improve time slider

* feat(time-slider): use circle icons for play button
  • Loading branch information
pwambach authored Aug 12, 2020
1 parent 2d91e01 commit 8bb6d44
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 59 deletions.
12 changes: 12 additions & 0 deletions src/scripts/components/icons/pause-circle-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, {FunctionComponent} from 'react';

export const PauseCircleIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M9 16h2V8H9v8zm3-14C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm1-4h2V8h-2v8z" />
</svg>
);
12 changes: 12 additions & 0 deletions src/scripts/components/icons/play-circle-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, {FunctionComponent} from 'react';

export const PlayCircleIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
</svg>
);
17 changes: 6 additions & 11 deletions src/scripts/components/time-slider-range/time-slider-range.styl
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,25 @@ boxShadow()
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2), 0px 3px 4px rgba(0, 0, 0, 0.12), 0px 2px 4px rgba(0, 0, 0, 0.14)

.track
position: absolute
top: $range-height
position: relative
width: 100%
height: $range-height
border-radius: emCalc(2px)
background: $darkGrey4

&:not(:first-of-type)
top: $range-height * 3

.range
position: absolute
top: 0
z-index: 1
display: flex
height: $range-height
border-radius: emCalc(2px)
background: $main
background: $textWhite

.tick
position: absolute
width: emCalc(5px)
height: emCalc(5px)
border-radius: 50%
background-color: rgba($darkGrey4, 0.5)
width: emCalc(1px)
height: emCalc(3px)
background-color: rgba($darkGrey4, 0.75)
transition: 0.2s all ease-out
transform: translateX(-50%)
transform: translate(-50%, 1px) scaleX(0.5)
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const TimeSliderRange: FunctionComponent<Props> = ({

return {
left: `${tickPosition}%`,
backgroundColor: isSelected ? 'white' : undefined, // eslint-disable-line no-undefined
transform: isSelected ? 'translateX(-50%) scale(2)' : undefined // eslint-disable-line no-undefined
backgroundColor: isSelected ? '#00AE9D' : undefined, // eslint-disable-line no-undefined
transform: isSelected ? 'translate(-50%, 1px) scale(3)' : undefined // eslint-disable-line no-undefined
};
};

Expand Down
54 changes: 36 additions & 18 deletions src/scripts/components/time-slider/time-slider.styl
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,30 @@ thumb()

compareThumb()
width: 10px
height: 25px
border-radius: emCalc(4px)

boxShadow()
height: 60px
border-radius: 0
background-color: transparent
background-image: url("data:image/svg+xml,%3Csvg width='100%25' height='100%25' viewBox='0 0 5 30' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' xmlns:serif='http://www.serif.com/' style='fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;'%3E%3Cg transform='matrix(1,0,0,1,-5,-4)'%3E%3Cg transform='matrix(1,0,0,0.666667,0,1.33333)'%3E%3Cpath d='M5,5C5,4.448 5.448,4 6,4L9,4C9.552,4 10,4.448 10,5L10,8C10,9.105 9.105,10 8,10L8,43C9.105,43 10,43.895 10,45L10,48C10,48.552 9.552,49 9,49L6,49C5.448,49 5,48.552 5,48L5,45C5,43.895 5.895,43 7,43L7,10C5.895,10 5,9.105 5,8L5,5Z' style='fill:rgb(0,174,157);'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
background-repeat: no-repeat
box-shadow: none
transform: translateY(-7px)

.timeSlider
position: absolute
bottom: emCalc(65px)
bottom: emCalc(80px)
display: flex
justify-content: center
width: 100%
font-size: emCalc(16px)

.timeSliderCompare
bottom: emCalc(100px)

.container
position: relative
display: flex
min-width: 400px
width: 30%
width: 40%

.label
display: flex
Expand All @@ -42,24 +49,21 @@ compareThumb()
.ranges
position: relative
width: 100%
height: $range-height * 2

.input, .compareInput
position: relative
position: absolute
top: 0
z-index: 2
margin: 0
width: 100%
outline: 0
background: transparent
-webkit-appearance: none

.compareInput
top: $range-height

.input::-webkit-slider-thumb
thumb()

margin-top: 0
margin-top: -5px
-webkit-appearance: none

.input::-moz-range-thumb
Expand All @@ -71,7 +75,7 @@ compareThumb()
thumb()

.compareInput::-webkit-slider-thumb
margin-top: -5px
margin-top: -6px

compareThumb()

Expand All @@ -83,16 +87,30 @@ compareThumb()

.timeOutput
position: absolute
bottom: 15px
top: -14px
padding: 0 4px
color: $textWhite
transform: translateX(-50%)
font-size: 0.9em
transform: translate(-50%, -100%)

.timeOutputMain
transform: translate(-100%, -100%)

.timeOutputCompare
top: 50px
transform: translate(0, 0)

.playButton
position: absolute
top: -4px
right: calc(100% + 1em)
margin-top: emCalc(-21px)
padding-right: 1em
transform: scale(1.2)

.playButtonCompare
margin-top: 0

.yearLabel
display: flex
justify-content: space-between
padding: 4px 0
color: $textWhite
font-size: 0.8em
71 changes: 43 additions & 28 deletions src/scripts/components/time-slider/time-slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {getLayerTimeIndex} from '../../libs/get-layer-tile-url';
import TimeSliderRange from '../time-slider-range/time-slider-range';
import TimePlayback from '../time-playback/time-playback';
import Button from '../button/button';
import {PlayIcon} from '../icons/play-icon';
import {PauseIcon} from '../icons/pause-icon';
import {PlayCircleIcon} from '../icons/play-circle-icon';
import {PauseCircleIcon} from '../icons/pause-circle-icon';

import styles from './time-slider.styl';

Expand Down Expand Up @@ -71,14 +71,6 @@ const TimeSlider: FunctionComponent = () => {
const timeSelectedCompare =
rangeCompare && new Date(rangeCompare.timestamps[timeIndexCompare]);

// get the label time - the tick time which is closest to the slider's time
const timeDiffMain = Math.abs(Number(timeSelectedMain) - time);
const timeDiffCompare = Math.abs(Number(timeSelectedCompare) - time);
const labelTime =
typeof timeDiffCompare === 'number' && timeDiffCompare < timeDiffMain
? timeSelectedCompare
: timeSelectedMain;

// update app state
const debouncedSetGlobeTime = useCallback(
debounce((newTime: number) => dispatch(setGlobeTime(newTime)), DELAY, {
Expand All @@ -102,21 +94,29 @@ const TimeSlider: FunctionComponent = () => {
const labelPosition = Number(
((time - combined.min) * 100) / (combined.max - combined.min)
);
const clampedLabelPosition = Math.max(Math.min(labelPosition, 100), 0);

const inputStyles = cx(
styles.input,
rangeMain && rangeCompare && styles.compareInput
);

return (
<div className={styles.timeSlider}>
<div
className={cx(
styles.timeSlider,
rangeCompare && styles.timeSliderCompare
)}>
{isPlaying && (
<TimePlayback minTime={combined.min} maxTime={combined.max} />
)}
<div className={styles.container}>
<Button
className={styles.playButton}
icon={isPlaying ? PauseIcon : PlayIcon}
className={cx(
styles.playButton,
rangeCompare && styles.playButtonCompare
)}
icon={isPlaying ? PauseCircleIcon : PlayCircleIcon}
onClick={() => setIsPlaying(!isPlaying)}>
{isPlaying ? 'playing' : 'pausing'}
</Button>
Expand All @@ -136,27 +136,34 @@ const TimeSlider: FunctionComponent = () => {
step={stepSize}
/>

<output
className={styles.timeOutput}
style={{
left: `${labelPosition}%`
}}>
{labelTime ? format(labelTime) : false}
</output>

{rangeMain && (
<TimeSliderRange
range={rangeMain}
combined={combined}
selectedTimeIndex={timeIndexMain}
/>
<output
className={cx(
styles.timeOutput,
rangeCompare && styles.timeOutputMain
)}
style={{
left: `${clampedLabelPosition}%`
}}>
{timeSelectedMain ? format(timeSelectedMain) : false}
</output>
)}

{rangeCompare && (
<output
className={cx(styles.timeOutput, styles.timeOutputCompare)}
style={{
left: `${clampedLabelPosition}%`
}}>
{timeSelectedCompare ? format(timeSelectedCompare) : false}
</output>
)}

{rangeMain && (
<TimeSliderRange
range={rangeCompare}
range={rangeMain}
combined={combined}
selectedTimeIndex={timeIndexCompare}
selectedTimeIndex={timeIndexMain}
/>
)}

Expand All @@ -168,6 +175,14 @@ const TimeSlider: FunctionComponent = () => {
<FormattedDate value={combined.max} year="numeric" />
</div>
</div>

{rangeCompare && (
<TimeSliderRange
range={rangeCompare}
combined={combined}
selectedTimeIndex={timeIndexCompare}
/>
)}
</div>
</div>
</div>
Expand Down

0 comments on commit 8bb6d44

Please sign in to comment.