WheelOfPorn

The Wheel of Porn from Family Guy (Season 13 Episode 9) programmed in react.
git clone git://git.oshgnacknak.de/WheelOfPorn.git
Log | Files | Refs | README

App.js (4380B)


      1 import React from 'react';
      2 import { PieChart } from 'react-minimal-pie-chart';
      3 import Label from './Label.js';
      4 
      5 class App extends React.Component {
      6     state = {
      7         tags: [],
      8         winner: -1,
      9         index: -1,
     10         theta: 0,
     11         dtheta: 0,
     12     };
     13 
     14     async spin()  {
     15         if (this.state.spinning) {
     16             this.setState({ dtheta: 0 });
     17             return;
     18         }
     19 
     20         const url = document.location.hostname === 'localhost' ? 'http://localhost:5000/spin' : '/spin';
     21         const res = await fetch(url);
     22         this.setState({ 
     23             tags: await res.json(),
     24             spinning: true,
     25             winner: -1,
     26             theta: Math.random() * 360,
     27             dtheta: 30 + Math.random(),
     28         });
     29 
     30         let last = Date.now();
     31         const anim = () => {
     32             const dt = last - Date.now();
     33             this.update(dt);
     34 
     35             if (this.state.dtheta > 0.01) {
     36                 last = Date.now();
     37                 requestAnimationFrame(anim);
     38             } else {
     39                 this.setState({
     40                     spinning: false, 
     41                     winner: this.state.index 
     42                 });
     43             }
     44         }
     45         requestAnimationFrame(anim);
     46     }
     47 
     48     update(dt) {
     49         const index = Math.floor(this.state.tags.length * (360-((this.state.theta+89)%360)) / 360);
     50 
     51         if (index !== this.state.index) { 
     52             new Audio('/click.mp3').play();
     53         }
     54 
     55         this.setState({
     56             index,
     57             theta: this.state.theta + this.state.dtheta,
     58             dtheta: this.state.dtheta * 0.995,
     59         })
     60     }
     61 
     62     winner() {
     63         if (this.state.winner < 0) {
     64             return (
     65                 <div>
     66                     <strong>
     67                         { this.state.spinning 
     68                             ? 'Click the wheel to stop spinning!' 
     69                             : 'Click the wheel to spin!' 
     70                         }
     71                     </strong><br />
     72                     <img className="wop" alt="Time to spin the wheel of porn" src="/wheelofporn.gif" />
     73                 </div>
     74             );
     75         }
     76 
     77         const winner = this.state.tags[this.state.winner];
     78         return (
     79             <div className="winner">
     80                 <h1>Your tag is: {winner.name}</h1>
     81                 <ul>
     82                     { winner.sites.map(site => (
     83                         <li key={site.baseUrl}>
     84                             <a href={site.url}>
     85                                 <img alt="" src={site.icon} />
     86                                 <strong>{site.hostname}</strong>
     87                             </a>
     88                         </li>
     89                     )) }
     90                 </ul>
     91             </div>
     92         )
     93     }
     94 
     95     render() {
     96         const { tags } = this.state;
     97         return (
     98             <div className="app">
     99                 <div className="spinner-container">
    100                     <div
    101                         onClick={ () => this.spin() }
    102                         className="spinner"
    103                         style={{
    104                             transform: `translate(-50%) rotate(${this.state.theta}deg)`,
    105                         }}
    106                     >
    107                         <PieChart
    108                             className="wheel"
    109                             totalValue={tags.length}
    110                             paddingAngle={1}
    111                             labelPosition="95"
    112                             label={
    113                                 props => (
    114                                     <Label key={tags[props.dataIndex].name} {...props}>
    115                                         {tags[props.dataIndex].name.toUpperCase()}
    116                                     </Label>
    117                                 )
    118                             }
    119                             data={
    120                                 tags.map((tag, i) => ({
    121                                     title: `${tag.name}: ${tag.sites.length} sites`,
    122                                     value: 1,
    123                                     color: `hsl(${360 * i*3/tags.length}, 100%, ${i === this.state.index ? 70 : 40}%)`,
    124                                 }))
    125                             }
    126                         />
    127                     </div>
    128                     <div className="arrow"></div>
    129                 </div>
    130                 { this.winner() }
    131             </div>
    132         );
    133     }
    134 }
    135 
    136 export default App;