Выделение элементов мышкой

пример работы программы

Как реализовать такое выделение на React или хотя бы на js ?


Ответы (1 шт):

Автор решения: Alexander Lonberg

Да вот так

const place = document.querySelector('div')
const size = 20
const [initColumn, initRow] = [20, 10]
const initColor = ['white', 'red']
let currentIndColor = 0

const cell = Object.entries({
  height: `${size}px`,
  width: `${size}px`,
  position: 'absolute',
  backgroundColor: initColor[currentIndColor],
  border: '1px solid #9e9e9e',
  boxSizing: 'border-box'
}).reduce((e, [s, v]) => (e.style[s] = v, e),
  document.createElement('div'))

function createElementTable(d, column, row, rowListeners) {
  let iColor = currentIndColor
  d._pos = {
    column, row,
    reset() {
      d.style.backgroundColor = initColor[iColor = iColor ? 0 : 1]
    },
    get indColor() {
      return iColor
    }
  }
  rowListeners[row] = {
    set() {
      if (currentIndColor === iColor) { return }
      iColor = currentIndColor
      d.style.backgroundColor = initColor[currentIndColor]
    },
    element: d
  }
}

const elementsTable = []
const currentCell = []

let cl = initColumn
while (cl--) {
  const rowListeners = []
  elementsTable[cl] = rowListeners
  let rw = initRow
  while (rw--) {
    const d = cell.cloneNode(true)
    d.style.top = `${size * rw}px`
    d.style.left = `${size * cl}px`
    place.appendChild(d)
    createElementTable(d, cl, rw, rowListeners)
  }
}

function setColor(target) {
  const startInd = currentCell[0]._pos
  const { column, row } = target._pos
  const rColumn = (startInd.column - column) > 0 ? -1 : 1
  const rRow = (startInd.row - row) > 0 ? -1 : 1
  const temp = new Set()
  let cl = startInd.column
  do {
    let rw = startInd.row
    do {
      const el = elementsTable[cl][rw]
      temp.add(el.element)
      if (!currentCell.includes(el.element)) {
        el.set()
        currentCell.push(el.element)
      }
    } while (rw !== row && (rw += 1 * rRow, true))
  } while (cl !== column && (cl += 1 * rColumn, true))
  for (let i = 0; i < currentCell.length; ++i) {
    if (temp.has(currentCell[i])) {
      continue
    }
    currentCell[i]._pos.reset()
    currentCell.splice(i--, 1)
  }
}

const over = ({ target }) => {
  if (!target._pos) { return }
  setColor(target)
}
const up = () => {
  place.removeEventListener('mouseover', over)
  currentCell.splice(0)
}
const down = (e) => {
  e.preventDefault()
  if (!e.target._pos) {
    return
  }
  document.addEventListener('mouseup', up, { once: true })
  place.addEventListener('mouseover', over)
  currentIndColor = e.target._pos.indColor ? 0 : 1
  const { column, row } = e.target._pos
  const el = elementsTable[column][row]
  el.set()
  currentCell.push(el.element)
}
place.addEventListener('mousedown', down)
<div></div>

→ Ссылка