React-dnd: Bagaimana cara mendapatkan koordinat item yang dijatuhkan relatif terhadap wadah target jatuh?

Dibuat pada 13 Mei 2015  ·  15Komentar  ·  Sumber: react-dnd/react-dnd

Saya bekerja dengan 1.0.0-rc.

Dalam 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);
  }
};

Saat ini sepertinya saya perlu mendapatkan offset dari halaman item asli, kemudian saya dapat menemukan offset dari halaman tempat saya menjatuhkan, lalu saya perlu menemukan offset wadah drop dari halaman, lalu lakukan perhitungan itu dan saya memiliki posisi relatif dalam wadah target penurunan saya.

Ini sepertinya banyak pekerjaan untuk sesuatu yang cukup umum ...

enhancement

Komentar yang paling membantu

Ya saya kira kita bisa memiliki ini untuk simetri. Untuk saat ini, Anda dapat menggunakan findDOMNode(component).getBoundingClientRect() , tetapi saya tidak keberatan menambahkan ini jika lebih banyak orang mendukung suara. Biarkan ini tetap terbuka dan lihat apa yang orang lain katakan.

Semua 15 komentar

Sepertinya getClientOffset mengembalikan saya posisi relatif terhadap viewport. Jadi yang harus saya lakukan adalah menemukan offset saya di target drop saya. Apakah menurut Anda masih layak untuk memiliki metode kenyamanan relatif terhadap target jatuh?

Ya saya kira kita bisa memiliki ini untuk simetri. Untuk saat ini, Anda dapat menggunakan findDOMNode(component).getBoundingClientRect() , tetapi saya tidak keberatan menambahkan ini jika lebih banyak orang mendukung suara. Biarkan ini tetap terbuka dan lihat apa yang orang lain katakan.

Saya ingin sesuatu seperti ini juga. Saya perlu mendapatkan rect/koordinat pembatas dari target drop, jadi ketika saya mengarahkan sesuatu di atasnya, saya dapat menghitung apakah itu di sisi kiri, kanan, atas atau bawah di dalam target drop.

Koordinat relatif dapat berguna untuk kasus penggunaan lainnya. Untuk aplikasi mirip Trello, saat Anda menyeret kartu ke atas daftar, daftar akan bergulir ke bawah saat melayang di dekat bagian bawah area pelepasan, dan menggulir ke atas saat melayang di dekat bagian atas.

Sepele untuk diterapkan pada ruang pengguna.

Juga, saya samar-samar ingat pernah membaca bahwa mengakses kotak pembatas memicu reflow di browser dan agak mahal. Tidak yakin apakah ini masih terjadi.

Saya tidak berpikir ada cara untuk melakukan ini tanpa benar-benar mengakses getBoundingClientRect karena Anda tidak pernah tahu apakah item tersebut dipindahkan.

Untuk aplikasi mirip Trello, saat Anda menyeret kartu ke atas daftar, daftar akan bergulir ke bawah saat melayang di dekat bagian bawah area pelepasan, dan menggulir ke atas saat melayang di dekat bagian atas.

Itu kasus penggunaan yang bagus.

Hukuman kinerja memang, signifikan, dan akan sia-sia jika ditambahkan ke React DnD tetapi aplikasi Anda tidak menggunakannya. Oleh karena itu, saya tidak ingin menambahkan ini ke React DnD.

Ini mudah diterapkan di userland, dan Anda akan dapat melakukan hal-hal seperti membatasi panggilan getBoundingClientRect , atau memasukkan kode pengguliran terkait ke dalam bingkai animasi.

Saya terbuka untuk menambahkan "gulir saat mengarahkan kursor ke bawah" _sebagai contoh_ ke tes stres yang dapat diurutkan . Ini akan melibatkan penambahan target penurunan lain di tingkat Penampung yang hanya mendengarkan hover dan menggulir di dalam bingkai animasi.

Namun saya tidak akan menambahkan metode koordinat DOM ke React DnD karena alasan yang dijelaskan di atas.

@gaearon Saya tertarik dengan solusi umum. Bagaimana kita bisa menggunakan react-dnd-html5-backend daripada getBoundingClientRect secara langsung?

Saya memecahkan ini dengan meneruskan fungsi DropTargetMonitor getInitialSourceClientOffset dan getSourceClientOffset ke fungsi panggilan balik di dalam acara onDrop . Dengan cara ini, fungsi panggilan balik saya dapat menghitung koordinat yang benar terkait dengan port tampilan.

// 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 tidak bekerja dengan komponen fungsional, dan useDrop#drop tidak memasukkan component . Sekarang jika saya ingin mendapatkan ref dari komponen saya, saya punya untuk menyimpannya secara terpisah dan secara manual panggil konektor drop untuk meneruskannya. Apakah ada cara yang lebih ringkas untuk melakukan ini?

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 apakah Anda memiliki contoh kode lengkap yang ingin Anda bagikan?

@dendrochronology

Contoh yang dibuat-buat: https://codesandbox.io/s/elastic-liskov-00ldf

API lebih bagus ketika kita tidak perlu menyimpan ref sendiri ( useGlobalDrop vs useLocalDrop ). Sekarang jika hanya ref , yang saya asumsikan react-dnd sudah diperoleh, dilampirkan ~ke objek monitor ~ di suatu tempat (dapat diakses di drop , saya tidak punya pendapat di mana), itu akan menyelesaikan ini.

solusi ini tidak dapat diandalkan terutama ketika Anda memperbesar browser atau perubahan resolusi perangkat. ada ide?

saya punya pertanyaan yang sama @sepehr09

Baru saja lewat setelah beberapa pencarian google... Ada pembaruan pada pertanyaan awal? (memperoleh x/y dari item yang dijatuhkan relatif terhadap target yang dijatuhkan)

Saya kira saya akan bergabung dengan daftar mereka, yang membutuhkan ini. Mohon bantuannya?

Menurut saya fitur ini sangat diperlukan, perlu ditambahkan di library. Saat ini, Siapapun yang bekerja dengannya, tolong bantu kami!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat