Files
EMI-ExpoAPP/Views/SongPlayer.js
T
2023-07-07 09:24:01 -04:00

185 lines
5.6 KiB
JavaScript

import React from 'react';
import { StyleSheet, TouchableHighlight, Text, Animated, View } from 'react-native';
let songExample = {
lyrics: [
'Our [C ..]God is an awe[G ..]some God',
'He rei[D ..]gns from [Em ..]heaven above',
'With wis[C ..]dom, pow[G .]er and lo[Em .]ve',
'Our [Am .]God is an aweso[D .]me [Em ..]God!'
],
title: 'Our God',
key: 'C',
tempo: 60,
beatsPerTempo: 4,
};
let SongPlayer = (props) => {
[song, setSong] = React.useState(songExample);
[currentChord, setCurrentCord] = React.useState(0);
[currentBeat, setCurrentBeat] = React.useState(0);
[currentBeatGlobal, setCurrentBeatGlobal] = React.useState(0);
const fadeAnim = React.useRef(new Animated.Value(1)).current;
let lyrics = song.lyrics;
let chords = [];
const replaceTextInBrackets = (str) => {
const regex = /(\[(.*?)\])/g;
const matches = str.match(regex);
if (!matches) {
return str;
}
let p = str.split(/(\[.*?\])/g).map((item, index) => {
//console.log(item, index)
if (item.match(/\[|\]/g)) {
const dots = item.match(/\./g);
const beats = dots ? dots.length : 0
const content = item.replace(/\[|\]|\./g, '');
chords.push([content, beats]);
const key = chords.length - 1;
return <View style={styles.chordView} key={"chord_" + key}>
<Text style={currentChord !== key ? styles.chord : styles.currentChord}>
{content}
</Text>
</View>;
}
return item;
});
return (
<View>
<Text style={styles.line}>
{p}
</Text>
</View>
)
};
const processedString = lyrics.map(replaceTextInBrackets);
//console.log(processedString, chords);
React.useEffect(() => {
let timer = setInterval(() => {
fadeIn();
beatsInChord = chords[currentChord][1];
//console.log(chords[currentChord])
if (currentBeat >= beatsInChord - 1) {
setCurrentCord((currentChord + 1) % chords.length);
setCurrentBeat(0);
} else {
setCurrentBeat(currentBeat + 1);
}
setCurrentBeatGlobal(currentBeatGlobal + 1);
//fadeOut();
setTimeout(fadeOut, 50);
}, (60 / song.tempo) * 1000);
return () => {
clearInterval(timer);
}
});
const fadeIn = () => {
// Will change fadeAnim value to 1 in 5 seconds
Animated.timing(fadeAnim, {
toValue: 1,
duration: 50,
useNativeDriver: true,
}).start();
};
const fadeOut = () => {
// Will change fadeAnim value to 0 in 3 seconds
Animated.timing(fadeAnim, {
toValue: 0.9,
duration: 270,
useNativeDriver: true,
}).start();
};
return (
<View style={styles.view}>
<Text style={{
fontSize: 20,
position: "absolute",
padding: 20
}}>
Beat: {(currentBeatGlobal) % 4 + 1}
</Text>
<View style={{
height: 100,
}}>
{
currentChord > 0 ?
<View style={{
transform: [{ translateX: 40 }, { translateY: 20 }],
position: "absolute",
width: 60,
height: 20,
}}><Text style={{
fontSize: 20,
opacity: 0.6
}}>
{chords[currentChord - 1][0]} {".".repeat(chords[currentChord - 1][1])}
</Text></View> : <></>
}
<Animated.Text style={{
fontSize: 50,
textAlign: "center",
//opacity: fadeAnim,
transform: [{ scale: fadeAnim }],
}}>
{chords[currentChord][0]} {".".repeat(chords[currentChord][1])}
{
chords[currentChord + 1] ?
<View style={{
transform: [{ translateX: 50 }, { translateY: -35 }],
position: "absolute",
width: 40,
height: 20,
}}><Text style={{
fontSize: 20,
opacity: 0.6
}}>
{chords[currentChord + 1][0]}
</Text></View> : <></>
}
</Animated.Text>
</View>
{processedString}
</View>
)
};
const styles = StyleSheet.create({
chordView: {
position: 'absolute',
},
chord: {
opacity: 0.5,
color: "red",
position: "absolute",
top: -35
},
currentChord: {
opacity: 0.5,
color: "green",
position: "absolute",
top: -40,
transform: [{ scale: 1.5 }]
},
view: {
padding: 15,
paddingTop: 40,
},
line: {
height: 60,
fontSize: 20,
textAlign: "center"
},
chordViewer: {
}
});
export default SongPlayer;