Estou trabalhando com 1.0.0-rc.
Em 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);
}
};
No momento, parece que preciso obter o deslocamento da página do item original, então posso encontrar o deslocamento da página de onde larguei, então preciso encontrar o deslocamento do contêiner de soltar da página e, em seguida, esse cálculo e eu tenho a posição relativa em meu recipiente de destino de gota.
Isso parece muito trabalho para algo muito comum ...
Parece que getClientOffset
retorna a posição em relação à janela de visualização. Então, tudo que tenho a fazer é encontrar meu deslocamento no meu alvo de queda. Você acha que ainda vale a pena ter um método de conveniência em relação ao alvo de descarte?
Sim, acho que poderíamos ter isso para simetria. Por enquanto, você pode apenas usar findDOMNode(component).getBoundingClientRect()
, mas eu não me importaria de adicionar isso se mais pessoas derem suporte por voz. Vamos manter isso em aberto e ver o que os outros dizem.
Eu também gostaria de algo assim. Preciso obter o retângulo / coordenadas delimitadoras do alvo de queda, então, quando eu passar o mouse sobre ele, posso calcular se está no lado esquerdo, direito, superior ou inferior dentro do alvo de queda.
As coordenadas relativas podem ser úteis para outros casos de uso. Para um aplicativo semelhante ao Trello, quando você arrasta um cartão sobre uma lista, a lista rola para a parte inferior ao pairar próximo à parte inferior da área para soltar e rola para cima ao pairar próximo ao topo.
Trivial para implementar no espaço do usuário tho.
Além disso, lembro-me vagamente de ter lido que acessar o retângulo delimitador dispara refluxo nos navegadores e é um tanto caro. Não tenho certeza se este ainda é o caso.
Não acho que haja uma maneira de fazer isso sem realmente acessar getBoundingClientRect
porque você nunca sabe se o item foi movido.
Para um aplicativo semelhante ao Trello, quando você arrasta um cartão sobre uma lista, a lista rola para a parte inferior ao pairar próximo à parte inferior da área para soltar e rola para cima ao pairar próximo ao topo.
Esse é um ótimo caso de uso.
A penalidade de desempenho é realmente significativa e será desperdiçada se for adicionada ao React DnD, mas seu aplicativo não a usar. Portanto, não quero adicionar isso ao React DnD.
É fácil de implementar no domínio do usuário e você poderá fazer coisas como acelerar getBoundingClientRect
chamadas ou colocar o código de rolagem relacionado em um quadro de animação.
Estou aberto para adicionar “rolar ao pairar na parte inferior” _como um exemplo_ para o teste de estresse classificável . Isso envolveria adicionar outro destino de soltar no nível do contêiner que apenas escuta hover
e rola dentro de um quadro de animação.
No entanto, não adicionarei os métodos de coordenadas DOM ao React DnD pelos motivos descritos acima.
@gaearon Estou interessado em soluções generalizadas. Como podemos usar react-dnd-html5-backend
vez de getBoundingClientRect
diretamente?
Resolvi isso passando as funções DropTargetMonitor
getInitialSourceClientOffset
e getSourceClientOffset
para uma função de retorno de chamada dentro do meu evento onDrop
. Dessa forma, minha função de retorno de chamada pode calcular as coordenadas corretas relacionadas à porta de visualização.
// 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
não funciona com o componente funcional e useDrop#drop
não passa nenhum component
. Agora, se eu quiser obter ref
do meu componente, eu tenho para armazená-lo separadamente e chamar manualmente o conector de gota para passá-lo. Existe alguma maneira mais concisa de fazer isso?
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 , você tem algum exemplo de código completo que gostaria de compartilhar, por favor?
@dendrochronology
Um exemplo inventado: https://codesandbox.io/s/elastic-liskov-00ldf
A API é melhor quando não temos que armazenar ref
nós mesmos ( useGlobalDrop
vs useLocalDrop
). Agora, se apenas o ref
, que presumo que react-dnd
já obtém, está anexado ~ ao objeto monitor
~ em algum lugar (acessível em drop
, não tenho opinião onde), isso resolveria.
esta solução não é confiável, especialmente quando você aumenta o zoom no navegador ou altera a resolução do dispositivo. qualquer ideia?
eu tenho a mesma pergunta @ sepehr09
Só de passagem depois de algumas pesquisas no google ... Alguma atualização sobre a pergunta original? (obtendo o x / y de um item solto em relação ao alvo de soltar)
Acho que vou entrar na lista de quem precisa disso. Alguma ajuda por favor?
Acho esse recurso muito necessário, precisa ser adicionado na biblioteca. No momento, Alguém já trabalhou com isso, por favor nos ajude!
Comentários muito úteis
Sim, acho que poderíamos ter isso para simetria. Por enquanto, você pode apenas usar
findDOMNode(component).getBoundingClientRect()
, mas eu não me importaria de adicionar isso se mais pessoas derem suporte por voz. Vamos manter isso em aberto e ver o que os outros dizem.