Рисование мышью элемента DIV

Рейтинг: 2Ответов: 2Опубликовано: 09.03.2023

Как изменить формулу, чтобы рисовать во всех направлениях?

// Создаем новый элемент div
const obl = document.querySelector(".main");
var newDiv = document.createElement("div");
newDiv.style.position = "absolute";
newDiv.style.backgroundColor = "red";

// Добавляем обработчик клика на странице
obl.addEventListener("mousedown", function(event) {
  // Проверяем, что клик был совершен левой кнопкой мыши

  // Устанавливаем начальные координаты элемента div
  newDiv.style.left = event.pageX + "px";
  newDiv.style.top = event.pageY + "px";
  // Добавляем элемент div на страницу
  obl.appendChild(newDiv);
  // Добавляем обработчик движения мыши с зажатой левой кнопкой
  obl.addEventListener("mousemove", drawDiv);

});

// Функция для рисования элемента div
function drawDiv(event) {
  // Проверяем, что левая кнопка мыши все еще зажата
  if (event.buttons === 1) {
    // Изменяем размеры элемента div в соответствии с положением мыши
    var width = event.pageX - parseInt(newDiv.style.left);
    var height = event.pageY - parseInt(newDiv.style.top);
    newDiv.style.width = width + "px";
    newDiv.style.height = height + "px";
  } else {
    // Если левая кнопка мыши отпущена, удаляем обработчик движения мыши
    obl.removeEventListener("mousemove", drawDiv);
  }
}
.main {
  height: 500px;
  width: 500px;
  border: 1px solid #000000;
  position: relative;
}
<div class="main"></div>

Ответы

▲ 4Принят

Вам необходимо добавить условия, которые будут проверять, больше ли текущие координаты курсора, чем стартовые:

// Создаем новый элемент div
const obl = document.querySelector(".main");
var newDiv = document.createElement("div");
newDiv.style.position = "absolute";
newDiv.style.backgroundColor = "red";
newDiv.style.pointerEvents = "none";

// Добавляем обработчик клика на странице
obl.addEventListener("mousedown", function(event) {
  // Проверяем, что клик был совершен левой кнопкой мыши
  if (event.buttons !== 1) return;
  // Устанавливаем начальные координаты элемента div
  newDiv.style.left = (obl.startPosX = event.offsetX) + "px";
  newDiv.style.top = (obl.startPosY = event.offsetY) + "px";
  newDiv.style.width = newDiv.style.height = "0px";
  // Добавляем элемент div на страницу
  obl.appendChild(newDiv);
  // Добавляем обработчик движения мыши с зажатой левой кнопкой
  obl.addEventListener("mousemove", drawDiv);
});

// Функция для рисования элемента div
function drawDiv(event) {
  // Проверяем, что левая кнопка мыши все еще зажата
  if (event.buttons === 1) {
    // Изменяем размеры элемента div в соответствии с положением мыши
    if (event.offsetX > obl.startPosX) {
      newDiv.style.width = event.offsetX - obl.startPosX + "px";
    } else {
      newDiv.style.left = event.offsetX + "px";
      newDiv.style.width = obl.startPosX - event.offsetX + "px";
    }
    if (event.offsetY > obl.startPosY) {
      newDiv.style.height = event.offsetY - obl.startPosY + "px";
    } else {
      newDiv.style.top = event.offsetY + "px";
      newDiv.style.height = obl.startPosY - event.offsetY + "px";
    }
  } else {
    // Если левая кнопка мыши отпущена, удаляем обработчик движения мыши
    obl.removeEventListener("mousemove", drawDiv);
  }
}
.main {
  height: 500px;
  width: 500px;
  border: 1px solid #000000;
  position: relative;
}
<div class="main"></div>


А можете подсказать, как сохранять новосозданный элемент.

Простейший способ сделать это - клонирование узла со всеми свойствами и атрибутами.

// Создаем новый элемент div
const obl = document.querySelector(".main");
var newDiv = document.createElement("div");
newDiv.style.position = "absolute";
newDiv.style.pointerEvents = "none";

// Добавляем обработчик клика на странице
obl.addEventListener("mousedown", function(event) {
  // Проверяем, что клик был совершен левой кнопкой мыши
  if (event.buttons !== 1) return;
  // Устанавливаем начальные координаты элемента div
  newDiv.style.left = (obl.startPosX = event.offsetX) + "px";
  newDiv.style.top = (obl.startPosY = event.offsetY) + "px";
  newDiv.style.width = newDiv.style.height = "0px";
  // Добавляем элемент div на страницу
  newDiv.style.backgroundColor = `hsla(${parseInt(Math.random() * 360)}deg,75%,50%,.9)`;
  obl.appendChild(newDiv);
  // Добавляем обработчик движения мыши с зажатой левой кнопкой
  obl.addEventListener("mousemove", drawDiv);
});

