Advertisement
Guest User

Sierpinski.html

a guest
Jul 15th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 6.41 KB | None | 0 0
  1. <head>
  2.     <meta charset="utf-8">
  3.     <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
  4.     <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
  5.     <script src="https://cdn.jsdelivr.net/npm/ramda@0.25.0/dist/ramda.min.js"></script>
  6.  
  7.     <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  8.     <link rel="stylesheet" href="https://unpkg.com/tachyons@4.10.0/css/tachyons.min.css" />
  9.  
  10.     <style>
  11.         html,
  12.         body {
  13.             font-family: sans-serif;
  14.         }
  15.     </style>
  16. </head>
  17.  
  18. <div class="f5 normal ma3 black-60 absolute z-max top-0">
  19.     <a href="../">..</a> /
  20.     <h1 class="f5 normal di">Sierpiński triangle</h1>
  21. </div>
  22. <div id="app" class="flex justify-center ma4"></div>
  23.  
  24.  
  25. <script type="text/babel">
  26.  
  27. const triangle_area = (x1, y1, x2, y2, x3, y3) =>
  28.     0.5 * ( x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2) )
  29.  
  30. const avg = (a, b) => (a + b) / 2
  31.  
  32.  
  33. class Triangle extends React.Component {
  34.     constructor(props) {
  35.         super(props)
  36.         for (const [k, v] of Object.entries(props)) {
  37.             this[k] = v
  38.         }
  39.     }
  40.     shouldComponentUpdate() {
  41.         return false
  42.     }
  43.     render() {
  44.         const { x1, y1, x2, y2, x3, y3, min_area} = this
  45.  
  46.         // return <polygon
  47.        //         key={`polygon-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  48.        //         points={`${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  49.        //         fill="black"
  50.        //         stroke="green"
  51.        //         />
  52.  
  53.         if (triangle_area(x1, y1, x2, y2, x3, y3) < min_area) {
  54.            return <polygon
  55.                key={`polygon-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  56.                points={`${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  57.                fill="black" />
  58.         } else {
  59.             return [
  60.                 <polygon
  61.                    fill="none"
  62.                    key={`polygon-${x1},${y1} ${x2},${y2} ${x3},${y3}`} points={`${x1},${y1} ${x2},${y2} ${x3},${y3}`} />,
  63.                    
  64.                 <Triangle
  65.                    key={`Triangle1-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  66.                    x1={x1}          y1={y1}
  67.                    x2={avg(x1, x2)} y2={avg(y1, y2)}
  68.                    x3={avg(x1, x3)} y3={avg(y1, y3)}
  69.                    min_area={min_area} />,
  70.                 <Triangle
  71.                    key={`Triangle2-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  72.                    x1={avg(x1, x2)} y1={avg(y1, y2)}
  73.                    x2={x2}          y2={y2}
  74.                    x3={avg(x2, x3)} y3={avg(y2, y3)}
  75.                    min_area={min_area} />,
  76.                 <Triangle
  77.                    key={`Triangle3-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
  78.                    x1={avg(x1, x3)} y1={avg(y1, y3)}
  79.                    x2={avg(x2, x3)} y2={avg(y2, y3)}
  80.                    x3={x3}          y3={y3}
  81.                    min_area={min_area} />,
  82.             ]
  83.         }
  84.     }
  85. }
  86.  
  87. class App extends React.Component {
  88.     width = 400
  89.  
  90.     constructor() {
  91.         super()
  92.         this.state = {
  93.             t: 0,
  94.             bodies: []
  95.         }
  96.         this.handleClick = this.handleClick.bind(this)
  97.     }
  98.  
  99.     update(time_ms) {
  100.  
  101.         this.setState(state => {
  102.             const time = time_ms / 1000
  103.             const dt = time - this.state.t
  104.            
  105.             if (dt <= 0) {
  106.                return
  107.            }
  108.  
  109.            const newState = {
  110.                t: time,
  111.                bodies: [],
  112.            }
  113.  
  114.            for (const b of state.bodies) {
  115.                if (!(b.centerx + b.r >= 0
  116.                     && b.centerx - b.r <= 100
  117.                    && b.centery + b.r >= 0
  118.                    && b.centery - b.r <= 100
  119.                    && b.r > 0)) {
  120.                    
  121.                    continue
  122.                }
  123.                
  124.                newState.bodies.push({
  125.                    ...b,
  126.                    centerx : b.centerx + dt * b.centerx_v,
  127.                    centery : b.centery + dt * b.centery_v,
  128.                    rot     : b.rot     + dt * b.rot_v,
  129.                    r       : b.r       + dt * b.r_v,
  130.                })
  131.            }
  132.  
  133.            return newState
  134.        })
  135.  
  136.        this.loop()
  137.    }
  138.    loop() {
  139.        window.requestAnimationFrame(this.update.bind(this))
  140.    }
  141.    componentDidMount() {
  142.        this.loop()
  143.    }  
  144.    handleClick(e) {
  145.        const new_body = {
  146.            r_i: 30*Math.random() + 12,
  147.            centerx: (e.clientX - e.target.getBoundingClientRect().x) / this.width * 100,
  148.            centery: (e.clientY - e.target.getBoundingClientRect().y)  / this.width * 100,
  149.            rot_i: Math.random() * 2 * Math.PI,
  150.  
  151.            r_v: -(Math.random() * 10 + 5),
  152.            centerx_v: (Math.random() - 0.5) * 16,
  153.            centery_v: (Math.random() - 0.5) * 16,
  154.            rot_v: (Math.random() - 0.5) * 20 * Math.PI,
  155.  
  156.            key: Math.random().toString(),
  157.            keyName: Math.random().toString(),
  158.        }
  159.        new_body.r = new_body.r_i
  160.        new_body.rot = new_body.rot_i
  161.        
  162.        this.setState(s =>
  163.            R.over(
  164.                R.lensProp('bodies'),
  165.                R.append(new_body),
  166.                s)
  167.        )
  168.    }
  169.  
  170.    render() {      
  171.        return (
  172.            <svg viewBox="0 0 100 100" width={this.width} className="ba" onClick={this.handleClick}>
  173.                {this.state.bodies.map(b => {
  174.                    const {r_i, rot_i} = b
  175.            
  176.                    return <g
  177.                        transform={
  178.                            `rotate(${b.rot-b.rot_i},${b.centerx},${b.centery})
  179.                            translate(${b.centerx},${b.centery})
  180.                            scale(${b.r / b.r_i})`}
  181.                        key={`Body-${b.keyName}`}>
  182.                        
  183.                        <Triangle
  184.                            x1={r_i*Math.cos(rot_i)}               y1={r_i*Math.sin(rot_i)}
  185.                            x2={r_i*Math.cos(rot_i + 2/3*Math.PI)} y2={r_i*Math.sin(rot_i + 2/3*Math.PI)}
  186.                            x3={r_i*Math.cos(rot_i + 4/3*Math.PI)} y3={r_i*Math.sin(rot_i+ 4/3*Math.PI)}
  187.                            min_area={1}/>
  188.                    </g>
  189.                    })}
  190.            </svg>
  191.        )
  192.    }
  193. }
  194.    
  195. ReactDOM.render(<App/>, document.getElementById('app'))
  196.  
  197. </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement