์ผ!
์ฐ๋ฆฌ๋ ์ด๋ค ์์ ์์ translate3d CSS ์คํ์ผ์ ํฌํจํ๋ ์์๋ฅผ ๋๋๊ทธ ๊ฐ๋ฅํ๊ฒ ๋ง๋ค๋ ค๊ณ ํฉ๋๋ค. ๋ถํํ๋ ์ด๊ฒ์ ์ ์ฒด ๋๋๊ทธ ๋ ์ด์ด์ ์์น๋ฅผ โโ๋ณ๊ฒฝํฉ๋๋ค. ๋๋ translate3d๊ฐ ๋ฃจํธ ์์๊ฐ ์๋๋ผ ์์ ๋ ธ๋์ ์๊ธฐ ๋๋ฌธ์ ๊ทธ ์ด์ ๋ฅผ ์ ๋ง๋ก ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๋๋ ๋น์ ์๊ฒ ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋งค์ฐ ๊ฐ๋จํ ์๋ฅผ ๋ชจ์์ต๋๋ค. (์๋ํ๋ ค๋ฉด ReactDnD๋ฅผ ํธ์คํ ํ๋ CDN์ ์ฐพ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ "./scripts/react-dnd-1.1.4/dist"ํด๋์ ReactDnD.min.js๋ฅผ ๋ฐฐ์นํด์ผํฉ๋๋ค).
๋์ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DragPreview with wrong position example</title>
<script src="http://fb.me/react-with-addons-0.13.3.js"></script>
<script src="http://fb.me/JSXTransformer-0.13.3.js"></script>
<script src="scripts/react-dnd-1.1.4/dist/ReactDnD.min.js"></script>
<style>
.ReactDnDElement {
background: red;
overflow: hidden;
width: 200px;
height: 100px;
}
.ReactDnDElement .wrapper {
display: flex;
align-items: center;
width: 600px;
height: 100%;
transform: translate3d(-275px, 0, 0);
}
.ReactDnDElement .wrapper div {
width: 150px;
height: 50%;
}
.ReactDnDElement .wrapper div.green { background: green; }
.ReactDnDElement .wrapper div.blue { background: blue; }
.ReactDnDElement .wrapper div.yellow { background: yellow; }
.ReactDnDElement .wrapper div.magenta { background: magenta; }
</style>
</head>
<body>
<script type="text/jsx">
/* ReactDnDApp */
var ReactDnDApp = React.createClass({
render: function() {
return (
<ReactDnDElement></ReactDnDElement>
);
}
});
ReactDnDApp = ReactDnD.DragDropContext(ReactDnD.HTML5)(ReactDnDApp)
/* ReactDnDElement */
var ReactDnDElement = React.createClass({
render: function() {
return this.props.connectDragSource(
this.props.connectDragPreview(
<div className="ReactDnDElement">
<div className="wrapper">
<div className="green"></div>
<div className="blue"></div>
<div className="yellow"></div>
<div className="magenta"></div>
</div>
</div>
)
);
}
});
ReactDnDElement = ReactDnD.DragSource("dndElement", {
beginDrag: function(props) {
return {};
}
}, function(connect, monitor) {
return {
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview()
};
})(ReactDnDElement);
/* RUN IT! */
React.render(React.createElement(ReactDnDApp), document.body);
</script>
</body>
</html>
๊ธฐ๋ณธ html5 ๋๋๊ทธ ์ค ๋๋กญ ๊ธฐ๋ฅ์๋ ๋ฌธ์ ๊ฐ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ธฐ๋ณธ html5 ๋๋๊ทธ ์ค ๋๋กญ ๋ฐฉ๋ฒ์ผ๋ก ๋์ผํ๊ฒ ์๋ํ๋ฉด firefox ๋ฐ safari์์๋ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง๋ง Chrome ๋ฐ Opera์์๋ ์๋ํ์ง ์์ต๋๋ค.
react-dnd๋ฅผ ์ฌ์ฉํ๋ฉด์ด ๋ฌธ์ ๋ ์ฌํ๋ฆฌ์ ์กด์ฌํ์ง ์์ง๋ง ํฌ๋กฌ, ์คํ๋ผ ๋ฐ FIREFOX์์๋ ์กด์ฌํฉ๋๋ค.
ํฌ๋กฌ์ ๋ํ ๋ฌธ์ ๋ฅผ ์ด์์ต๋๋ค : https://code.google.com/p/chromium/issues/detail?id=525604
์ด ๋ฒ๊ทธ๋ฅผ ์์ ํ๋ ค๋ ์๋๊ฐ ์์ต๋๊น?
๋ถ์พํ ๊ฒ๋ค. ๋๋ ์ด๊ฒ์ ๋จ์ง ๋ ์๊ฐ์ ๋ณด๋๊ณ ๊ทธ๊ฒ์ ์๋์ํค๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅธ๋ค.
์ด๊ฒ์ ๋์ฐํ ๋ธ๋ผ์ฐ์ ๋ถ์ผ์น ์ค ํ๋ ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๊ฐ์ x
๋ฐ y
์ ์ ๋ฌ ๋ ๊ฐ dataTransfer.setDragImage
๋ธ๋ผ์ฐ์ ์ ์ํด ํด์๋์ด ๋ค๋ฅธ ๋ ๋ถ๋ชจ ์คํ์
๋ถ์ ์ ์ผ๋ก ์์น์ ์ํธ ์์ฉํ๋ ์์์ ์์. ๋ณํ์ ์์๋ก ๋ณ๊ฒฝํ๋ฉด ๋ง์ ์ฒ๋ผ ์๋ํฉ๋๋ค.
Firefox์ ์ผ๋ถ ๊ธฐ๋ณธ HTML5 ๋๋๊ทธ ์ค ๋๋กญ ์์ ์์์ด ๋ฌธ์ ๊ฐ ํ์๋์ง ์๋ ์ด์ ๋ x
๋ฐ y
์ง์ ํ์ง ์์๊ณ ๊ธฐ๋ณธ๊ฐ์ด "์๋ โ. ๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ฌ๋ฐ๋ฅธ ์์น์ ๋ํ๋๋ ๋๋๊ทธ ๋ ํญ๋ชฉ์ ๋ํด ์ง์ ํด์ผํฉ๋๋ค _.
์ฌ๊ธฐ์ ๊ฐ๋ฅํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์๋์ง ์์ฌ๋ฉ๋๋ค. ๋๋๊ทธ ์์ค ๋
ธ๋์ ๊น์ด ์ค์ฒฉ ๋ ์์์ด ์ผ์ชฝ ๋๋ ์์ชฝ ๊ฐ์ฅ์๋ฆฌ ๊ฒฝ๊ณ๋ฅผ ๋ฒ์ด๋๋ฉด setDragImage(node, x, y)
๊ฐ ์ผ๋ถ ๋ธ๋ผ์ฐ์ ์์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง ์์ต๋๋ค. ๋ค์ ๋งํ์ง๋ง, ์ผ๋ถ ๋ธ๋ผ์ฐ์ ์์ ์์ ํ๋ ค๊ณ ํ๋๋ผ๋ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ์์๋ ํ์คํ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ผ๋ฏ๋ก ์์ ์ ์ผ๋ก ์์ ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ซ์ต๋๋ค. ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐพ์ผ์ญ์์ค. ์ง๊ธ์ ๋๋๊ทธ ์์ค ๋ด๋ถ์์ ๋ถ์ ์ ์ธ ๋ณํ์ ํผํ๋ ๊ฒ์ด ์ข์ต๋๋ค. connectDragSource
_inside_ ๋ณํ ๋ ๋ํผ๋ฅผ ์ด๋ํ ์ ์์ต๋๋ค.
.ReactDnDElement {
background: red;
overflow: hidden;
width: 200px;
height: 100px;
}
.ReactDnDElement .transform {
transform: translate3d(-275px, 0, 0);
width: 100%;
height: 100%;
}
.ReactDnDElement .wrapper {
display: flex;
align-items: center;
width: 600px;
height: 100%;
}
.ReactDnDElement .wrapper div {
width: 150px;
height: 50%;
}
.ReactDnDElement .wrapper div.green { background: green; }
.ReactDnDElement .wrapper div.blue { background: blue; }
.ReactDnDElement .wrapper div.yellow { background: yellow; }
.ReactDnDElement .wrapper div.magenta { background: magenta; }
var ReactDnDElement = React.createClass({
render: function() {
return (
<div className="ReactDnDElement">
<div className="transform">
{this.props.connectDragSource(
<div className="wrapper">
<div className="green"></div>
<div className="blue"></div>
<div className="yellow"></div>
<div className="magenta"></div>
</div>
)}
</div>
</div>
);
}
});
๊ทธ๋ฌ๋ ์ด๋ ๊ฒํ๋ฉด ํ์ ๋ถ๋ถ ๋ง ๋๋๊ทธ ์ด๋ฏธ์ง๋ก ์ฌ์ฉ๋๋ฉฐ ์ํ๋์ง ์ฌ๋ถ๋ ํ์คํ์ง ์์ต๋๋ค.
๋ถํํ๋ ์ด๊ฒ์ด ์ ๊ฐ ์ ์ ํ ์์๋ ์ต์ ์ ๋ฐฉ๋ฒ์
๋๋ค. ์ด๊ฒ์ด ํฐ ๋ฌธ์ ๋ผ๋ฉด HTML5 ๋์ ๋์ฒด React DnD ๋ฐฑ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์๋ฅผ ๋ค์ด # 70๊ณผ ๊ฐ์ ๋ง์ฐ์ค ๋ฐฑ์๋๋ setDragImage
์ ์์กดํ์ง ์๊ธฐ ๋๋ฌธ์์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค. setDragImage
์ ์์กดํ์ง ์๋ ๋ง์ถค ๋๋๊ทธ ๋ ์ด์ด ๋ฅผ ์ฌ์ฉ
์ผ! ์ด๊ฑธ ๋ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋ค, ์ ๋ง ๋ถ์พํ ๊ฒ! ๋ธ๋ผ์ฐ์ ๋ด๋น์๊ฐ ๊ณง์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๋ธ๋ผ์ฐ์ ๋ด๋น์๊ฐ ๊ณง์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. HTML5 ๋๋๊ทธ ์ค ๋๋กญ์ IE5 ๋์์ ๊ธฐ๋ฐ์ผ๋ก ํ์คํ๋์์ผ๋ฉฐ ์ค๋ซ๋์ ๊นจ์ง๊ณ ์ผ๊ด์ฑ์ด ์์ต๋๋ค. ์น์ด ๋ ๋ณต์ก ํด์ง์ ๋ฐ๋ผ ๋ ๋์์ง์ง ์๊ณ ๋ ๋๋น ์ง ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ง์ถคํ ๋ง์ฐ์ค ๋ฐ ํฐ์น ์ฒ๋ฆฌ๊ฐ ๋ ๋์ ์๋ฃจ์ ์ด๋ฉฐ ๊ทธ๋ฌํ React DnD ๋ฐฑ์๋๊ฐ ๊ฒ์๋๊ธฐ๋ฅผ ๊ธฐ๋ํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. HTML5 ๋๋๊ทธ ์ค ๋๋กญ์ IE5 ๋์์ ๊ธฐ๋ฐ์ผ๋ก ํ์คํ๋์์ผ๋ฉฐ ์ค๋ซ๋์ ๊นจ์ง๊ณ ์ผ๊ด์ฑ์ด ์์ต๋๋ค. ์น์ด ๋ ๋ณต์ก ํด์ง์ ๋ฐ๋ผ ๋ ๋์์ง์ง ์๊ณ ๋ ๋๋น ์ง ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ง์ถคํ ๋ง์ฐ์ค ๋ฐ ํฐ์น ์ฒ๋ฆฌ๊ฐ ๋ ๋์ ์๋ฃจ์ ์ด๋ฉฐ ๊ทธ๋ฌํ React DnD ๋ฐฑ์๋๊ฐ ๊ฒ์๋๊ธฐ๋ฅผ ๊ธฐ๋ํฉ๋๋ค.