LoginSignup
67
56

More than 5 years have passed since last update.

Reactサブセット実装の preact で、ライフゲームのアニメーション書いて使い方を確認した

Posted at

厳密なサブセットかは要確認な気がするが、まあそういうコンセプトのライブラリがある。

で、使ってみた。

preact とは

reactのサブセット実装。reactと比較してかなり小さい(圧縮して3kb)。contextとかpropTypesとかはない。いらないと思う。

reactとの互換をもたせるレイヤーは本体を小さくするために外部パッケージに切り出されている。 https://github.com/developit/preact-compat

コード量が少ないので、迷ったら元のコード読めるという安心感がある。
個人的にReactは過剰な抽象化の迷宮だと思っていて、あんまり読みたくない。

最初に

ライフゲームのアニメーションしたかったわけで、ライフゲームを書きたかったわけではないので、ライフゲームのロジック部分はnpmから適当に持ってきた。

動いてるコードはここ http://mizchi-sandbox.github.io/sketch-board-1/

Reactとの主な違い

babel では /** @jsx h */ というプラグマでReactElementを生成する関数をハック出来る。deku等でも使える。
https://babeljs.io/docs/plugins/transform-react-jsx/

render関数がそのままだとcontainerへのprependなので、rootでStateless Component のpropsを更新し続ける場合(React0.14スタイルと個人的に呼んでる)、render(<Main />, el, el.lastChild); と第三引数を渡さないとDOMを生成し続ける。

コード

そのままだと svg のレンダリングは別パッケージになってるので、そこも引っ張ってくる。

/** @jsx h */
import GameOfLife  from 'game-of-life-logic'
import flatten  from 'lodash.flatten'
import range  from 'lodash.range'
import { h, render } from 'preact'
import SVG  from 'preact-svg'

// Domain
const createBuffer = (x, y, rate = 0.5) =>
  range(y).map(
    _ => range(x).map(
      _ =>
        Math.random() < rate ? 1 : 0));

const createGameOfLife = (x, y, rate = 0.5) => {
  let gol = new GameOfLife(x, y);
  let buf = createBuffer(x, y, rate);
  gol.copyMatrixAt(0, 0, buf);
  return gol;
};

// Component
function GameOfLifeComponent({matrix, size}) {
  return (
    <SVG width="640" height="480">
      {
        flatten(matrix.map((row, y) => row.map((val, x) =>
          <rect
            x={x*size}
            y={y*size}
            width={size}
            height={size}
            style={{fill: val ? "#000" : "#fff"}}
          />
        )))
      }
    </SVG>
  );
}

// Controller
const SIZE_X = 30;
const SIZE_Y = 10;
const INITIAL_ACTIVE_RATE = 0.3;

let gol = createGameOfLife(SIZE_X, SIZE_Y, INITIAL_ACTIVE_RATE);

const startApp = el => {
  (function _update() {
    render(<GameOfLifeComponent matrix={gol.matrix} size={15} />, el, el.lastChild);
    gol.tick();
    setTimeout(_update, 1000)
  })();
}

window.addEventListener("DOMContentLoaded", () => {
  let el = document.querySelector(".main");
  startApp(el);
});

やや手癖で書いた感がある(createBufferあたりがひどい)

https://github.com/mizchi-sandbox/sketch-board-1
http://mizchi-sandbox.github.io/sketch-board-1/

感想

マイナー故の動作確認の辛さはあるが、サイズが小さいのは魅力的なので、仮想DOM欲しいが、Reactでけーよって人いたら検討に値する。

67
56
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
56