Как изменить ширину таблицы при перетаскивании react
Перейти к содержимому

Как изменить ширину таблицы при перетаскивании react

  • автор:

Мышь: Drag’n’Drop

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/mouse-drag-and-drop.

Drag’n’Drop – это возможность захватить мышью элемент и перенести его. В своё время это было замечательным открытием в области интерфейсов, которое позволило упростить большое количество операций.

Перенос мышкой может заменить целую последовательность кликов. И, самое главное, он упрощает внешний вид интерфейса: функции, реализуемые через Drag’n’Drop, в ином случае потребовали бы дополнительных полей, виджетов и т.п.

Отличия от HTML5 Drag’n’Drop

В современном стандарте HTML5 есть поддержка Drag’n’Drop при помощи специальных событий.

Эти события поддерживаются всеми современными браузерами, и у них есть свои интересные особенности, например, можно перетащить файл в браузер, так что JS получит доступ к его содержимому. Они заслуживают отдельного рассмотрения.

Но в плане именно Drag’n’Drop у них есть существенные ограничения. Например, нельзя организовать перенос «только по горизонтали» или «только по вертикали». Также нельзя ограничить перенос внутри заданной зоны. Есть и другие интерфейсные задачи, которые такими встроенными событиями нереализуемы.

Поэтому здесь мы будем рассматривать Drag’n’Drop при помощи событий мыши.

Рассматриваемые приёмы, вообще говоря, применяются не только в Drag’n’Drop, но и для любых интерфейсных взаимодействий вида «захватить – потянуть – отпустить».

Алгоритм Drag’n’Drop

Основной алгоритм Drag’n’Drop выглядит так:

  1. Отслеживаем нажатие кнопки мыши на переносимом элементе при помощи события mousedown .
  2. При нажатии – подготовить элемент к перемещению.
  3. Далее отслеживаем движение мыши через mousemove и передвигаем переносимый элемент на новые координаты путём смены left/top и position:absolute .
  4. При отпускании кнопки мыши, то есть наступлении события mouseup – остановить перенос элемента и произвести все действия, связанные с окончанием Drag’n’Drop.

В следующем примере эти шаги реализованы для переноса мяча:

var ball = document.getElementById('ball'); ball.onmousedown = function(e) < // 1. отследить нажатие // подготовить к перемещению // 2. разместить на том же месте, но в абсолютных координатах ball.style.position = 'absolute'; moveAt(e); // переместим в body, чтобы мяч был точно не внутри position:relative document.body.appendChild(ball); ball.style.zIndex = 1000; // показывать мяч над другими элементами // передвинуть мяч под координаты курсора // и сдвинуть на половину ширины/высоты для центрирования function moveAt(e) < ball.style.left = e.pageX - ball.offsetWidth / 2 + 'px'; ball.style.top = e.pageY - ball.offsetHeight / 2 + 'px'; >// 3, перемещать по экрану document.onmousemove = function(e) < moveAt(e); >// 4. отследить окончание переноса ball.onmouseup = function() < document.onmousemove = null; ball.onmouseup = null; >>

Если запустить этот код, то мы заметим нечто странное. При начале переноса мяч «раздваивается» и переносится не сам мяч, а его «клон».

Это можно увидеть в действии внутри ифрейма:

Попробуйте перенести мяч мышкой и вы увидите описанное, довольно-таки странное, поведение.

Это потому, что браузер имеет свой собственный Drag’n’Drop, который автоматически запускается и вступает в конфликт с нашим. Это происходит именно для картинок и некоторых других элементов.

Его нужно отключить:

ball.ondragstart = function() < return false; >;

Теперь всё будет в порядке.

В действии (внутри ифрейма):

Ещё одна особенность правильного Drag’n’Drop – событие mousemove отслеживается на document , а не на ball .

С первого взгляда кажется, что мышь всегда над мячом и обработчик mousemove можно повесить на сам мяч, а не на документ.

Однако, на самом деле мышь во время переноса не всегда над мячом.

