diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-06-30 17:03:31 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-06-30 17:03:31 +0200 |
| commit | 7bc1723499503800cbdd446b27e202898fc32b9e (patch) | |
| tree | 03480b0dae36c6e97ad524ff667a01d2efe43c82 | |
| parent | bd57b5abf5fc73d5e61d80be1ee509b7afc97ff7 (diff) | |
cursor
6 files changed, 82 insertions, 3 deletions
diff --git a/animism-align/frontend/util/index.js b/animism-align/frontend/util/index.js index baa121c..0615f93 100644 --- a/animism-align/frontend/util/index.js +++ b/animism-align/frontend/util/index.js @@ -53,7 +53,9 @@ export const courtesyS = (n, s) => n + ' ' + (n === 1 ? s : s + 's') export const padSeconds = n => n < 10 ? '0' + n : n export const timestamp = (n = 0, fps = 1) => { + if (n < 0) return '' n /= fps + n = Math.round(n) let s = padSeconds(Math.round(n) % 60) n = Math.floor(n / 60) if (n > 60) { diff --git a/animism-align/frontend/views/align/align.actions.js b/animism-align/frontend/views/align/align.actions.js index 36e17b0..7d8cbd1 100644 --- a/animism-align/frontend/views/align/align.actions.js +++ b/animism-align/frontend/views/align/align.actions.js @@ -15,3 +15,7 @@ export const setZoom = zoom => dispatch => { dispatch({ type: types.align.set_display_setting, key: 'zoom', value: zoom }) } } + +export const setCursor = cursor_ts => dispatch => ( + dispatch({ type: types.align.set_display_setting, key: 'cursor_ts', value: cursor_ts }) +) diff --git a/animism-align/frontend/views/align/align.css b/animism-align/frontend/views/align/align.css index 0910c5a..153c481 100644 --- a/animism-align/frontend/views/align/align.css +++ b/animism-align/frontend/views/align/align.css @@ -20,8 +20,8 @@ canvas { display: flex; flex-direction: row; position: relative; - border-left: 1px solid #333; width: 300px; + cursor: crosshair; } .ticks .tick { @@ -38,4 +38,24 @@ canvas { width: 40px; margin-top: -7px; text-align: right; + text-shadow: 0 0 2px #00f; +} +.timeline .cursor { + width: 100%; + position: absolute; + left: 0; +} +.timeline .cursor .line { + width: 100%; + height: 1px; + background: #00f; +} +.timeline .cursor .tickLabel { + position: absolute; + right: 6px; + font-size: 12px; + width: 40px; + margin-top: -7px; + text-align: right; + text-shadow: 0 0 2px #000, 0 0 2px #000, 0 0 2px #000; }
\ No newline at end of file diff --git a/animism-align/frontend/views/align/align.reducer.js b/animism-align/frontend/views/align/align.reducer.js index 00d77ff..f616dc2 100644 --- a/animism-align/frontend/views/align/align.reducer.js +++ b/animism-align/frontend/views/align/align.reducer.js @@ -5,6 +5,7 @@ import { crudState, crudReducer } from '../../api/crud.reducer' const initialState = { timeline: { + cursor_ts: -1, start_ts: 0, zoom: 1, duration: 0, diff --git a/animism-align/frontend/views/align/components/cursor.component.js b/animism-align/frontend/views/align/components/cursor.component.js new file mode 100644 index 0000000..c92f807 --- /dev/null +++ b/animism-align/frontend/views/align/components/cursor.component.js @@ -0,0 +1,25 @@ +import React, { Component } from 'react' + +import { ZOOM_STEPS } from '../constants' +import { clamp, timestamp } from '../../../util' + +const Cursor = ({ timeline }) => { + const { start_ts, zoom, cursor_ts, duration } = timeline + const secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 + const y = (cursor_ts - start_ts) / secondsPerPixel + return ( + <div + className='cursor' + style={{ + top: y, + }} + > + <div className='line' /> + <div className='tickLabel'> + {timestamp(cursor_ts, 1)} + </div> + </div> + ) +} + +export default Cursor
\ No newline at end of file diff --git a/animism-align/frontend/views/align/components/timeline.component.js b/animism-align/frontend/views/align/components/timeline.component.js index eb851b7..86175cf 100644 --- a/animism-align/frontend/views/align/components/timeline.component.js +++ b/animism-align/frontend/views/align/components/timeline.component.js @@ -8,6 +8,7 @@ import actions from '../../../actions' import Waveform from './waveform.component' import Ticks from './ticks.component' +import Cursor from './cursor.component' import { ZOOM_STEPS } from '../constants' import { clamp } from '../../../util' @@ -16,6 +17,7 @@ class Timeline extends Component { constructor(props){ super(props) this.handleKeydown = this.handleKeydown.bind(this) + this.handleMouseMove = this.handleMouseMove.bind(this) this.handleWheel = this.handleWheel.bind(this) } componentDidMount() { @@ -40,17 +42,42 @@ class Timeline extends Component { handleWheel(e) { let { start_ts, zoom, duration } = this.props.timeline let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step - let widthTimeDuration = window.innerWidth * secondsPerPixel // secs per pixel + let widthTimeDuration = window.innerHeight * secondsPerPixel // secs per pixel start_ts = clamp(start_ts + e.deltaY * ZOOM_STEPS[zoom], 0, Math.max(0, duration - widthTimeDuration / 2)) console.log(start_ts) actions.align.setScrollPosition(start_ts) } + handleMouseMove(e) { + const { start_ts, zoom, duration } = this.props.timeline + const y = e.pageY + const height = window.innerHeight + + let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 + let widthTimeDuration = height * secondsPerPixel + + let timeMin = start_ts + let timeMax = Math.min(start_ts + widthTimeDuration, duration) + let timeWidth = timeMax - timeMin + + let cursor_ts = y * secondsPerPixel + start_ts + cursor_ts = clamp(cursor_ts, 0, timeMax) + + actions.align.setCursor(cursor_ts) + + // let pixelMin = timeMin / secondsPerPixel + // const ts = + } render() { return ( - <div className='timeline' onWheel={this.handleWheel}> + <div + className='timeline' + onWheel={this.handleWheel} + onMouseMove={this.handleMouseMove} + > <Waveform /> <Ticks timeline={this.props.timeline} /> + <Cursor timeline={this.props.timeline} /> </div> ) } |
