185 lines
5.6 KiB
JavaScript
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;
|