Вспомним, событие mousemove возникает хоть и часто, но не для каждого пикселя. Быстрое движение курсора вызовет mousemove уже не над мячом, а, например, в дальнем конце страницы.

Вот почему мы должны отслеживать mousemove на всём document .

Правильное позиционирование

В примерах выше мяч позиционируется в центре под курсором мыши:

self.style.left = e.pageX - ball.offsetWidth / 2 + 'px'; self.style.top = e.pageY - ball.offsetHeight / 2 + 'px';

Если поставить left/top ровно в pageX/pageY , то мячик прилипнет верхним-левым углом к курсору мыши. Будет некрасиво. Поэтому мы сдвигаем его на половину высоты/ширины, чтобы был центром под мышью. Уже лучше.

Но не идеально. В частности, в самом начале переноса, особенно если мячик «взят» за край – он резко «прыгает» центром под курсор мыши.

Для правильного переноса необходимо, чтобы изначальный сдвиг курсора относительно элемента сохранялся.

Где захватили, за ту «часть элемента» и переносим:

    Когда человек нажимает на мячик mousedown – курсор сдвинут относительно левого-верхнего угла мяча на расстояние, которое мы обозначим shiftX/shiftY . И нужно при переносе сохранить этот сдвиг. Получить значения shiftX/shiftY легко: достаточно вычесть из координат курсора pageX/pageY левую-верхнюю границу мячика, полученную при помощи функции getCoords. При Drag’n’Drop мы везде используем координаты относительно документа, так как они подходят в большем количестве ситуаций. Конечно же, не проблема перейти к координатам относительно окна, если это понадобится. Достаточно использовать position:fixed , elem.getBoundingClientRect() для определения координат и e.clientX/Y .

// onmousedown shiftX = e.pageX - getCoords(ball).left; shiftY = e.pageY - getCoords(ball).top;
// onmousemove ball.style.left = e.pageX - shiftX + 'px'; ball.style.top = e.pageY - shiftY + 'px';

Итоговый код с правильным позиционированием:

var ball = document.getElementById('ball'); ball.onmousedown = function(e) < var coords = getCoords(ball); var shiftX = e.pageX - coords.left; var shiftY = e.pageY - coords.top; ball.style.position = 'absolute'; document.body.appendChild(ball); moveAt(e); ball.style.zIndex = 1000; // над другими элементами function moveAt(e) < ball.style.left = e.pageX - shiftX + 'px'; ball.style.top = e.pageY - shiftY + 'px'; >document.onmousemove = function(e) < moveAt(e); >; ball.onmouseup = function() < document.onmousemove = null; ball.onmouseup = null; >; > ball.ondragstart = function() < return false; >; function getCoords(elem) < // кроме IE8- var box = elem.getBoundingClientRect(); return < top: box.top + pageYOffset, left: box.left + pageXOffset >; >

В действии (внутри ифрейма):

Различие особенно заметно, если захватить мяч за правый-нижний угол. В предыдущем примере мячик «прыгнет» серединой под курсор, в этом – будет плавно переноситься с текущей позиции.

Итого

Мы рассмотрели «минимальный каркас» Drag’n’Drop .

  1. События ball.mousedown → document.mousemove → ball.mouseup .
  2. Передвижение с учётом изначального сдвига shiftX/shiftY .
  3. Отмена действия браузера по событию dragstart .

На этой основе можно сделать очень многое.

  • При mouseup можно обработать окончание переноса, произвести изменения в данных, если они нужны.
  • Во время самого переноса можно подсвечивать элементы, над которыми проходит элемент.
  • При обработке событий mousedown и mouseup можно использовать делегирование, так что одного обработчика достаточно для управления переносом в зоне с сотнями элементов.

Это и многое другое мы рассмотрим в статье про Drag’n’Drop объектов.

16 posts tagged with «react.js»

Zustand (читается как «цуштанд», что переводится с немецкого как «состояние») — это, на мой взгляд, один из лучших на сегодняшний день инструментов для управления состоянием приложений, написанных на React.

