LoginSignup
10
12

More than 3 years have passed since last update.

Moveableを使って、要素を移動したりサイズ変更したりする。

Posted at

概要

Officeのオートシェイプみたいな感じで、html要素をマウスでポチポチっと移動したり、
サイズ変更したいなぁって時ありますよね?

Moveableを使って、やってみようと思います。
今回は、React用のreact-moveableを使います。

環境構築

yarnでポチポチ作っていきましょう。

yarn create react-app sample-react-moveable
cd sample-react-moveable
yarn add react-moveable

実装

公式サイトのサンプルを見ると、targetdocument.querySelector()で直接指定していますが、
これだと動かないので、useStateuseEffectを使ってstateから指定してやります。

とりあえず、src/App.jsを弄っていきます。
また、src/App.cssに表示するオブジェクト用のクラスを追加しておきます。

.moveable {
  width: 200px;
  line-height: 150px;
  text-align: center;
  margin: 50px;
  display: inline-block;
  position: absolute;
}

draggable(ドラッグで移動できる)

import React, { useState, useEffect } from 'react';
import Moveable from 'react-moveable';
import './App.css';

const App = () => {
  const [target, setTarget] = useState(null);

  useEffect(() => {
    setTarget(document.querySelector('.draggable'));
  }, []);

  return (
    <React.Fragment>
      <div className={'moveable draggable'}>draggable</div>
      <Moveable
        target={target}
        draggable={true}
        origin={false}
        throttleDrag={0}
        onDrag={e => {
          e.target.style.transform = e.transform;
        }}
      />
    </React.Fragment>
  );
};

export default App;

GIF.gif

resizable(ドラッグでサイズ変更できる)

import React, { useState, useEffect } from 'react';
import Moveable from 'react-moveable';
import './App.css';

const App = () => {
  const [target, setTarget] = useState(null);

  useEffect(() => {
    setTarget(document.querySelector('.resizable'));
  }, []);

  return (
    <React.Fragment>
      <div className={'moveable resizable'}>resizable</div>
      <Moveable
        target={target}
        resizable={true}
        origin={false}
        throttleResize={0}
        keepRatio={true}
        onResize={e => {
          e.target.style.width = `${e.width}px`;
          e.target.style.height = `${e.height}px`;
        }}
      />
    </React.Fragment>
  );
};

export default App;

GIF.gif

scalable(ドラッグでスケール変更できる)

import React, { useState, useEffect } from 'react';
import Moveable from 'react-moveable';
import './App.css';

const App = () => {
  const [target, setTarget] = useState(null);

  useEffect(() => {
    setTarget(document.querySelector('.scalable'));
  }, []);

  return (
    <React.Fragment>
      <div className={'moveable scalable'}>scalable</div>
      <Moveable
        target={target}
        scalable={true}
        origin={false}
        throttleScale={0}
        keepRatio={true}
        onScale={e => {
          e.target.style.transform = e.transform;
        }}
      />
    </React.Fragment>
  );
};

export default App;

GIF.gif

rotatable(ドラッグで回転できる)

import React, { useState, useEffect } from 'react';
import Moveable from 'react-moveable';
import './App.css';

const App = () => {
  const [target, setTarget] = useState(null);

  useEffect(() => {
    setTarget(document.querySelector('.rotatable'));
  }, []);

  return (
    <React.Fragment>
      <div className={'moveable rotatable'}>rotatable</div>
      <Moveable
        target={target}
        rotatable={true}
        origin={false}
        throttleRotate={0}
        onRotate={e => {
          e.target.style.transform = e.transform;
        }}
      />
    </React.Fragment>
  );
};

export default App;

GIF.gif

warpable(ドラッグで歪ませる)

import React, { useState, useEffect } from 'react';
import Moveable from 'react-moveable';
import './App.css';

const App = () => {
  const [target, setTarget] = useState(null);

  useEffect(() => {
    setTarget(document.querySelector('.warpable'));
  }, []);

  return (
    <React.Fragment>
      <div className={'moveable warpable'}>warpable</div>
      <Moveable
        target={target}
        warpable={true}
        origin={false}
        throttleRotate={0}
        onWarp={e => {
          e.target.style.transform = e.transform;
        }}
      />
    </React.Fragment>
  );
};

export default App;

GIF.gif

組み合わせる(draggable & scalable & rotatable)

import React, { useState, useEffect } from 'react';
import Moveable from 'react-moveable';
import './App.css';

const App = () => {
  const [target, setTarget] = useState(null);

  useEffect(() => {
    setTarget(document.querySelector('.mix'));
  }, []);

  return (
    <React.Fragment>
      <div className={'moveable mix'}>mix</div>
      <Moveable
        target={target}
        draggable={true}
        scalable={true}
        rotatable={true}
        origin={false}
        throttleRotate={0}
        onDrag={e => {
          e.target.style.transform = e.transform;
        }}
        onScale={e => {
          e.target.style.transform = e.transform;
        }}
        onRotate={e => {
          e.target.style.transform = e.transform;
        }}
      />
    </React.Fragment>
  );
};

export default App;

GIF.gif

まとめ

それっぽい動きはできた。
モバイルのピンチインにも対応してるみたいですが、未確認です。

10
12
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
10
12