Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

68 newspaper scene #101

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/interview_assets/dummy_sound.mp3
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export const App: React.FC = () => (
<Switch>
<Route path="/vom-esstisch-in-die-arktis" component={Chapter1} />
<Route path="/mobilitaet" component={Chapter2} />

<Route path="/blog/:slug" component={Post} />
<Route path="/blog" component={Blog} />
<Route exact path="/" component={Stories} />
Expand Down
120 changes: 120 additions & 0 deletions src/components/audio-player/AudioFileInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React, { useState, useEffect, useRef } from "react";
import altImg from "./kapitel1_testimonial-1.png"
import './range.css';

const AudioFileInfo = ({ interview } ) => {
const [isPlaying, setIsPlaying] = useState(false);
const [duration, setDuration] = useState(0);
const [currentTime, setCurrentTime] = useState(0);

const { text, imgSrc, audioSrc } = interview;

const audioRef = useRef(new Audio(audioSrc));
const progressBar = useRef<HTMLInputElement>(null);
const animationRef = useRef(0);

useEffect(() => {
const seconds = Math.floor(audioRef.current.duration);
setDuration(seconds);
const node = progressBar.current;
if(progressBar.current != null){
}
if(node != null){

node.max = seconds.toString();
}
}, [audioRef?.current?.readyState]);

audioRef.current.onloadedmetadata = function () {
const seconds = Math.floor(audioRef.current.duration);
setDuration(seconds);
const node = progressBar.current;
if(node != null){
node.max = seconds.toString();
}
}

const calcTime = (secs: number) => {
const minutes = Math.floor(secs / 60);
const retMinutes = minutes < 10 ? `0${minutes}`:`${minutes}`;
const seconds = Math.floor(secs % 60);
const retSeconds = seconds < 10? `0${seconds}`:`${seconds}`
return `${retMinutes}:${retSeconds}`;
}

const handlePlayClick = () => {
const prevValue = isPlaying;
setIsPlaying(!prevValue);
if(prevValue){
audioRef.current.pause();
cancelAnimationFrame(animationRef.current);
} else {
audioRef.current.play();
animationRef.current = requestAnimationFrame(whilePlaying);
}
};

const whilePlaying = () => {
console.log('progress bar value: ', progressBar.current?.value);
console.log('progress bar max value: ', progressBar.current?.max);
console.log('current time value: ', audioRef.current.currentTime);
console.log('current time value floored: ', Math.floor(audioRef.current.currentTime));
if (progressBar.current != null && audioRef.current.currentTime !== (null || undefined)){
progressBar.current.valueAsNumber = Math.floor(audioRef.current.currentTime);
}
progressBar.current?.style.setProperty('--seek-before-width', `${Number(progressBar.current?.value) / duration * 100}%`);
setCurrentTime(Number(progressBar.current?.value));
animationRef.current = requestAnimationFrame(whilePlaying);
}

const changeRange = () => {
audioRef.current.currentTime = Number(progressBar.current?.value);
progressBar.current?.style.setProperty('--seek-before-width', `${Number(progressBar.current?.value) / duration * 100}%`);
setCurrentTime(Number(progressBar.current?.value));
}

return (
<div className=" bg-em1-extralight h-240 relative ">
<div className="flex flex-auto">
{interview.imgSrc ?
<img className="w-1/2 object-cover" id="audio-player-image" src={imgSrc} alt=""/> :
<img className="w-1/2 object-cover" id="audio-player-image" src={altImg} alt=""/>
}
<div className="flex items-center w-1/2 container mx-auto px-4 md:px-12 -mt-12 text-xxs sm:text-sm md:text-base overflow-hidden">{text}</div>
<div className="flex items-center absolute justify-between bottom-0 mx-auto py-2 bg-white bg-opacity-60 right-0 left-0">

<svg className="mx-4" id="audio-button" width="40" height="40" viewBox="0 0 40 40" onClick={() => handlePlayClick()}>
<circle id="play-button" cx="20" cy="20" r="20" fill="#fff"/>
{
!isPlaying ?
<path id="Icon_awesome-play" data-name="Icon awesome-play" d="M20.051,9.921,3.421.306A2.256,2.256,0,0,0,0,2.214V21.44a2.267,2.267,0,0,0,3.421,1.908l16.631-9.611A2.191,2.191,0,0,0,20.051,9.921Z" transform="translate(14.5 12.5) scale(0.65 0.65)" fill="#197eb7"/>
:
<g transform="translate(12.5 12.5) scale(0.055 0.055)" fill="#197eb7">
<path d="M14.22,45.665v186.013c0,25.223,16.711,45.66,37.327,45.66c20.618,0,37.339-20.438,37.339-45.66V45.665
c0-25.211-16.721-45.657-37.339-45.657C30.931,0,14.22,20.454,14.22,45.665z"/>
<path d="M225.78,0c-20.614,0-37.325,20.446-37.325,45.657V231.67c0,25.223,16.711,45.652,37.325,45.652s37.338-20.43,37.338-45.652
V45.665C263.109,20.454,246.394,0,225.78,0z"/>
</g>
}
</svg>
<div className="flex-grow mx-4 -t-2">
<input type="range" className="range" step="1" min="0" defaultValue="0" ref={progressBar} onChange={changeRange}></input>
<div className="flex justify-between">
<p className="text-xs">
{ calcTime(currentTime) }
</p>
{(duration && !isNaN(duration)) &&
<p className="text-xs">
{ calcTime(duration) }
</p>
}
</div>
</div>
</div>
</div>

</div>
);
}

export default AudioFileInfo;
35 changes: 35 additions & 0 deletions src/components/audio-player/AudioPlayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useState } from "react";
import AudioFileInfo from "./AudioFileInfo";
import { Interview } from "./interview"

