<div id="app"></div>
@import url("//fonts.googleapis.com/css?family=Press+Start+2P");
body {
font-family: 'Press Start 2P', cursive;
background:#000;
line-height:20px;
}
button {
background-color: #f4fc67;
font-family: 'Press Start 2P', cursive;
box-shadow:2px 2px #000;
border:1px solid #000;
padding:3px;
outline:none;
font-size:14px;
}
button:hover {
box-shadow:5px 5px #000;
}
button:focus {
outline:0 !important;
}
.cs-instructions {
background-image: url('https://i.imgur.com/1woliuF.png');
background-size: contain;
background-position: bottom left;
background-repeat: no-repeat;
position: relative;
z-index: 1;
height:342px;
width: 467px;
margin:0 auto;
}
.cs-instructions-inner {
background-color:#fff;
background-image: url('https://i.imgur.com/6aOej4c.jpg');
background-size: contain;
background-position: bottom left;
background-repeat:repeat-y;
font-size:14px;
line-height:30px;
padding:10px 30px 10px 30px;
margin:10px 0 0 38px;
min-height:120px;
width:330px;
overflow-y:hidden;
position: absolute;
color:#000;
z-index: 2;
bottom:190px;
}
.mb-4 {
margin-bottom:20px;
}
.mb-0 {
margin-bottom:0;
}
.credits {
text-align:center;
margin-top:40px;
color:#444;
font-size:9px;
}
.credits a {
color:#444;
text-decoration:none;
}
class Typewriter extends React.Component {
constructor(props){
super(props);
this.myDiv = null;
this.mySound = null;
this.typewriter = element => {
this.myDiv = element;
};
this.setmySound = element => {
this.mySound = element;
};
this.playSound = this.playSound.bind(this);
this.pauseSound = this.pauseSound.bind(this);
}
playSound() {
if (this.mySound && (this.mySound.duration === 0 || this.mySound.paused)) {
this.mySound.play();
}
}
pauseSound() {
if(this.mySound){
this.mySound.pause();
}
}
typeWriter = (s, i=0) => {
if (this.myDiv && i < s.length) {
this.myDiv.innerHTML += s.charAt(i);
i++;
if(i>5) {
this.props.setScroll();
}
this.playSound();
setTimeout(() => this.typeWriter(s, i), 40);
}
else {
this.pauseSound();
if(this.props.nextStep){
this.props.nextStep();
}
}
}
componentDidMount() {
if(this.myDiv) {
setTimeout(() => this.typeWriter(this.props.mystring), 200);
}
}
componentWillUnmount() {
this.pauseSound();
}
render() {
return (
<div className={this.props.mb}>
<audio autoPlay preload="auto" ref={this.setmySound} src="https://freesound.org/data/previews/138/138049_2423928-lq.mp3" type="audio/mpeg" > </audio>
<span ref={this.typewriter}> </span>
</div>
);
}
}
class App extends React.Component {
constructor(){
super();
this.state = {
step: 0
}
this.myDiv = null;
this.instructions = element => {
this.myDiv = element;
};
this.setScroll = this.setScroll.bind(this);
}
setScroll() {
this.myDiv.scrollTo(0, this.myDiv.scrollHeight);
}
nextStep = () => this.setState({step: this.state.step + 1});
render(){
return(
<div className="wrapper">
<div className="cs-instructions">
<div className="cs-instructions-inner" ref={this.instructions}>
{
this.state.step === 0
? <button onClick={() => {this.nextStep()}}>CLICK TO START THE CASE</button>
: ''
}
{
this.state.step > 0
? <Typewriter mb={'mb-4'} nextStep={this.nextStep} setScroll={this.setScroll} mystring="****** FLASH ******"></Typewriter>
: ''
}
{
this.state.step > 1
? <Typewriter mb={'mb-4'} nextStep={this.nextStep} setScroll={this.setScroll} mystring="National treasure stolen from Paris."></Typewriter>
: ''
}
{
this.state.step > 2
? <Typewriter mb={'mb-0'} nextStep={this.nextStep} setScroll={this.setScroll} mystring="The treasure has been identified as the elevator from the Eiffel Tower."></Typewriter>
: ''
}
{
this.state.step > 3
? <button className="mb-4" onClick={() => {this.nextStep()}}>Click to continue</button>
: ''
}
{
this.state.step > 4
? <Typewriter mb={'mb-0'} nextStep={this.nextStep} setScroll={this.setScroll} mystring="Female suspect reported at the scene of the crime. Your assignement: Track the thief from Paris to her hideout and arrested her!"></Typewriter>
: ''
}
{
this.state.step > 5
? <button className="mb-4" onClick={() => {this.nextStep()}}>Click to continue</button>
: ''
}
{
this.state.step > 6
? <Typewriter mb={'mb-0'} setScroll={this.setScroll} mystring="You must apprehend the thief by Sunday, 5 pm. Good luck ! "></Typewriter>
: ''
}
</div>
</div>
<div className="credits">Typewriter effect realised with ReactJS inspired by Carmen Sandiego 1991 MS-DOS <br/><a href="https://www.julien-verkest.fr/" target="_blank">Julien Verkest ©️ april 2019 </a> </div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
View Compiled
This Pen doesn't use any external CSS resources.