Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <head>
- <meta charset="utf-8">
- <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
- <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
- <script src="https://cdn.jsdelivr.net/npm/ramda@0.25.0/dist/ramda.min.js"></script>
- <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
- <link rel="stylesheet" href="https://unpkg.com/tachyons@4.10.0/css/tachyons.min.css" />
- <style>
- html,
- body {
- font-family: sans-serif;
- }
- </style>
- </head>
- <div class="f5 normal ma3 black-60 absolute z-max top-0">
- <a href="../">..</a> /
- <h1 class="f5 normal di">Sierpiński triangle</h1>
- </div>
- <div id="app" class="flex justify-center ma4"></div>
- <script type="text/babel">
- const triangle_area = (x1, y1, x2, y2, x3, y3) =>
- 0.5 * ( x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2) )
- const avg = (a, b) => (a + b) / 2
- class Triangle extends React.Component {
- constructor(props) {
- super(props)
- for (const [k, v] of Object.entries(props)) {
- this[k] = v
- }
- }
- shouldComponentUpdate() {
- return false
- }
- render() {
- const { x1, y1, x2, y2, x3, y3, min_area} = this
- // return <polygon
- // key={`polygon-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- // points={`${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- // fill="black"
- // stroke="green"
- // />
- if (triangle_area(x1, y1, x2, y2, x3, y3) < min_area) {
- return <polygon
- key={`polygon-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- points={`${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- fill="black" />
- } else {
- return [
- <polygon
- fill="none"
- key={`polygon-${x1},${y1} ${x2},${y2} ${x3},${y3}`} points={`${x1},${y1} ${x2},${y2} ${x3},${y3}`} />,
- <Triangle
- key={`Triangle1-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- x1={x1} y1={y1}
- x2={avg(x1, x2)} y2={avg(y1, y2)}
- x3={avg(x1, x3)} y3={avg(y1, y3)}
- min_area={min_area} />,
- <Triangle
- key={`Triangle2-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- x1={avg(x1, x2)} y1={avg(y1, y2)}
- x2={x2} y2={y2}
- x3={avg(x2, x3)} y3={avg(y2, y3)}
- min_area={min_area} />,
- <Triangle
- key={`Triangle3-${x1},${y1} ${x2},${y2} ${x3},${y3}`}
- x1={avg(x1, x3)} y1={avg(y1, y3)}
- x2={avg(x2, x3)} y2={avg(y2, y3)}
- x3={x3} y3={y3}
- min_area={min_area} />,
- ]
- }
- }
- }
- class App extends React.Component {
- width = 400
- constructor() {
- super()
- this.state = {
- t: 0,
- bodies: []
- }
- this.handleClick = this.handleClick.bind(this)
- }
- update(time_ms) {
- this.setState(state => {
- const time = time_ms / 1000
- const dt = time - this.state.t
- if (dt <= 0) {
- return
- }
- const newState = {
- t: time,
- bodies: [],
- }
- for (const b of state.bodies) {
- if (!(b.centerx + b.r >= 0
- && b.centerx - b.r <= 100
- && b.centery + b.r >= 0
- && b.centery - b.r <= 100
- && b.r > 0)) {
- continue
- }
- newState.bodies.push({
- ...b,
- centerx : b.centerx + dt * b.centerx_v,
- centery : b.centery + dt * b.centery_v,
- rot : b.rot + dt * b.rot_v,
- r : b.r + dt * b.r_v,
- })
- }
- return newState
- })
- this.loop()
- }
- loop() {
- window.requestAnimationFrame(this.update.bind(this))
- }
- componentDidMount() {
- this.loop()
- }
- handleClick(e) {
- const new_body = {
- r_i: 30*Math.random() + 12,
- centerx: (e.clientX - e.target.getBoundingClientRect().x) / this.width * 100,
- centery: (e.clientY - e.target.getBoundingClientRect().y) / this.width * 100,
- rot_i: Math.random() * 2 * Math.PI,
- r_v: -(Math.random() * 10 + 5),
- centerx_v: (Math.random() - 0.5) * 16,
- centery_v: (Math.random() - 0.5) * 16,
- rot_v: (Math.random() - 0.5) * 20 * Math.PI,
- key: Math.random().toString(),
- keyName: Math.random().toString(),
- }
- new_body.r = new_body.r_i
- new_body.rot = new_body.rot_i
- this.setState(s =>
- R.over(
- R.lensProp('bodies'),
- R.append(new_body),
- s)
- )
- }
- render() {
- return (
- <svg viewBox="0 0 100 100" width={this.width} className="ba" onClick={this.handleClick}>
- {this.state.bodies.map(b => {
- const {r_i, rot_i} = b
- return <g
- transform={
- `rotate(${b.rot-b.rot_i},${b.centerx},${b.centery})
- translate(${b.centerx},${b.centery})
- scale(${b.r / b.r_i})`}
- key={`Body-${b.keyName}`}>
- <Triangle
- x1={r_i*Math.cos(rot_i)} y1={r_i*Math.sin(rot_i)}
- x2={r_i*Math.cos(rot_i + 2/3*Math.PI)} y2={r_i*Math.sin(rot_i + 2/3*Math.PI)}
- x3={r_i*Math.cos(rot_i + 4/3*Math.PI)} y3={r_i*Math.sin(rot_i+ 4/3*Math.PI)}
- min_area={1}/>
- </g>
- })}
- </svg>
- )
- }
- }
- ReactDOM.render(<App/>, document.getElementById('app'))
- </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement