Как при наведении на элемент выделить его соседние элементы так, что бы получилась определенная фигура?
class Grid {
constructor(cols, rows, gap) {
this.cols = cols
this.rows = rows
this.gap = gap
this.grid = null
this.cells = []
this.mouseEnterHandler = this.mouseEnterHandler.bind(this)
this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this)
}
init(parent) {
this.createCells()
this.createGrid()
this.grid.append(...this.cells)
parent.prepend(this.grid)
}
createGrid() {
this.grid = document.createElement('div')
this.grid.style.display = 'grid'
this.grid.style.height = '100%'
this.grid.style.width = '100%'
this.grid.style.gridTemplateColumns = `repeat(${this.cols}, 1fr)`
this.grid.style.gridTemplateRows = `repeat(${this.rows}, 1fr)`
this.grid.style.gridGap = `${this.gap}px`
}
createCells() {
for (let i = 0; i < this.rows * this.cols; i++) {
const cell = document.createElement('div')
cell.style.backgroundColor = 'lightblue'
cell.id = i
cell.addEventListener('mouseenter', this.mouseEnterHandler)
cell.addEventListener('mouseleave', this.mouseLeaveHandler)
this.cells.push(cell)
}
}
mouseEnterHandler(e) {
e.target.style.backgroundColor = 'lightgreen'
}
mouseLeaveHandler(e) {
e.target.style.backgroundColor = 'lightblue'
}
}
const grid = new Grid(20, 20, 3)
grid.init(document.body)
body {
margin: 0;
height: 100vh;
}
Мои попытки сделать хоть какую-нибудь фигурку
class Grid {
constructor(cols, rows, gap) {
this.cols = cols
this.rows = rows
this.gap = gap
this.grid = null
this.cells = []
this.hoveredElements = []
this.hoveredElement = null
this.mouseEnterHandler = this.mouseEnterHandler.bind(this)
this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this)
}
init(parent) {
this.createCells()
this.createGrid()
this.grid.append(...this.cells)
parent.prepend(this.grid)
}
createGrid() {
this.grid = document.createElement('div')
this.grid.style.display = 'grid'
this.grid.style.height = '100%'
this.grid.style.width = '100%'
this.grid.style.gridTemplateColumns = `repeat(${this.cols}, 1fr)`
this.grid.style.gridTemplateRows = `repeat(${this.rows}, 1fr)`
this.grid.style.gridGap = `${this.gap}px`
}
createCells() {
for (let i = 0; i < this.rows * this.cols; i++) {
const cell = document.createElement('div')
cell.style.backgroundColor = 'lightblue'
cell.id = i
cell.addEventListener('mouseenter', this.mouseEnterHandler)
cell.addEventListener('mouseleave', this.mouseLeaveHandler)
this.cells.push(cell)
}
}
mouseEnterHandler(e) {
const targetBox = e.target.getBoundingClientRect()
this.cells.forEach((cell) => {
const cellBox = cell.getBoundingClientRect()
if (
targetBox.left - 100 <= cellBox.right &&
cellBox.right <= targetBox.left &&
targetBox.top == cellBox.top ||
targetBox.right + 100 >= cellBox.left &&
cellBox.left >= targetBox.right &&
targetBox.top == cellBox.top ||
targetBox.top - 100 <= cellBox.bottom &&
cellBox.bottom <= targetBox.top &&
targetBox.left == cellBox.left ||
targetBox.bottom + 100 >= cellBox.top &&
cellBox.top >= targetBox.bottom &&
targetBox.left == cellBox.left
) {
this.hoveredElements.push(cell)
}
})
this.hoveredElements.forEach((element) => {
element.style.backgroundColor = 'white'
})
}
mouseLeaveHandler(e) {
this.hoveredElements.forEach((element) => {
element.style.backgroundColor = 'lightblue'
})
this.hoveredElements = []
}
}
const grid = new Grid(20, 20, 3)
grid.init(document.body)
body {
margin: 0;
height: 100vh;
}
Ответы (2 шт):
Автор решения: Stranger in the Q
→ Ссылка
Вот например при помощи такой проверки
let x = e.target.id % this.cols;
let y = (e.target.id / this.rows) | 0;
this.cells.forEach((cell) => {
let cx = cell.id % this.cols;
let cy = (cell.id / this.rows) | 0;
if (Math.abs(cx - x) + Math.abs(cy - y) < 4) {
this.hoveredElements.push(cell)
}
})
class Grid {
constructor(cols, rows, gap) {
this.cols = cols
this.rows = rows
this.gap = gap
this.grid = null
this.cells = []
this.hoveredElements = []
this.hoveredElement = null
this.mouseEnterHandler = this.mouseEnterHandler.bind(this)
this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this)
}
init(parent) {
this.createCells()
this.createGrid()
this.grid.append(...this.cells)
parent.prepend(this.grid)
}
createGrid() {
this.grid = document.createElement('div')
this.grid.style.display = 'grid'
this.grid.style.height = '100%'
this.grid.style.width = '100%'
this.grid.style.gridTemplateColumns = `repeat(${this.cols}, 1fr)`
this.grid.style.gridTemplateRows = `repeat(${this.rows}, 1fr)`
this.grid.style.gridGap = `${this.gap}px`
}
createCells() {
for (let i = 0; i < this.rows * this.cols; i++) {
const cell = document.createElement('div')
cell.style.backgroundColor = 'lightblue'
cell.id = i
cell.addEventListener('mouseenter', this.mouseEnterHandler)
cell.addEventListener('mouseleave', this.mouseLeaveHandler)
this.cells.push(cell)
}
}
mouseEnterHandler(e) {
let x = e.target.id % this.cols;
let y = (e.target.id / this.rows) | 0;
this.cells.forEach((cell) => {
let cx = cell.id % this.cols;
let cy = (cell.id / this.rows) | 0;
if (Math.abs(cx - x) + Math.abs(cy - y) < 3) {
this.hoveredElements.push(cell)
}
})
this.hoveredElements.forEach((element) => {
element.style.backgroundColor = 'white'
})
}
mouseLeaveHandler(e) {
this.hoveredElements.forEach((element) => {
element.style.backgroundColor = 'lightblue'
})
this.hoveredElements = []
}
}
const grid = new Grid(20, 20, 3)
grid.init(document.body)
body {
margin: 0;
height: 100vh;
}
Автор решения: Leonid
→ Ссылка
Можно составить маску любой фигуры (так я вижу букву К):
this.mask = [[-1,-2],[-1,-1],[-1, 0],[-1,1],[-1,2],[0,0],[1,-1],[2,-2],[1, 1],[2,2]];
И переписать mouseEnterHandler следующим образом:
mouseEnterHandler(e) {
let x = e.target.id % this.cols; // Получаем х координату mouseover элемента
let y = Math.floor(e.target.id / this.rows); // Получаем y координату
this.mask.forEach(item => { // Перебираем позиции маски
let itemX = x + item[0]; // Определяем x координату элемента по дельте из маски
let itemY = y + item[1]; // Определяем y координату
// Проверяем не выходит ли элемент за пределы сетки
// Можно было потом проверить на существование по id, но мало ли где еще будут использоваться такие (числовые) id
if(itemX >= 0 && itemX < this.cols && itemY >= 0 && itemY < this.rows){
let order = +e.target.id + item[0] + item[1]*this.cols; // Находим порядковый номер
let cell = document.getElementById(order); // Получаем элемент по id = порядковый номер
this.hoveredElements.push(cell); // Закидываем в массив для последующего изменения style
}
})
this.hoveredElements.forEach((element) => { // Здесь перебираются элементы из массива this.hoveredElements
element.style.backgroundColor = 'white';
})
}
class Grid {
constructor(cols, rows, gap) {
this.cols = cols
this.rows = rows
this.gap = gap
this.grid = null
this.cells = []
this.hoveredElements = []
this.hoveredElement = null
this.mouseEnterHandler = this.mouseEnterHandler.bind(this)
this.mouseLeaveHandler = this.mouseLeaveHandler.bind(this)
this.mask = [[-1,-2],[-1,-1],[-1, 0],[-1,1],[-1,2],[0,0],[1,-1],[2,-2],[1, 1],[2,2]];
}
init(parent) {
this.createCells()
this.createGrid()
this.grid.append(...this.cells)
parent.prepend(this.grid)
}
createGrid() {
this.grid = document.createElement('div')
this.grid.style.display = 'grid'
this.grid.style.height = '100%'
this.grid.style.width = '100%'
this.grid.style.gridTemplateColumns = `repeat(${this.cols}, 1fr)`
this.grid.style.gridTemplateRows = `repeat(${this.rows}, 1fr)`
this.grid.style.gridGap = `${this.gap}px`
}
createCells() {
for (let i = 0; i < this.rows * this.cols; i++) {
const cell = document.createElement('div')
cell.style.backgroundColor = 'lightblue'
cell.id = i
cell.addEventListener('mouseenter', this.mouseEnterHandler)
cell.addEventListener('mouseleave', this.mouseLeaveHandler)
this.cells.push(cell)
}
}
mouseEnterHandler(e) {
let x = e.target.id % this.cols; // Получаем х координату mouseover элемента
let y = Math.floor(e.target.id / this.rows); // Получаем y координату
this.mask.forEach(item => { // Перебираем позиции маски
let itemX = x + item[0]; // Определяем x координату элемента по дельте из маски
let itemY = y + item[1]; // Определяем y координату
// Проверяем не выходит ли элемент за пределы сетки
// Можно было потом проверить на существование по id, но мало ли где еще будут использоваться такие (числовые) id
if(itemX >= 0 && itemX < this.cols && itemY >= 0 && itemY < this.rows){
let order = +e.target.id + item[0] + item[1]*this.cols; // Находим порядковый номер
let cell = document.getElementById(order); // Получаем элемент по id = порядковый номер
this.hoveredElements.push(cell); // Закидываем в массив для последующего изменения style
}
})
this.hoveredElements.forEach((element) => { // Здесь перебираются элементы из массива this.hoveredElements
element.style.backgroundColor = 'white';
})
}
mouseLeaveHandler(e) {
this.hoveredElements.forEach((element) => {
element.style.backgroundColor = 'lightblue'
})
this.hoveredElements = []
}
}
const grid = new Grid(20, 20, 1)
grid.init(document.body)
body {
margin: 0;
height: 100vh;
}
