私は1.0.0-rcで作業しています。
drag-around-naive
:
const boxTarget = {
drop(props, monitor, component) {
const item = monitor.getItem();
const delta = monitor.getDifferenceFromInitialOffset();
const left = Math.round(item.left + delta.x);
const top = Math.round(item.top + delta.y);
component.moveBox(item.id, left, top);
}
};
現在、元のアイテムのページからオフセットを取得する必要があるようです。次に、ドロップした場所のページからのオフセットを見つけることができます。次に、ページからドロップコンテナのオフセットを見つける必要があります。次に、その計算と私は私のドロップターゲットコンテナ内の相対的な位置を持っています。
これはかなり一般的な何かのための多くの仕事のようです...
getClientOffset
は、ビューポートに対する相対的な位置を返すようです。 したがって、私がしなければならないのは、ドロップターゲットでオフセットを見つけることだけです。 ドロップターゲットに比べて便利な方法をとる価値はまだあると思いますか?
ええ、私たちは対称性のためにこれを持つことができると思います。 今のところ、 findDOMNode(component).getBoundingClientRect()
使用できますが、より多くの人が音声サポートを提供する場合は、これを追加してもかまいません。 これを開いたままにして、他の人の言うことを見てみましょう。
私もこういうものが欲しいです。 ドロップターゲットの境界の長方形/座標を取得する必要があるので、何かをその上に置くと、ドロップターゲットの内側の左側、右側、上部、または下部にあるかどうかを計算できます。
相対座標は、他のユースケースで役立ちます。 Trelloのようなアプリの場合、カードをリストの上にドラッグすると、ドロップ領域の下部にカーソルを合わせるとリストが下にスクロールし、上部にカーソルを合わせるとリストが上にスクロールします。
ユーザースペースに実装するのは簡単です。
また、境界矩形にアクセスするとブラウザでリフローが発生し、多少コストがかかることを読んだことをぼんやりと覚えています。 これがまだ当てはまるかどうかはわかりません。
アイテムが移動したかどうかわからないため、実際にgetBoundingClientRect
にアクセスせずにこれを行う方法はないと思います。
Trelloのようなアプリの場合、カードをリストの上にドラッグすると、ドロップ領域の下部にカーソルを合わせるとリストが下にスクロールし、上部にカーソルを合わせるとリストが上にスクロールします。
これは素晴らしいユースケースです。
パフォーマンスペナルティは確かに重要であり、React DnDに追加されても、アプリがそれを使用しない場合は無駄になります。 したがって、これをReactDnDに追加したくありません。
ユーザーランドでの実装は簡単で、 getBoundingClientRect
呼び出しを抑制したり、関連するスクロールコードをアニメーションフレームに配置したりすることができます。
ソート可能なストレステストに_例として_「下部のホバーでスクロール」を追加することを歓迎します。 これには、 hover
のみをリッスンし、アニメーションフレーム内でスクロールするコンテナレベルで別のドロップターゲットを追加することが含まれます。
ただし、上記の理由により、DOM座標メソッドをReactDnDに追加しません。
@gaearon一般化されたソリューションに興味があります。 react-dnd-html5-backend
代わりにgetBoundingClientRect
直接使用するにはどうすればよいですか?
DropTargetMonitor
関数getInitialSourceClientOffset
とgetSourceClientOffset
をonDrop
イベント内のコールバック関数に渡すことでこれを解決しました。 このようにして、私のコールバック関数はビューポートに関連する正しい座標を計算できます。
// some code before...
const [, dropRef] = useDrop({
accept: 'STICKY',
drop(item, monitor) {
move(
item.id,
monitor.getInitialSourceClientOffset(),
monitor.getSourceClientOffset()
);
},
});
// I'm updating my state with npm immer (immutable helper) throuthg the produce function...
const move = (id, initialPosition, finalPosition) => {
setList(
produce(list, draft => {
list.map(item => {
if (item.id === id) {
item.position = getCorrectDroppedOffsetValue(
initialPosition,
finalPosition
);
}
return item;
});
})
);
};
// and finally, my getCorrectDroppedOffsetValue function
const getCorrectDroppedOffsetValue = (initialPosition, finalPosition) => {
// get the container (view port) position by react ref...
const dropTargetPosition = ref.current.getBoundingClientRect();
const { y: finalY, x: finalX } = finalPosition;
const { y: initialY, x: initialX } = initialPosition;
// calculate the correct position removing the viewport position.
// finalY > initialY, I'm dragging down, otherwise, dragging up
const newYposition =
finalY > initialY
? initialY + (finalY - initialY) - dropTargetPosition.top
: initialY - (initialY - finalY) - dropTargetPosition.top;
const newXposition =
finalX > initialX
? initialX + (finalX - initialX) - dropTargetPosition.left
: initialX - (initialX - finalX) - dropTargetPosition.left;
return {
x: newXposition,
y: newYposition,
};
};
findDOMNode
は機能コンポーネントでは機能せず、 useDrop#drop
はcomponent
を渡しません。コンポーネントのref
を取得したい場合は、個別に保管し、手動でドロップコネクタを呼び出して渡します。 これを行うためのより簡潔な方法はありますか?
function useCustomDrop(onDrop: (info: unknown, xy: Point) => void) {
const ref = useRef<Element>();
const [, dropTarget] = useDrop<any, void, unknown>({
accept: 'item-type',
drop(item, monitor) {
const offset = monitor.getSourceClientOffset();
if (offset && ref.current) {
const dropTargetXy = ref.current.getBoundingClientRect();
onDrop(item.data, {
x: offset.x - dropTargetXy.left,
y: offset.y - dropTargetXy.top,
});
}
}
});
return (elem) => {
ref.current = elem;
dropTarget(ref);
};
}
@quanganhtran共有したい完全なコードサンプルはありますか?
@dendrochronology
不自然な例: https :
ref
自分で保存する必要がない場合、APIはより優れています( useGlobalDrop
とuseLocalDrop
)。 ここで、 react-dnd
すでに取得していると想定しているref
のみが、どこかのmonitor
オブジェクトにアタッチされている場合( drop
でアクセス可能)、意見)、それはこれを解決します。
このソリューションは、特にブラウザを拡大したり、デバイスの解像度を変更したりする場合は信頼できません。 何か案が?
同じ質問があります@ sepehr09
数回のグーグル検索の後に通り過ぎるだけです...元の質問の更新はありますか? (ドロップターゲットに対するドロップアイテムのx / yを取得する)
私はこれを必要とする人々のリストに加わると思います。 何か助けてください?
この機能は非常に必要であり、ライブラリに追加する必要があると思います。 今、誰もがそれを使って作業しました、私たちを助けてください!
最も参考になるコメント
ええ、私たちは対称性のためにこれを持つことができると思います。 今のところ、
findDOMNode(component).getBoundingClientRect()
使用できますが、より多くの人が音声サポートを提供する場合は、これを追加してもかまいません。 これを開いたままにして、他の人の言うことを見てみましょう。