読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

React + TypeScript JSXでInteractを使う

先日見つけたInteractというライブラリを使って簡単なサンプルを作ってみました。

github.com

f:id:okazuki:20160108131128p:plain

灰色の場所をクリックすると矩形が追加されます。矩形はドラッグで移動させることと、端っこをつまむことでリサイズが可能です。

f:id:okazuki:20160108131334p:plain

ポイント

interactは、npmではinteract.jsという名前で配布されてます。tsdでとってきた型定義ではinteractという名前でexportされてるので、TypeScriptのコンパイルは通ってもJavaScriptをbrowserifyでコンパイルするときにこけてしまうので、TypeScriptの型定義ファイルの最後のほうにある部分を以下のように書き換える必要があります。

declare module "interact.js" {
    export = interact;
}

続けてReactとInteractの繋ぎの部分です。これはReactのComponentのcomponentDidMountでInteractのAPIを呼び出すことで実現します。以下のような感じです。

componentDidMount() {
    Interact(ReactDOM.findDOMNode(this) as HTMLElement)
        .draggable({
            inertia: true,
            restrict: {
                restriction: 'parent',
                endOnly: true,
                elementRect: { top: 1, left: 1, bottom: 1, right: 1 }
            },
            autoScroll: true,
            onmove: e => {
                CanvasActionCreators.move(
                    this.props.rectangle.id,
                    e.dx,
                    e.dy);
            }
        })
        .resizable({
            preserveAspectRatio: false,
            edges: { left: true, right: true, bottom: true, top: true },
            onmove: e => {
                CanvasActionCreators.resize(
                    this.props.rectangle.id,
                    e.deltaRect.left,
                    e.deltaRect.top,
                    e.rect.width,
                    e.rect.height);
            }
        });
}

ReactDOMのfindDOMNodeでDOMをとってきて、Interactに食わせています。そのあとに続く処理の内容はInteractのページにあるサンプルを、ほぼそのまま書いています。

interactjs.io

一応Fluxにのっとって書いてるのでComponentからActionCreatorsにいって、そこからDispatcherを経由してStoreが変更されて最終的にViewのレンダリングという流れになっています。ReactとInteractを組み合わせることで、非常に簡単に矩形のドラッグとリサイズに対応できました。しかもデータはクラスとして保存されてる状態なので、あとでAjaxとかでサーバーに送信するときも簡単にできていい感じです。