// Функция для рисования элемента div
function drawDiv(event) {
  // Проверяем, что левая кнопка мыши все еще зажата
  if (event.buttons === 1) {
    // Изменяем размеры элемента div в соответствии с положением мыши
    if (event.offsetX > obl.startPosX) {
      newDiv.style.width = event.offsetX - obl.startPosX + "px";
    } else {
      newDiv.style.left = event.offsetX + "px";
      newDiv.style.width = obl.startPosX - event.offsetX + "px";
    }
    if (event.offsetY > obl.startPosY) {
      newDiv.style.height = event.offsetY - obl.startPosY + "px";
    } else {
      newDiv.style.top = event.offsetY + "px";
      newDiv.style.height = obl.startPosY - event.offsetY + "px";
    }
  } else {
    // Если левая кнопка мыши отпущена, удаляем обработчик движения мыши
    obl.removeEventListener("mousemove", drawDiv);
    // Добавляем клон созданного элемента 
    obl.appendChild(newDiv.cloneNode(true));
  }
}
.main { position: relative; height: 500px; width: 500px; border: 1px solid #000; }
<div class="main"></div>

Вариант на jQuery на enSO.


Еще такой вопрос - свойство pointer-events не дает обрабатывать события мыши на созданных областях.

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

// Создаем новый элемент div
const obl = document.querySelector(".main");
const newDiv = document.createElement("div");

// Добавляем обработчик клика на странице
obl.addEventListener("mousedown", function(ev) {
  // Проверяем, что клик был совершен левой кнопкой мыши
  if (ev.buttons !== 1) return;
  // Проверяем, что клик был совершен по холсту
  if (ev.target === this) {
    // Добавляем вспомогательный класс на время создания
    this.classList.toggle("create", true);
    // Устанавливаем начальные координаты элемента div
    newDiv.style.left = (this.startPosX = ev.offsetX) + "px";
    newDiv.style.top = (this.startPosY = ev.offsetY) + "px";
    newDiv.style.width = newDiv.style.height = "0px";
    // Устанавливаем случайный цвет
    newDiv.style.backgroundColor = `hsla(${parseInt(Math.random() * 360)}deg,75%,50%,.8)`;
    // Добавляем элемент div на страницу
    this.appendChild(newDiv);
    // Добавляем обработчик движения мыши с зажатой левой кнопкой
    this.addEventListener("mousemove", drawDiv);
  } else {
    this.dragElem = ev.target;
    obl.addEventListener("mousemove", mMove);
    obl.addEventListener("mouseup", mUp);
  }
});

// Функция для рисования элемента div
function drawDiv(ev) {
  // Проверяем, что левая кнопка мыши все еще зажата
  if (ev.buttons === 1) {
    // Изменяем размеры элемента div в соответствии с положением мыши
    if (ev.offsetX > this.startPosX) {
      newDiv.style.width = ev.offsetX - this.startPosX + "px";
    } else {
      newDiv.style.left = ev.offsetX + "px";
      newDiv.style.width = this.startPosX - ev.offsetX + "px";
    }
    if (ev.offsetY > this.startPosY) {
      newDiv.style.height = ev.offsetY - this.startPosY + "px";
    } else {
      newDiv.style.top = ev.offsetY + "px";
      newDiv.style.height = this.startPosY - ev.offsetY + "px";
    }
  } else {
    // Если левая кнопка мыши отпущена, удаляем обработчик движения мыши
    this.removeEventListener("mousemove", drawDiv);
    this.classList.toggle("create", false);
    // Добавляем клон созданного элемента
    let clone = this.appendChild(newDiv.cloneNode(true));
    clone.addEventListener("mousedown", mDown);
    newDiv.remove();
  }
}

/* Перетаскивание элементов */
function mDown(e) {
  this.x = this.offsetLeft - e.clientX;
  this.y = this.offsetTop - e.clientY;
}
function mUp(e) {
  obl.removeEventListener("mousemove", mMove);
}
function mMove(e) {
  this.dragElem.style.left = e.clientX + this.dragElem.x + "px";
  this.dragElem.style.top = e.clientY + this.dragElem.y + "px";
}
.main { position: relative; height: 500px; width: 500px; border: 1px solid #000; }

.main > div { position: absolute; filter: drop-shadow(0 2px 2px #0008); cursor: pointer; }
.main > div:hover { box-shadow: inset 0 0 0 1px #000; }
.main.create > div { pointer-events: none; }
<div class="main"></div>

▲ 0

Можно сделать проще, но перед использованием стоит проверить совместимость используемых pointer-событий с браузерами.

pointer-events: none используется для устранения проблем с начальной точкой когда рисование начинается над добавленным div'ом. Думаю, это можно исправить - займусь попозже.

var root = document.querySelector("main")
var div, x0, y0

root.addEventListener('pointerdown', e => {
  e.target.setPointerCapture(e.pointerId)

  div = document.createElement('div')

  div.style.left = (x0 = e.offsetX) + 'px'
  div.style.top = (y0 = e.offsetY) + 'px'
  div.style.background = '#' + (Math.random() * 0x1000000 | 0x1000000).toString(16).slice(1)
  
  root.addEventListener('pointermove', update);

  root.addEventListener('pointerup', e => {
    update(e)
    div = null
    root.removeEventListener('pointermove', update)
  }, { once: true })

  root.appendChild(div)
})

function update({ offsetX: x, offsetY: y }) {
  div.style.left = Math.min(x, x0) + 'px'
  div.style.top = Math.min(y, y0) + 'px'
  div.style.width = Math.abs(x - x0) + 'px'
  div.style.height = Math.abs(y - y0) + 'px'
}
main {
  height: 500px;
  width: 500px;
  border: 1px solid #000000;
  position: relative;
}

main > div {
  position: absolute;
  pointer-events: none; /* Oops... */
}
<main></main>