Skip to content

Instantly share code, notes, and snippets.

@zapkub
Created April 21, 2017 07:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zapkub/3328e2d9fe1c9739c3be9580fcdeb006 to your computer and use it in GitHub Desktop.
Save zapkub/3328e2d9fe1c9739c3be9580fcdeb006 to your computer and use it in GitHub Desktop.
// @flow
import React from 'react';
import { Textfit } from 'react-textfit';
import _ from 'lodash';
import { TweenMax, Back, Power4 } from 'gsap';
import type { Song } from '../models';
import styles from './SongList.css';
export class PlayerSongList extends React.Component {
constructor(props) {
super(props);
this.state = {
deg: 0,
};
this.state.shuffleList = props.songList.map(() => _.shuffle(props.fullSongList));
this.toRadius = this.toRadius.bind(this);
this.getApothem = this.getApothem.bind(this);
this.calculateSongStyle = this.calculateSongStyle.bind(this);
this.start = this.start.bind(this);
}
componentDidMount() {
// setTimeout(() => TweenMax.to('#row_0', 2, { rotationX: '180deg' }), 400);
if (this.props.selectedRoundName === 'round1') {
this.start();
}
}
start() {
TweenMax.to(this.refs.row_0, 5, { rotationX: '-=1800deg' });
TweenMax.to(this.refs.row_1, 7, { rotationX: '-=1800deg', ease: Power4.easeOut });
TweenMax.to(this.refs.row_2, 10, { rotationX: '-=1800deg', ease: Back.easeOut.config(1.7) });
}
getApothem() {
return 100 / (2 * Math.tan(this.toRadius(180 / (this.props.fullSongList.length + 1))));
}
toRadius(deg) {
return deg / 180 * Math.PI;
}
calculateSongStyle(index) {
const degPerItem = 360 / (this.props.fullSongList.length + 1);
const deg = degPerItem * index;
const radius = this.getApothem();
return {
transformOrigin: 'center center',
transform: `rotateX(${deg}deg) translateZ(${radius}px)`,
height: 100,
background: 'rgba(0,0,0,0.9)',
position: 'absolute',
width: '100%',
};
}
render() {
const props: {songList: Song[], fullSongList: Song[], selectedSongIndex: number } = this.props;
function calculateStyle(index, selected) {
if (selected) {
return {
height: 100,
};
}
if (index === 2) {
return {
opacity: 0,
transform: 'translateY(-50px)',
};
}
return {
height: 0,
opacity: 0,
};
}
return (
<div className={`${styles.container} ${props.selectedSongIndex > -1 ? styles.active : ''}`}>
{ props.songList.map((item, i) => <div
id={`s${i}`}
style={{
...props.selectedSongIndex > -1 ? calculateStyle(i, props.selectedSongIndex === item.id) : null,
}}
className={`${styles.songItem}`}
key={i}
>
<div
ref={`row_${i}`}
className={styles.song3dwrap} style={{
transform: `translateY(-50%) translateZ(-${this.getApothem()}px) rotateX(${this.state.deg}deg)`,
top: '50%',
}}
>
<Textfit
style={this.calculateSongStyle(0)}
className={styles.songText}
max={48}
mode="single"
>{`${item.name} ${item.artist}`}</Textfit>
{this.state.shuffleList[i].map((song, j) =>
<Textfit
max={48}
className={styles.songText}
style={this.calculateSongStyle(j + 1)}
key={`f${song.id || song.name}`}
>{song.name}</Textfit>)}
</div>
</div>)}
</div>
);
}
}
export default PlayerSongList;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment