Skip to content

Commit f17b079

Browse files
committed
keyframe indicator on timeline
1 parent 336df87 commit f17b079

File tree

5 files changed

+62
-1
lines changed

5 files changed

+62
-1
lines changed

src/Header/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export const Header = ({
4343
currentVideoTime,
4444
multipleImages,
4545
videoPlaying,
46-
onChangeCurrentTime
46+
onChangeCurrentTime,
47+
keyframes
4748
}: Props) => {
4849
const classes = useStyles()
4950
return (
@@ -53,6 +54,7 @@ export const Header = ({
5354
currentTime={currentVideoTime}
5455
duration={videoDuration}
5556
onChangeCurrentTime={onChangeCurrentTime}
57+
keyframes={keyframes}
5658
/>
5759
<div className={classes.headerActions}>
5860
<HeaderButtonContext.Provider value={{ onHeaderButtonClick }}>

src/KeyframeTimeline/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,39 @@ const PositionCursor = styled("div")({
6464
}
6565
})
6666

67+
const KeyframeMarker = styled("div")({
68+
position: "absolute",
69+
bottom: 8,
70+
cursor: "pointer",
71+
opacity: 0.75,
72+
fontSize: 10,
73+
fontWeight: "bold",
74+
color: "#fff",
75+
display: "grid",
76+
placeItems: "center",
77+
width: 16,
78+
marginLeft: 0,
79+
borderTopLeftRadius: 2,
80+
borderTopRightRadius: 2,
81+
height: 12,
82+
marginLeft: -8,
83+
backgroundColor: colors.red[500],
84+
userSelect: "none",
85+
fontVariantNumeric: "tabular-nums",
86+
87+
"&::before": {
88+
position: "absolute",
89+
bottom: -8,
90+
left: 0,
91+
content: '""',
92+
width: 0,
93+
height: 0,
94+
borderTop: `8px solid ${colors.red[500]}`,
95+
borderLeft: "8px solid transparent",
96+
borderRight: "8px solid transparent"
97+
}
98+
})
99+
67100
const min = 60000
68101
const displayIntervalPairs = [
69102
[50, 250],
@@ -98,6 +131,10 @@ export default ({
98131
const [ref, bounds] = useMeasure()
99132
const [instantCurrentTime, changeInstantCurrentTime] = useState(currentTime)
100133
const [draggingTime, changeDraggingTime] = useRafState(false)
134+
const keyframeTimes = Object.keys(keyframes || {})
135+
.map(t => parseInt(t))
136+
.filter(t => !isNaN(t))
137+
.sort((a, b) => a - b)
101138

102139
useEffect(() => {
103140
if (currentTime !== instantCurrentTime) {
@@ -159,6 +196,13 @@ export default ({
159196
}}
160197
/>
161198
))}
199+
{keyframeTimes.map(kt => (
200+
<KeyframeMarker
201+
onClick={() => onChangeCurrentTime(kt)}
202+
key={kt}
203+
style={{ left: (kt / duration) * bounds.width }}
204+
/>
205+
))}
162206
<PositionCursor
163207
onMouseDown={e => changeDraggingTime(true)}
164208
style={{

src/MainLayout/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export const MainLayout = ({ state, dispatch }: Props) => {
9090
onChangeCurrentTime={action("CHANGE_VIDEO_TIME", "newTime")}
9191
videoPlaying={state.videoPlaying}
9292
currentVideoTime={state.currentVideoTime}
93+
keyframes={state.keyframes}
9394
/>
9495
</div>
9596
<div className={classes.workspace}>

src/SettingsDialog/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ export const SettingsDialog = ({ open, onClose }) => {
2626
type: "boolean",
2727
title: "Show Crosshairs",
2828
name: "showCrosshairs"
29+
},
30+
{
31+
type: "dropdown",
32+
title: "Video Playback Speed",
33+
name: "videoPlaybackSpeed",
34+
defaultValue: "1x",
35+
choices: ["0.25x", "0.5x", "1x", "2x"]
2936
}
3037
]
3138
}}

src/VideoOrImageCanvasBackground/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import React, { useRef, useEffect, useMemo } from "react"
44
import { styled } from "@material-ui/core/styles"
55
import useEventCallback from "use-event-callback"
6+
import { useSettings } from "../SettingsProvider"
67

78
const Video = styled("video")({
89
zIndex: 0,
@@ -25,6 +26,7 @@ export default ({
2526
onChangeVideoTime,
2627
onChangeVideoPlaying
2728
}) => {
29+
const settings = useSettings()
2830
const videoRef = useRef()
2931
const imageRef = useRef()
3032

@@ -40,6 +42,11 @@ export default ({
4042
if (videoPlaying) {
4143
videoRef.current.play()
4244
renderLoopRunning = true
45+
if (settings.videoPlaybackSpeed) {
46+
videoRef.current.playbackRate = parseFloat(
47+
settings.videoPlaybackSpeed
48+
)
49+
}
4350
} else {
4451
videoRef.current.pause()
4552
}

0 commit comments

Comments
 (0)