В этой статье я немного расскажу о том, как он работает.

Давайте начнем с примера использования zustand для реализации функционала отображения/скрытия модального окна.

  • react.js
  • reactjs
  • react
  • zustand
  • reverse engineering
  • state management
  • управление состоянием
  • обратная разработка

Как React 18 улучшает производительность приложения

July 24, 2023 · 13 min read
JavaScript Developer

React 18 представил конкурентные (concurrent) возможности, которые радикально меняют способ рендеринга приложений. В этой статье мы рассмотрим, как эти возможности улучшают производительность приложения.

Начнем с повторения основ «долгих (долго выполняющихся) задач» (long tasks) и соответствующих метрик производительности.

RSC с нуля. Часть 1. Серверные компоненты

June 14, 2023 · 35 min read
JavaScript Developer

В этом техническом «глубоком погружении» (deep dive) мы с нуля реализуем очень простую версию серверных компонентов React.

Данный туториал будет состоять из трех частей (написана пока только эта).

Интересная схема работы с формами в React

March 21, 2023 · 13 min read
JavaScript Developer

В этой статье я хочу рассказать о схеме (назовем ее так) работы с формами в React, которая на сегодняшний день кажется мне наиболее эффективной. Эта схема предполагает использование React Hook Form для обработки форм и Zod для валидации пользовательских данных. Применение данной схемы имеет несколько существенных преимуществ по сравнению с использованием других решений или реализацией необходимого функционала вручную. Главными преимуществами являются минимизация количества шаблонного кода и автоматическое выведение типов (type inference).

Для тех, кого интересует только код, вот ссылка на соответствующий репозиторий.

Интересно? Тогда прошу под кат.

Разрабатываем расширение для браузера

March 6, 2023 · 7 min read
JavaScript Developer

В этом небольшом туториале мы с вами разработаем простое, но полезное расширение для браузера с помощью Plasmo.

Наше расширение будет представлять собой вызываемый сочетанием клавиш попап с инпутом для поиска информации на MDN с выводом 5 лучших результатов в виде списка. Кроме основного функционала, мы добавим страницу настроек для кастомизации цветов и отображения хлебных крошек. Мы будем разрабатывать расширения для Chrome, которое также будет работать в Firefox.

Вот как это будет выглядеть:

Для тех, кого интересует только код, вот ссылка на соответствующий репозиторий.

Искусственный интеллект как React-разработчик

January 26, 2023 · 8 min read
JavaScript Developer

Представляю вашему вниманию перевод этой замечательной статьи, в которой автор просит ChatGPT разработать компонент модального окна на React.

ChatGPT — это чат-бот с искусственным интеллектом, разработанный компанией OpenAI и способный работать в диалоговом режиме, поддерживающий запросы на естественных языках. ChatGPT — большая языковая модель, для тренировки которой использовались методы обучения с учителем и обучения с подкреплением. Чат-бот основывается на другой языковой модели от OpenAI GPT-3.5 — улучшенной версии модели GPT-3.

ChatGPT был запущен 30 ноября 2022 года и привлек внимание своими широкими возможностями: написание кода, создание текстов, возможности перевода, получения точных ответов и использование контекста диалога для ответов, хотя его фактическая точность подверглась критике (источник — Википедия).

Работа с 3D-графикой в React

December 7, 2022 · 9 min read
JavaScript Developer

В данном туториале я покажу вам самый простой и быстрый, хотя и не очень оптимальный с точки зрения размера сборки, способ рендеринга 3D-объектов и моделей в React.

Мы решим 3 интересные задачи:

  • рендеринг самописного 3D-объекта;
  • рендеринг готовой 3D-модели;
  • совместный рендеринг объекта и модели.

Знание вами основ работы с трехмерной графикой в браузере является опциональным.

Источником вдохновения для меня послужила эта замечательная статья.

Разработка приложения с помощью React Query

December 1, 2022 · 21 min read
JavaScript Developer

Представляю вашему вниманию перевод этой замечательной статьи, в которой рассказывается о разработке приложения с помощью React Query.

