Создание изменяемых HTML элементов на чистом JavaScript

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

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

JS
Скопировать код
const elem = document.getElementById('resizable');
elem.style.position = 'relative';
const handle = document.createElement('div');
Object.assign(handle.style, { width: '8px', height: '8px', background: 'blue', position: 'absolute', right: '0', bottom: '0', cursor: 'nwse-resize' });
elem.append(handle);

handle.addEventListener('mousedown', e => {
  e.preventDefault();
  const startX = e.pageX, startY = e.pageY;
  const startWidth = parseInt(window.getComputedStyle(elem).width, 10);
  const startHeight = parseInt(window.getComputedStyle(elem).height, 10);

  const doDrag = (e) => {
    elem.style.width = `${startWidth + e.pageX – startX}px`;
    elem.style.height = `${startHeight + e.pageY – startY}px`;
  };

  const stopDrag = () => {
    document.documentElement.removeEventListener('mousemove', doDrag);
    document.documentElement.removeEventListener('mouseup', stopDrag);
  };

  document.documentElement.addEventListener('mousemove', doDrag);
  document.documentElement.addEventListener('mouseup', stopDrag);
});

Стоит заметить, что данный способ изменения размеров элемента осуществляется за счёт отслеживания событий мыши непосредственно на document.documentElement, что позволяет изменять размер элемента, начиная с его нижнего правого угла.

Кинга Идем в IT: пошаговый план для смены профессии

Оптимизация взаимодействия с пользователем

Отзывчивость страницы

Чтобы веб-страница оставалась отзывчивой во время изменения размеров элемента, важно обеспечить плавность всех действий пользователя. В данном случае можно воспользоваться requestAnimationFrame в обработчике mousemove для оптимизации обычных операций:

JS
Скопировать код
let rafPending = false;

const doDrag = (e) => {
  if (rafPending) return;

  rafPending = true;
  requestAnimationFrame(() => {
    elem.style.width = `${startWidth + e.pageX – startX}px`;
    elem.style.height = `${startHeight + e.pageY – startY}px`;
    rafPending = false;
  });
};

Совместимость с различными браузерами

Обязательно проверьте работу кода в разных браузерах, включая Firefox. Для старых версий Internet Explorer (IE <9) подготовьте альтернативные варианты, например, простые уведомления для пользователей этих версий браузера.

Улучшение пользовательского опыта

Внесите изменения в размер и внешний вид ручки, чтобы повысить качество взаимодействия с пользователем. Обновите стиль ручки и добавьте переходные эффекты:

JS
Скопировать код
handle.style.transition = 'all 0.2s';
handle.addEventListener('mouseover', () => {
  handle.style.background = 'red';
});
handle.addEventListener('mouseout', () => {
  handle.style.background = 'blue';
});

Визуализация

Для наглядности сравним процесс изменения размеров элемента с настройкой телескопа:

Markdown
Скопировать код
Телескоп (🔭) – это HTML-элемент
Расширение/Сжатие (🔄) – изменение размера с помощью JavaScript
Окуляр (👁️) – это пункт взаимодействия пользователя с элементом
JS
Скопировать код
// Телескоп, настроенный в JavaScript:
element.onmousedown = function(event) {
  document.onmousemove = function(moveEvent) {
    element.style.width = `${moveEvent.clientX}px`;
    element.style.height = `${moveEvent.clientY}px`;
  };
  document.onmouseup = function() {
    document.onmousemove = null;
  };
};

Поясним:

Markdown
Скопировать код
До: [🔭👁️] – размер фиксирован
После: [🔭🔄👁️] – размер изменён

Изменение размеров в разных направлениях

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

JS
Скопировать код
// Добавляем функцию для создания ручек в разных направлениях
function addResizeHandle(element, position) {
  const handle = document.createElement('div');
  // Затем применяем необходимые стили и добавляем логику перетаскивания для каждой ручки
  element.appendChild(handle);
}

// Укомплектовываем элемент ручками по углам
addResizeHandle(elem, 'top-left');
addResizeHandle(elem, 'top-right');
addResizeHandle(elem, 'bottom-left');
addResizeHandle(elem, 'bottom-right');

Установка ограничений

Установите минимум и максимум для изменения размеров элемента:

JS
Скопировать код
// ... в функции doDrag задайте ограничения для новых размеров

elem.style.width = `${newWidth}px`;
elem.style.height = `${newHeight}px`;

Эффективное использование стилей

Сохраните начальные значения стилей и используйте их:

JS
Скопировать код
const computedStyle = getComputedStyle(elem);

Используйте computedStyle для доступа к значениям ширины и высоты в начале операции перетаскивания.

Полезные материалы

  1. resize – CSS: Cascading Style Sheets — документация о свойстве resize в CSS.
  2. Примеры использования resize на CSS-Tricks — полезные советы и примеры.
  3. HTML DOM Style object — как изменять стили элементов с помощью JavaScript.
  4. Обработка событий мыши — как работать с событиями мыши в JavaScript.
  5. Набор JavaScript-утилит — обширный набор JS-утилит для различных задач.
  6. Как создать плавные CSS-анимации — руководство по созданию плавных CSS-анимаций.