const AudioPlayer = (props: {interviews: Interview[]}) => {
const [tabOpened, setTabOpened] = useState(0);

const handleClick = (id: number) => {
setTabOpened(id);
};

return(
<div className="container mx-auto px-6 sm:px-16 md:px-20">
{props.interviews.map((i, id) => {

return (
<div className="rounded-xl overflow-hidden bg-white m-2 z-10 opacity-95 text-gray-900" key={id}>
<div id="title-bar" className="flex flex-row flex-auto p-1 z-10" onClick={() => handleClick(id)}>
<div className="px-6 p-1 font-bold text-xs sm:text-sm md:text-base z-10"> {i.title} </div>
<div className="p-1 text-xs sm:text-sm md:text-base z-10"> {i.description} </div>
</div>

{id === tabOpened &&
<AudioFileInfo interview={i}></AudioFileInfo>
}
</div>

);
})}

</div>
);
}

export default AudioPlayer;
14 changes: 14 additions & 0 deletions src/components/audio-player/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import AudioPlayer from "./AudioPlayer";
import { interviews } from "./interviews";

const AudioIndex = () => {

return(

<AudioPlayer interviews={interviews}></AudioPlayer>

)
}

export default AudioIndex;
8 changes: 8 additions & 0 deletions src/components/audio-player/interview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type Interview = {
title: string,
description: string,
text: string,
imgSrc: string,
audioSrc: string,
isOpen: boolean
}
29 changes: 29 additions & 0 deletions src/components/audio-player/interviews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

import { Interview } from "./interview";

export const interviews: Interview[] = [
{
title: "Erika Musterfrau",
description: "Benötigen wir mehr Sicherheit auf Düsseldorfs Straßen?",
text: "Hier könnte ein kurzer Einleitungstext stehen, der erklärt, worum es geht und Lust macht, sich das Interview anzuhören.",
imgSrc: "/interview_assets/kapitel1_testimonial-1.png",
audioSrc: "/interview_assets/dummy_sound.mp3",
isOpen: true
},
{
title: "Vorname Testname",
description: "Thema, Artikeltitel",
text: "Hier könnte ein kurzer Einleitungstext stehen, der erklärt, worum es geht und Lust macht, sich das Interview anzuhören.",
imgSrc: "/interview_assets/kapitel1_testimonial-1.png",
audioSrc: "/interview_assets/dummy_sound.mp3",
isOpen: false
},
{
title: "Vorname Nachname",
description: "Thema, Artikeltitel",
text: "Hier könnte ein kurzer Einleitungstext stehen, der erklärt, worum es geht und Lust macht, sich das Interview anzuhören.",
imgSrc: "/interview_assets/kapitel1_testimonial-1.png",
audioSrc: "/interview_assets/dummy_sound.mp3",
isOpen: false
}
];
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 86 additions & 0 deletions src/components/audio-player/range.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
body, html { width: 100%; }
.range{
--bar-bg: #FFFFFF;
--seek-before-width: 0;
--thumb: #E78182;

appearance: none;
background: var(--bar-bg);
border-radius: 6px;
position: relative;
width: 100%;
height: 6px;
outline: none;
}

/* range: safari */
.range::-webkit-slider-runnable-track {
background: var(--bar-bg);
border-radius: 6px;
position: relative;
width: 100%;
height: 6px;
outline: none;
}

/* range: firefox */
.range::-moz-range-track {
background: var(--bar-bg);
border-radius: 6px;
position: relative;
width: 100%;
height: 6px;
outline: none;
}
.range::-moz-focus-outer {
border: 0;
}

/* range progress: chrome & safari */
.range::before {
content: '';
height: 6px;
display: block;
width: var(--seek-before-width);
background-color : var(--thumb);
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
top: 0;
left: 0;
z-index: 2;
cursor: pointer;
}
/* range progress: firefox */
.range::-moz-range-progress {
background: var(--thumb);
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
height: 6px;
}

/* thumb: chrome & safari */
.range::-webkit-slider-thumb {
-webkit-appearance: none;
height: 16px;
width: 16px;
border-radius: 50%;
border: none;
background: transparent;
cursor: pointer;
position: relative;
margin: -5px 0 0 0;
z-index: 3;
box-sizing: border-box;
}
/* thumb: firefox */
.range::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
border: transparent;
background-color: var(--thumb);
cursor: pointer;
position: relative;
z-index: 3;
box-sizing: border-box;
}
4 changes: 4 additions & 0 deletions src/components/chapter1/start/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { BlackScreen } from "./blackScreen";
import mountainBackground from "./background/background.png";
import fridgeBackground from "./fridge/kapitel1_fridge_background.png";
import { useIntersection } from "use-intersection";
import { Newspaper } from "./newspaper";

export const Start: React.FC = () => {
const mountainScene = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -40,6 +41,9 @@ export const Start: React.FC = () => {
<Fridge />
</div>
</div>
<div id="newspaper">
<Newspaper />
</div>
</div>
);
}
Expand Down
Loading