Прим. пер.: автор рассказывает лишь о ключевых особенностях приложения, поэтому я рекомендую клонировать репозиторий, установить зависимости и запустить сервер для разработки, чтобы иметь возможность выполнять необходимые операции при чтении статьи. Обратите внимание: если у вас возникнут проблемы при запуске сервера для разработки с помощью команды npm start , перенесите переменные, определенные в этой команде в файле package.json , в файл .env :

SKIP_PREFLIGHT_CHECK=true TSC_COMPILE_ON_ERROR=true ESLINT_NO_DEV_ERRORS=true 

И отредактируйте команду start следующим образом:

"start": "react-scripts start" 

Как изменить height объекта путем перетаскивания мыши?

В общем есть div, надо что бы при его перетаскивании, не менялись его координаты, а менялось значения стиля height, то есть что бы можно было мышкой растягивать элемент по вертикали. jQuery нельзя использовать. Если не сложно, дайте код для этого jsfiddle.net/Aliance/Z4NPu/4/.

  • Вопрос задан более трёх лет назад
  • 5019 просмотров

4 комментария

Оценить 4 комментария

мб. всетаки drag and drop?

iLeonidze

Описание вопроса не соответствует его названию

iLeonidze

Вопросы с меткой [drag-n-drop]

Это позволяет «схватить» объект с помощью мыши и перетащить его в другое место. Перетаскивание (Drag and Drop ) можно выполнять в приложении на основе браузера (веб) или в собственных приложениях с графическим интерфейсом, таких как Android или desktop.

231 вопрос
Конкурсные
Неотвеченные

  • Конкурсные 0
  • Неотвеченные
  • Цитируемые
  • Рейтинг
  • Неотвеченные (мои метки)

в библиотеке dnd kit для drag&drop при нажатии на вложенный компонент не срабатывает событие клика

У меня два компонента, родительский и дочерний, брал пример из документации, в дочернем компоненте у меня реализована логика по событию onClick раскрывать список элементов внутри, а в родительском .

задан 26 дек 2023 в 14:26
48 показов

Как сделать рабочую область C# Winforms

Делаю программу по учебе и мне требуется сделать конструктор php файла. Пытаюсь сделать программу на C# Winforms и хочу реализовать drag-n-drop интерфейс, позволяющий перетаскивать модули на рабочую .

задан 18 дек 2023 в 13:23

Смещения зоны загрузки drag-and-drop

Зона загрузки drag-and-drop назначена на модальное окно. Когда заносишь файлы на зону, то зона сместилась в сторону. Почему?! Необходимо над модальным окном. function inputFile() < const .

задан 11 дек 2023 в 9:07
48 показов

Инициировать событие Drag при создании объекта

У меня есть кнопка, при зажатии на которой клавиши (Input.GeyKey()), создаёт в точке другой объект из префаба. Создаваемый объект использует EventSystem для DragAndDrop. Но при создании, событие Drag .

задан 1 дек 2023 в 9:03
111 показов

Как модифицировать почти работающий скрипт, реализующий альтернативный скроллбар на странице через drag-n-drop? javascript

Вкратце: хочу реализовать скроллбар альтернативный системному. Если запустить код в FF, то наглядно видно, что всё вроде как работает, но скроллинг путем перетаскивания слайдера (функция DragElement) .

задан 9 окт 2023 в 21:30
30 показов

Проблемы с Drag and Drop в unity c# при изменении разрешения

При стандартном разрешении во время перетаскивания объекта все идет хорошо. Но при изменении разрешения в ondrag объект начинает двигаться быстрее курсора, чем выше разрешение тем он быстрее. Вот .

задан 26 сен 2023 в 14:42

Как в batch файле обработать нескольких сброшенных на него файлов?

Один файл без проблем: ffmpeg -i «%~1» «%~n1.gif» Как обработать группу из нескольких сброшенных (drag and drop) файлов? Пробовал: for %%a in (%*) do ( ffmpeg «%%a~1» .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *