diff options
Diffstat (limited to 'frontend/site/projects/museum/views/titles.overlay.js')
| -rw-r--r-- | frontend/site/projects/museum/views/titles.overlay.js | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/frontend/site/projects/museum/views/titles.overlay.js b/frontend/site/projects/museum/views/titles.overlay.js new file mode 100644 index 0000000..26acc05 --- /dev/null +++ b/frontend/site/projects/museum/views/titles.overlay.js @@ -0,0 +1,136 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' + +import { SUBTITLES } from '../subtitles.js' + +import './titles.css' + +const TITLE_SHOW_DELAY = 1000 +const TITLE_HIDE_DELAY = 6000 +const FIRST_SUBTITLE_DELAY = 3000 +const SUBTITLE_DELAY = 3500 +const LAST_SUBTITLE_DELAY = 5000 + +class TitlesOverlay extends Component { + state = { + content: null, + } + + constructor(props) { + super(props) + this.titleRef = React.createRef() + this.subtitleRef = React.createRef() + this.showTitle = this.showTitle.bind(this) + this.nextSubtitle = this.nextSubtitle.bind(this) + } + + componentDidMount() { + if (this.props.interactive) { + this.load() + } + } + + componentDidUpdate(prevProps) { + if ( + (this.props.interactive && this.props.interactive !== prevProps.interactive) + || this.props.location.pathname !== prevProps.location.pathname + ) { + this.load() + } + if ( + this.props.popups !== prevProps.popups + && this.state.content + && this.state.content.popup + && this.props.popups[this.state.content.popup] + ) { + this.startSubtitles() + } + } + + load() { + const { page_name } = this.props.match.params + clearTimeout(this.titleTimeout) + clearTimeout(this.subtitleTimeout) + this.props.audio.player.stop("text-overlay") + if (SUBTITLES[page_name]) { + this.setState({ + content: SUBTITLES[page_name], + open: false, + }) + setTimeout(this.showTitle, 0) + } else { + this.setState({ + content: null, + open: false, + }) + } + } + + showTitle() { + if (!this.titleRef.current) return + this.titleRef.current.style.color = this.state.content.color || "rgba(255, 121, 13, 1.0)" + this.titleRef.current.style.opacity = 0 + this.titleTimeout = setTimeout(() => { + this.titleRef.current.style.opacity = 1 + this.titleTimeout = setTimeout(() => { + this.titleRef.current.style.opacity = 0 + }, TITLE_HIDE_DELAY) + }, TITLE_SHOW_DELAY) + } + + startSubtitles() { + if (this.state.content.audio_url) { + this.props.audio.player.stop("text-overlay") + this.props.audio.player.playURL({ + id: "text-overlay", + url: this.state.content.audio_url, + }) + } + clearTimeout(this.subtitleTimeout) + this.index = -1 + this.subtitleTimeout = setTimeout(this.nextSubtitle, FIRST_SUBTITLE_DELAY) + } + + nextSubtitle() { + if (!this.subtitleRef.current) return + this.index += 1 + const subtitle = this.state.content.subtitles[this.index] || "" + this.subtitleRef.current.style.color = this.state.content.color || "rgba(255, 121, 13, 1.0)" + this.subtitleRef.current.innerHTML = subtitle + if (this.index === (this.state.content.subtitles.length - 1)) { + this.subtitleTimeout = setTimeout(this.nextSubtitle, LAST_SUBTITLE_DELAY) + } + else if (subtitle.length) { + this.subtitleTimeout = setTimeout(this.nextSubtitle, SUBTITLE_DELAY) + } + } + + render() { + const { content } = this.state + const { popups, interactive } = this.props + if (!interactive || !content) return null + return ( + <div> + <div + ref={this.titleRef} + className="chapter-title" + dangerouslySetInnerHTML={{ __html: content.title }} + /> + {content.popup && popups[content.popup] && ( + <div + ref={this.subtitleRef} + className="subtitles" + /> + )} + </div> + ) + } +} + +const mapStateToProps = state => ({ + audio: state.audio, + popups: state.site.popups, + interactive: state.site.interactive, +}) + +export default connect(mapStateToProps)(TitlesOverlay) |
