概要
Officeのオートシェイプみたいな感じで、html要素をマウスでポチポチっと移動したり、
サイズ変更したいなぁって時ありますよね?
Moveableを使って、やってみようと思います。
今回は、React用のreact-moveable
を使います。
環境構築
yarnでポチポチ作っていきましょう。
yarn create react-app sample-react-moveable
cd sample-react-moveable
yarn add react-moveable
実装
公式サイトのサンプルを見ると、target
をdocument.querySelector()
で直接指定していますが、
これだと動かないので、useState
とuseEffect
を使って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;
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;
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;
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;
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;
組み合わせる(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;
まとめ
それっぽい動きはできた。
モバイルのピンチインにも対応してるみたいですが、未確認です。