DropTargetãäœæããgetClientOffsetã次ã®ããã«æ¥ç¶ããŸããã
targetCollect = function (connect, monitor) {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
clientOffset: monitor.getClientOffset()
}
}
ãã ããã³ã³ããŒãã³ãå ã§ãã©ãã°ã移åãããšãã¿ãŒã²ããã¯ããŠã¹ãå°å»ã¿ã«åãããã³ã«æŽæ°ãããå°éå ·ãåãåããŸããïŒEnterãšExitã®å Žåã®ã¿ïŒã ãã ããã¿ãŒã²ããã¹ããã¯ã®ãããŒã¯ç¹°ãè¿ãåŒã³åºãããŸãã clientOffsetãããããå€æŽããããã³ã«æ³šå ¥ãããªãçç±ã¯ãããŸããïŒ
ãããè¯ãç¹ã ããã§ããç§ã¯ãã®äœ¿çšæ³ãäºæããŠããŸããã§ããã çŸåšãã¯ã©ã€ã¢ã³ããªãã»ããã®è¿œè·¡ããªããã€ã³ããå¯äžã®æ¹æ³ã¯ã DragLayer
ã䜿çšããããšã§ãã ãã以å€ã®å Žåãããã©ãŒãã³ã¹äžã®çç±ããã_dropã¿ãŒã²ããèªäœ_ã«é¢ããäœããå€æŽãããå Žåã«ã®ã¿å°éå
·ãæŽæ°ããŸãã
ããã¯APIã®åé¡ã ãšæããŸãããããã€ãã®è§£æ±ºçããããããããŸããã
collect
é¢æ°å
ããgetClientOffset()
ããã³åæ§ã®ã¡ãœããã«å°éããããšãçŠæ¢ãã代ããã«DragLayer
ã䜿çšããããã«æ瀺ããŸãïŒç°¡åã§ããã°ãããŠããŸãïŒãç§ã¯2çªç®ã®ãªãã·ã§ã³ãè¡ãPRãåãå
¥ãããšæããŸãã DragLayer
å®è£
ããã§ãã¯ããŠããªãã»ããã®å€æŽãã©ã®ããã«ãµãã¹ã¯ã©ã€ããããã確èªã§ããŸãã
2çªç®ã®ãªãã·ã§ã³ã調ã¹ãŸããããcollectã¯é¢æ°ã§ãããã泚æãå¿ èŠã§ãããã®ãããã©ã®ã¢ãã¿ãŒé¢æ°ãåŒã³åºãããããèŠã€ããããšã¯äžå¯èœ/ç°¡åã§ã¯ãããŸããã
ç§ã®ãŠãŒã¹ã±ãŒã¹ã¯ãå Žæã«ã¹ãããããããŠã£ãžã§ããããã©ãã°ããŠãä»ã®ãŠã£ãžã§ãããæ¯èŒçè€éãªæ¹æ³ã§ç§»åãããããšã§ãïŒAndroidã§ããã°ã©ã ã¢ã€ã³ã³ããã©ãã°ããããšãèããŠãã ããïŒã æ£ç¢ºãªãããŒäœçœ®ã«å¿ããŠããèªäœãåé 眮ããå¿ èŠãããã®ã¯å®éã«ã¯ã¿ãŒã²ããã§ããããã©ãã°èªäœã¯HTML5ã¹ãããã·ã§ãããšããŠå®å šã«åé¡ãããŸããã ã¿ãŒã²ããã¹ããã¯ã®ãããŒã§ã¿ãŒã²ããã³ã³ããŒãã³ãã®ç¶æ ãæŽæ°ããããšã§ãããè¡ãããšãã§ããŸãã ããã§ãç§ã¯ä»ã®ãšãããããæ®ããŠããããåé¿ããŸãã çŽ æŽãããã©ã€ãã©ãªãããããšãã ç§ã¯éåžžã«æ°æéã®ä»äºã§ãŸãšããªä»äºãããŠããŸãã
ãšãããããããéãããŸãŸã«ããŸãããã ïŒ172ãšåãã§ãã canDrop
ãŸãã¯åéé¢æ°å
ã§ãã«ã¿ã䜿çšãã人ã¯äºæ³ããŠããŸããã§ããã ãããããã«ä¿®æ£ããã€ããã¯ãããŸãããã1ãæããããã§è§£æŸãããåŸãããããŸããã
ç§ããã®åé¡ã«ééããŸããã ã¯ã©ã€ã¢ã³ããDropTargetä»æ§ã«ãã©ã°ãæž¡ããŠããªãã»ããå€æŽããµãã¹ã¯ã©ã€ãã§ããããã«ããããšã«ã€ããŠã©ãæããŸããïŒ ããã¯ãŠãŒã¶ãŒã«ãšã£ãŠãã1ã€ã®ãèœãšãç©Žãã§ããããªãã»ãããæåã§ãµãã¹ã¯ã©ã€ã/ãµãã¹ã¯ã©ã€ã解é€ãããããç°¡åã§ãã
RxJS-DOMã䜿çšããŠãèŠçŽ ã®ãã©ãã°ãªãŒããŒã€ãã³ããç£èŠããããŠã¹åº§æšã§ç¶æ ãæŽæ°ããããšã¯ã§ããŸãããïŒ ããããããããŒãªè§£æ±ºçã
componentDidMount() {
this._events.dragOver = DOM.fromEvent(findDOMNode(this.refs.grid), 'dragover')
.throttle(200)
.subscribe(this.getMouseCoords)
}
çµå±ãã¢ãã¿ãŒãã€ããã§ãDragLayerã®ãããªãªãã»ããå€æŽããµãã¹ã¯ã©ã€ãããŸããã ãŸããå Žæã«ãã£ãŠã¯å éšã¬ãžã¹ããªãå©çšããããšã«ãªããŸããã ç§ãããããããšã¯_ããŸãã«ã_çããããšã§ã¯ãªããšæãã®ã§ãIMOã¯åçŽãªAPIã®å€æŽã§å¯ŸåŠã§ããŸãã
ããããäœããæ¥ãŸãããïŒ ã«ã¹ã¿ã ãã©ãã°ã¬ã€ã€ãŒã§ã¯ãªãDropTargetã§ã¯ã©ã€ã¢ã³ããªãã»ãããç£èŠãããã®ã¯ãã«ã¹ã¿ã ãã©ãã°ã¬ã€ã€ãŒã§ã¯ãªãDropTargetãããããŒäœçœ®ã«ã¢ã¯ã»ã¹ã§ããæ¹ããDropTargetã®æ§é ãå€æŽãããããšæããããã§ãã
+ 1 @ jchristmanãããããšããŠããããšãæ£ç¢ºã«ããããã§ãã
+1ã ããã«ééããgetClientOffsetïŒïŒãcanDropïŒïŒã§æ£åžžã«æ©èœããçç±ãç解ããããšããŠå€ãã®æéãç¡é§ã«ããŠããŸã-ããã¯ç¹°ãè¿ãåŒã³åºãããŸã...-ããããç§ãã¡ãããã¢ã€ãã ã®ãã©ããã§ç§ã®ã³ã³ãããŒã«ã«è»¢éããæ¹æ³ã¯ãããŸããã ããªãŒããŒãã®ãäžãã ãã§ãªããããªãŒããŒãã®äžäžã«æ¿å ¥ã§ããå¿ èŠããããŸãã canDropïŒïŒã«ã¯ãããŒããæã€å€ãã®ãã¿ã€ããã®ããããã®ã©ããã³ã³ããŒãã³ãã«å®éã«äŒããŠãããã«å¿ããŠã³ã³ãããŒã«ãå衚瀺ã§ããããã«ããæ¹æ³ããããŸããã canDropã§å°éå ·ãå€æŽãããšããšã©ãŒãçºçããŸããã onMouseMoveã®ãµãã¹ã¯ã©ã€ãã¯ããã©ãã°ã¢ã³ãããããæäœäžã«ã¯æ©èœããŸããã ããã¯ãããŸã§ã®ãšããæéã®å€§ããªç¡é§ã§ãã...ã©ããªå©ããããã ããã°å¹žãã§ãã
@ibash ãåé¡ã解決ããããã«è¡ã£ãããšã®èŠç¹ãæçš¿ããŠ
ãããŒã®äœ¿çšã«åãæ¿ãããšãã€ãã«ãããã§ããŸããã
`ãããŒ:(å°éå
·ïŒMyPropsãã¢ãã¿ãŒïŒDropTargetMonitorãã³ã³ããŒãã³ãïŒReportItemRowïŒ=> {
ifïŒcomponentïŒ= nullïŒ{
const clientOffset = monitor.getClientOffsetïŒïŒ;
// Is the dragging node dragged above/below us as opposed to "on" us?
const elementRect = document.elementFromPoint(clientOffset.x, clientOffset.y).getBoundingClientRect();
const percentageY = (clientOffset.y - elementRect.top) / elementRect.height;
// Divide the box up into .25 .5 .25
const insertDragAndDropMagnetPercent = .25;
if (insertDragAndDropMagnetPercent >= percentageY) {
component.setState({ dropTarget: "above" });
}
else if (1 - insertDragAndDropMagnetPercent >= percentageY) {
component.setState({ dropTarget: "inside" });
}
else {
component.setState({ dropTarget: "below" });
}
}
},`
@ noah79 ãããªãŒããŒãã®äžã«çœ®ãããšã§åé¡ã解決ã§ããŸãã ãã®ãããªãã®ïŒ
_____
_____| <-- drop div1 (above treenode1/below top of list)
treenode1_____| <-- drop div2 (on treenode1)
_____| <-- drop div3 (below treenode1/above treenode2)
treenode2_____| <-- drop div4 (on treenode 2)
_____| <-- drop div5 (below treenode2/above bottom of list)
æçµçã«2n + 1ã®ããããã¿ãŒã²ããã«ãªããŸããããã§ãnã¯ãªã¹ãå ã®èŠçŽ ã®æ°ã§ãã 次ã«ãã©ã®divã«ã«ãŒãœã«ãåããããã«åºã¥ããŠãããªãŒãªã¹ãã®å€èŠ³ãå€æŽã§ããŸãã ä»ã®ãšããgetClientOffsetïŒïŒã«ã¢ã¯ã»ã¹ã§ããªãããšãåé¿ããããã«ããããšéåžžã«ãã䌌ãåŠçãå®è¡ããŸããããããã©ãŒãã³ã¹ãžã®åœ±é¿ã«ã¯æ°ã¥ããŸããã§ããã åããããdivã®é«ãã¯treenode1ã©ã€ã³ã®é«ãã®1/2ã§ãããæåã®ããããdivã¯æåã®ã©ã€ã³ãããtreenode1ã©ã€ã³ã®é«ãã®1/4é«ãäœçœ®ã«ããå¿ èŠããããŸãã ã€ãŸããCSSã¯æ¬¡ã®ããã«ãªããŸãã
.dropdiv-container {
position: absolute;
top: -0.25em; /* If the top of this container is aligned with the top of the treenode list initially */
}
.dropdiv {
height: 0.5em; /* If the height of treenode1 line is 1em with no padding */
}
<div className='dropdiv-container'>
{ renderDropTargets(2 * listLength + 1) }
</div>
ããã¯çã«ããªã£ãŠããŸããïŒ
ãããç§ããããã©ã®ããã«è§£æ±ºãããã®èŠç¹ã§ãã ç§èš£ã¯ãã æã䌞ã°ãããšã§ã
react-dnd internalsã䜿çšããŠãã°ããŒãã«ã¢ãã¿ãŒãçŽæ¥äœ¿çšããŸãã èŠãŠãã ãã
DragDropMonitor.jsãœãŒã¹ã䜿çšããŠã䜿çšå¯èœãªã¡ãœããã確èªããŠãã ããã
åç
§ïŒ https ïŒ
ããªãã¯ã³ãŒããŒã¹ã¯ãªãããèš±ããªããã°ãªããªãã§ããã:)
# in the component being dragged, get access to the dragDropManager by adding
# it to the contextTypes
#
# dragDropManager is an instance of this:
# https://github.com/gaearon/dnd-core/blob/master/src/DragDropManager.js
<strong i="11">@contextTypes</strong>: {
dragDropManager: React.PropTypes.object
}
# because we can receive events after the component is unmounted, we need to
# keep track of whether the component is mounted manually.
#
# <strong i="12">@_monitor</strong> is what lets us access all the nice internal state - it is an instance of this:
# https://github.com/gaearon/dnd-core/blob/master/src/DragDropMonitor.js
componentWillMount: () =>
<strong i="13">@_isMounted</strong> = true
<strong i="14">@_monitor</strong> = @context.dragDropManager.getMonitor()
<strong i="15">@_unsubscribeToStateChange</strong> = @_monitor.subscribeToStateChange(@_onStateChange)
<strong i="16">@_unsubscribeToOffsetChange</strong> = @_monitor.subscribeToOffsetChange(@_onOffsetChange)
componentWillUnmount: () =>
<strong i="17">@_isMounted</strong> = false
<strong i="18">@_monitor</strong> = null
@_unsubscribeToStateChange()
@_unsubscribeToOffsetChange()
# we can access dragging / dropping state by accessing the monitor
_onStateChange: () =>
return unless <strong i="19">@_isMounted</strong>
# When we stop dragging reset the counter state and hide all cursors.
if <strong i="20">@_previousIsDragging</strong> && !@_monitor.isDragging()
console.log('no longer dragging')
<strong i="21">@_previousIsDragging</strong> = @_monitor.isDragging()
_onOffsetChange: () =>
return unless <strong i="22">@_isMounted</strong>
# mouse is the x/y coordinates
mouse = @_monitor.getClientOffset()
# item is the drag item
item = @_monitor.getItem()
# if you want to check if a dragged item is over a target, you need the
# targetId -- in the DropTarget wrapper you can pass it in like:
#
# (connect, monitor) ->
# {
# targetId: monitor.targetId,
# connectDropTarget: connect.dropTarget()
# }
#
# and then you can use it like below
@_monitor.isOverTarget(@props.targetId))
ããã¯æå³ããããŸããïŒ ããã§ãªãå Žåã¯ã詳现ãè¿œå ã§ããŸã
ç§ãä»æ¥ããã«ééããæ°æéãç¡é§ã«ããŸããã DropTarget->åéæ©èœã®äžã®ããã¥ã¡ã³ãã«ããã«ã€ããŠã®ã¡ã¢ãæ®ãã®ã¯ã©ãã§ããïŒ ããã¯å°ãªããšãä»ã®äœäººãã欲æ±äžæºã®ããã«æããŸãªãã§ãããã
ãšããã§ã ãã®åé¡ã«é¢ãããã1ã€ã®æ¬åœã«éãããã¯ã¯ã dropTarget.hover()
ãã_ç¶æ
ãšããŠ_座æšãéä¿¡ããããšã§ãã
const dropTarget = {
hover(props, monitor, component) {
// HACK! Since there is an open bug in react-dnd, making it impossible
// to get the current client offset through the collect function as the
// user moves the mouse, we do this awful hack and set the state (!!)
// on the component from here outside the component.
component.setState({
currentDragOffset: monitor.getClientOffset(),
});
},
drop() { /* ... */ },
};
ãã¡ããããã®ãããªsetStateã®æªçšãåé¿ããããããè¡ãããã®ããæ£ããæ¹æ³ã¯ãããããããŸãã ããããå°ãªããšããã®å°ããªããã¯ã¯éåžžã«åçž®ãããŠããããã®åé¡ãæçµçã«ä¿®æ£ããããŸã§æ©èœããå¯èœæ§ããããŸãã ä»ã®ã³ã³ããŒãã³ãããã¡ã€ã«ãå€æŽããããã©ã€ãã©ãªã®å éšã«äŸåãããããããšãªãããã°ãããã¯ã§ããŸãã
ç·šéïŒããã¯åºæ¬çã«noah79ãšåãã§ããç§ã¯ä»ãŸã§åœŒã®ã³ãŒããèªãã§ããŸããã§ããã
ããããæã«ããŠã¹ã®äœçœ®ãååŸããæ¹æ³ã¯æ¬åœã«ãããŸãããïŒ ç§ã®ã¿ãŒã²ããã³ã³ããŒãã³ãã¯ããã«ã€ããŠç¥ãå¿
èŠããªãã®ã§ã setState
ã¯ç§ã«ãšã£ãŠãªãã·ã§ã³ã§ã¯ãããŸããã reduxã¢ã¯ã·ã§ã³ãããªã¬ãŒããããã«å¿
èŠãªã®ã¯åº§æšã ãã§ãã
ç§ã®æåŸã®ã¡ãã»ãŒãžã¯ç¡èŠããŠãã ããã drop
ãšendDrag
ã¯2ã€ã®ç°ãªãæ©èœã§ããã drop
å
ã§ã®ã«ãŒãœã«äœçœ®ã®ååŸã¯æåŸ
ã©ããã«æ©èœããããšãããããŸããã :)
ç§ã®ãã¹ãã«ãããšãreact-dndã¯ãã¢ã€ãã ãã¿ãŒã²ããäžã«ãã©ãã°ããããšããã«ããŠã¹ç§»åã€ãã³ããæ¶è²»ããŸãã html-backendããã®ã€ãã³ããæ¶è²»ããªãå¯èœæ§ãããå ŽåãisOverããããã£ãtrueã«èšå®ãããŠãããšãã¿ãŒã²ããã³ã³ããŒãã³ãã¯éåžžã®mousemoveãªã¹ããŒãæ¡ä»¶ä»ãã§ãã®domã«é 眮ã§ããŸãã ãã®åŸããã®ãªã¹ããŒã¯ãäœããããŠã¹ã®äžã«ãã©ãã°ãããŠãããšãã«ãïŒéåžžã®æ¹æ³ã§ïŒããŠã¹ã®äœçœ®ãååŸã§ããŸãã ç§ã¯ãããdragïŒïŒã¡ãœããããsetStateã䜿çšããŠäžæçã«æ©èœãããŸãããreactã¯ã¬ã³ããªã³ã°é·ç§»ã®éäžã§ç¶æ ãèšå®ããããšã«ã€ããŠèŠåãåºããŸãã
ãããç§ãã€ãŸããããã APIãœãªã¥ãŒã·ã§ã³ã®å Žåã¯+1ããŸãã¯å°ãªããšãFAQã®äœãã
ããããµããŒãããèšç»ã¯ãããŸããïŒ
ããã¯ã®ãªãåé¿çã®ã¢ã€ãã¢ããããŸãã DropTarget
ã©ãããŒãäœæãã hover
ãã©ããããŠãåéé¢æ°ãžã®å¥ã®åŒã³åºããããªã¬ãŒããåéé¢æ°ãæ°ããå€ãè¿ããå Žåã«åã¬ã³ããªã³ã°ããŸãã ã
ãã®åé¡ã®+1ã ç§ãæã£ãŠãããŠãŒã¹ã±ãŒã¹ã¯ãäºãã«è¿æ¥ããŠããããã€ãã®ããããã¿ãŒã²ãããããããšã§ãã ãããŒãããšãé©åãªããããã¿ãŒã²ããã匷調衚瀺ãããŸãããå®éã«ãããããããšããããŒããæ¹åã«å¿ããŠãããäœãã¿ãŒã²ããã«ããããããã®ã¯å¥åŠã«æããŸãã
ãªãã»ãããæŽæ°ãããªãçç±ã調æ»ããŠãããã®åé¡ã«ééããŸãããããŸã åé¿çãå¿
èŠãªããã§ãã
@ jedwards1211ã®ã¢ã€ãã¢ãåãäžãããããç§ãæãã€ãããã®ã§ãã HOCã®ã€ã³ã¿ãŒãã§ãŒã¹ã¯ããã©DropTarget
ãšã»ãŒåãã§ããããªãã·ã§ã³ã§collectRapidly
ãåãå
¥ããŸããããã¯ãåéé¢æ°ãä»ããŠã¯ãšãªãå®è¡ããå°éå
·ã®ãªã¹ãã§ããããã¹ãŠã®ãããŒã€ãã³ãã«æž¡ãããŸãã ãã¹ãŠã®å°éå
·ãåéé¢æ°ããç¡å·®å¥ã«æž¡ããšãå¥åŠãªããšãèµ·ããã connect
ãã³ã¬ã¯ã¿ãŒã«æž¡ãããšãã§ããªããªãããã connectDropTarget
ãè¿
éã«ãã¯ãšãªããããšãé²ãããšãã§ããŸãã
ã ããã代ããã«DropTarget(types, target, collect)
ããªãã䜿çšããRapidFireDropTarget(types, target, collect, {collectRapidly: ['offset']})
ã offset
ãããããããå€ãåãåããã®ã§ãmonitor.getOffset
é¢æ°ãã¡ããªãã
import React from 'react';
import {DropTarget} from 'react-dnd';
import pick from 'lodash/pick';
function RapidFireDropTarget(types, spec, collect, options={}) {
let collectProps = {};
const prevHover = spec.hover;
const {collectRapidly = []} = options;
const dummyConnect = {
dropTarget: () => () => {
throw new Error('Rapidly collected props cannot include results from `connect`');
}
};
const WrappedComponent = Component => {
return class extends React.Component {
render() {
return <Component {...this.props} {...collectProps} />;
}
};
};
spec.hover = (props, monitor, component) => {
const allCollectProps = collect(dummyConnect, monitor);
collectProps = pick(allCollectProps, collectRapidly);
component.forceUpdate();
if (prevHover instanceof Function) {
prevHover(props, monitor, component);
}
}
return (Component) => {
return DropTarget(types, spec, collect, options)(WrappedComponent(Component));
};
}
export default RapidFireDropTarget;
ãã®åé¡ã¯ãæè¿ã®ã¢ã¯ãã£ããã£ããªããããèªåçã«å€ããã®ãšããŠããŒã¯ãããŠããŸãã ãã以äžã®ã¢ã¯ãã£ããã£ãçºçããªãå Žåã¯éããããŸãã è²¢ç®ããŠããã ãããããšãããããŸãã
æãåèã«ãªãã³ã¡ã³ã
+1ã ããã«ééããgetClientOffsetïŒïŒãcanDropïŒïŒã§æ£åžžã«æ©èœããçç±ãç解ããããšããŠå€ãã®æéãç¡é§ã«ããŠããŸã-ããã¯ç¹°ãè¿ãåŒã³åºãããŸã...-ããããç§ãã¡ãããã¢ã€ãã ã®ãã©ããã§ç§ã®ã³ã³ãããŒã«ã«è»¢éããæ¹æ³ã¯ãããŸããã ããªãŒããŒãã®ãäžãã ãã§ãªããããªãŒããŒãã®äžäžã«æ¿å ¥ã§ããå¿ èŠããããŸãã canDropïŒïŒã«ã¯ãããŒããæã€å€ãã®ãã¿ã€ããã®ããããã®ã©ããã³ã³ããŒãã³ãã«å®éã«äŒããŠãããã«å¿ããŠã³ã³ãããŒã«ãå衚瀺ã§ããããã«ããæ¹æ³ããããŸããã canDropã§å°éå ·ãå€æŽãããšããšã©ãŒãçºçããŸããã onMouseMoveã®ãµãã¹ã¯ã©ã€ãã¯ããã©ãã°ã¢ã³ãããããæäœäžã«ã¯æ©èœããŸããã ããã¯ãããŸã§ã®ãšããæéã®å€§ããªç¡é§ã§ãã...ã©ããªå©ããããã ããã°å¹žãã§ãã
@ibash ãåé¡ã解決ããããã«è¡ã£ãããšã®èŠç¹ãæçš¿ããŠ