Раскрашивание HTML <area> на основе клика

function eating(Num) {
  console.info("entered eating", Num);
  
  bodyEating = Num;
  
  for (let i = 0; i < Num; i++) {
    BODYEATING[0].background = "black";
  }
  console.info(BODYEATING[0]);
  //e.preventDefault();
}
<div class = "container text-center">
  <img src = "https://media.geeksforgeeks.org/wp-content/uploads/unique-rectangles-formed-using-n-unit-squares.png" usemap = "#image-map">
  <map id = "map" name = "image-map">
    <area target = "_self" alt = "1" title = "1" onclick = "eating(1)" coords = "21,385,24,309,100,309,101,385" shape = "poly">
    <area target = "_self" alt = "2" title = "2" onclick = "eating(2)" coords = "102,305,23,304,23,228,101,227" shape = "poly">
    <area target = "_self" alt = "3" title = "3" onclick = "eating(3)" coords = "103,225,26,228,25,149,99,151" shape = "poly">
    <area target = "_self" alt = "4" title = "4" onclick = "eating(4)" coords = "103,147,102,65,25,70,23,147" shape = "poly">
  </map>
</div>

У меня есть что-то вроде 5 изображений, каждое изображение представляет собой стопку из 10 квадратов. Я хочу, чтобы для каждого изображения, когда пользователь щелкает, например, изображение на квадрате 3, тогда я получу в своем коде, что пользователь нажал на квадрат 3, а также квадраты с 1 по 3 будут иметь фоновый цвет применяемый.

Я выполнил первую задачу, создав карту изображений. Тем не менее, я не могу поставить цель раскраски, и я много искал ее. Кто-нибудь может помочь?

Привет, Хеба. У вас есть соответствующий код, который вы могли бы опубликовать?

Daniel_Knights 20.12.2020 15:58

также добавьте чертеж предполагаемого макета. Я понятия не имею, что вы имеете в виду под: a pile of 10 squares, squares from 1 -3

tacoshy 20.12.2020 16:22

Я добавил файлы html и javascript

Heba 21.12.2020 09:27

Я хочу раскрасить квадраты. Например, когда я нажимаю на квадрат 3, я хочу раскрасить квадраты 1, 2 и 3.

Heba 21.12.2020 09:27

Изображения всегда квадратные? Если это так, было бы проще сделать это с помощью простых позиционированных элементов HTML, элементов SVG или элемента Canvas.

AKX 21.12.2020 09:29

Как так. Можете ли вы объяснить больше?

Heba 21.12.2020 09:32

Это не всегда квадраты. Мне также нужно будет работать с многоугольниками

Heba 21.12.2020 09:33

Я попытался изменить изображение на прозрачное, но также не была применена окраска.

Heba 21.12.2020 09:35

Карты изображений <area> на самом деле не имеют визуального присутствия, поэтому их нельзя раскрасить. Я бы предложил сделать ваши изображения SVG; Формы SVG, такие как квадраты и многоугольники, можно легко перекрасить.

AKX 21.12.2020 10:41
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
9
108
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы знаете, что размер/позиция будут статическими, вы можете вручную расположить элемент map и изменить размер каждого area так, чтобы он соответствовал:

function eating(Num) {
  const squares = document.querySelectorAll('area');

  console.info("entered eating", Num);

  for (let i = 0; i < squares.length; i++) {
    if (i < Num) {
      squares[i].style.background = "black";
    } else {
      squares[i].style.background = "transparent";
    }
  }
}
.container {
  position: relative;
}

map {
  display: grid;
  gap: 1px;
  position: absolute;
  top: 68px;
  left: 22.5px;
}

area {
  width: 79px;
  height: 79px;
  top: 0;
}
<div class = "container text-center">
  <img src = "https://media.geeksforgeeks.org/wp-content/uploads/unique-rectangles-formed-using-n-unit-squares.png" usemap = "#image-map">
  <map id = "map" name = "image-map">
    <area target = "_self" alt = "1" title = "1" onclick = "eating(1)" coords = "21,385,24,309,100,309,101,385" shape = "poly">
    <area target = "_self" alt = "2" title = "2" onclick = "eating(2)" coords = "102,305,23,304,23,228,101,227" shape = "poly">
    <area target = "_self" alt = "3" title = "3" onclick = "eating(3)" coords = "103,225,26,228,25,149,99,151" shape = "poly">
    <area target = "_self" alt = "4" title = "4" onclick = "eating(4)" coords = "103,147,102,65,25,70,23,147" shape = "poly">
  </map>
</div>

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

Я не понимаю, что именно это решит? Моя проблема в том, что я не могу раскрасить кучу квадратов. Тем не менее, они кликабельны, и я могу получить в своем коде, на какой квадрат щелкнул пользователь.

Heba 21.12.2020 10:14

Это окрашивает их, щелкните любой квадрат в левой колонке, и к ним будет применен фоновый цвет.

Daniel_Knights 21.12.2020 10:17

Вот, например, если я нажал на квадрат 3, квадраты с 1 по 3 окрашены в черный цвет. Есть ли способ сделать так, чтобы если пользователь снова нажал на 2, то квадраты только от 1 до 2 были окрашены?

Heba 21.12.2020 10:25

Отлично. Спасибо. Однако когда я применяю этот код к полигонам, он не работает. Он окрашивает квадраты? Вы можете помочь?

Heba 21.12.2020 10:33

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

Heba 21.12.2020 10:34

Как я уже сказал, это решение не масштабируется, и использовать его с другими формами будет либо очень сложно, либо невозможно. Как сказал @AKX в комментариях, вам лучше использовать другой подход.

Daniel_Knights 21.12.2020 10:36

Какие еще решения вы рекомендуете?

Heba 21.12.2020 10:39

Лично я бы выбрал отдельные <svg> элементы, но это только мои предпочтения.

Daniel_Knights 21.12.2020 10:41
Ответ принят как подходящий

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

function handleSVGClick(event) {
  if (event.target.tagName === "polygon") {
    event.target.style.fill = `hsl(${Math.random() * 360}, 90%, 60%)`;
  }
}
polygon {
  stroke-width: 2px;
  stroke: #333;
  fill: transparent;
}
<svg width = "564" height = "409" onclick = "handleSVGClick(event)">
  <image
    href = "https://media.geeksforgeeks.org/wp-content/uploads/unique-rectangles-formed-using-n-unit-squares.png"
    width = "564"
    height = "409"
  />
  <polygon title = "1" points = "21,385 24,309 100,309 101,385" />
  <polygon title = "2" points = "102,305 23,304 23,228 101,227" />
  <polygon title = "3" points = "103,225 26,228 25,149 99,151" />
  <polygon title = "4" points = "103,147 102,65 25,70 23,147" />
</svg>

Скажите, как вы отметили каждый квадрат?

Heba 21.12.2020 10:59

<polygon title = "1" points = "21,385 24,309 100,309 101,385" /> эта часть

Heba 21.12.2020 10:59

Кроме того, математика, которую вы сделали здесь hsl(${Math.random() * 360}, 90%, 60%), заключается в том, чтобы просто генерировать случайный цвет или у него есть другое применение?

Heba 21.12.2020 11:00

Это просто для красивых цветов, да. Вы можете найти документацию по полигонам SVG по адресу developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon

AKX 21.12.2020 11:05

Есть ли способ определить, на какой полигон я нажал?

Heba 21.12.2020 12:03

Я получаю event.target,.tagName = "image

Heba 21.12.2020 12:11

Вы можете дать каждому полигону идентификатор. Многоугольники также должны быть заполнены прозрачным цветом, как в моем примере, чтобы на них можно было кликать. В противном случае вы перейдете к изображению.

AKX 21.12.2020 12:13

Почему, когда я добавляю к изображению более одного полигона, появляется только первый?

Heba 21.12.2020 13:37

Не видя вашего кода, невозможно понять, почему.

AKX 21.12.2020 13:41

Откуда вы взяли этот номер = "points = "21,385 24,309 100,309 101,385"" Я знаю, что это значит, но как вы его получили, есть ли инструмент или что-то в этом роде?

Heba 21.12.2020 13:57

например, в том же коде, который вы написали ранее, если бы это были координаты, появляются только два полигона <polygon title = "1" points = "24,68,98,68,99,144,23,144" /> <polygon title = "2" points = "98,150,25,150,24,222,101,225" /> <polygon title = "3" points = "103,225 26,228 25,149 99,151" /> <polygon title = "4" points = "103,147 102,65 25,70 23,147" />

Heba 21.12.2020 14:01

Это те же координаты, что и у вас, только с пробелом между каждой парой x/y (т. е. x, y, x, y, x, y равно x, y x, y x, y)

AKX 21.12.2020 17:08

Как я могу сделать форму многоугольника более гладкой? особенно, когда у меня есть более пышные формы, такие как банан, например

Heba 20.05.2021 11:58

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

Heba 20.05.2021 15:26

В этом случае вы можете использовать элемент <path>. Они также могут описывать кривые.

AKX 20.05.2021 18:04

Когда я делал многоугольники, я использовал онлайн-генератор карт изображений, чтобы определить координаты многоугольника на изображении, которое у меня есть. Что я могу использовать для определения пути к имеющемуся у меня изображению?

Heba 23.05.2021 09:36

Вы можете использовать эл. г. Inkscape, редактор SVG, для рисования контуров/многоугольников поверх вашего изображения. Затем вы можете сохранить SVG и открыть его в текстовом редакторе, чтобы извлечь нужный путь.

AKX 23.05.2021 12:28

Ну, чтобы область была кликабельной, у них должен быть атрибут href. (по крайней мере, в Firefox). Поскольку они скрыты, их сложно стилизовать в разных браузерах. Поэтому я пошел другим путем и создал элементы в той же позиции, что и области, и стилизовал их при каждом щелчке по области.

Эти наложения — просто доказательство концепции, но, поскольку я работаю здесь с процентами, это может работать, даже если изображение уменьшено.

Также я бы рекомендовал делать все это, когда Javascript определенно поддерживается, а также предложить удалить элемент области, если вы не хотите, чтобы пользователи повторно щелкали по ним во второй раз. дайте мне знать, если есть что-то еще, что вы хотели бы, чтобы я настроил здесь:

function eating(Num) {
  console.info("entered eating", Num);    
  if (Num == 4) { // testcode
     document.querySelector("#overlay"+Num).style.display = "block";  
  }
  // remove area from map
 
}
(function init() {
    var container = document.querySelector('.container');
    container.classList.add("js")
})()
img {
  max-width: 100%; 
}

.overlay {
  display: none;
}

.container {
  display: inline-block; /* container same width as image */
  width: auto;
  outline: 2px solid red;
}

.container.js {
  position: relative;
}
.container.js .overlay {
  position: absolute;
  top: 16.8%; left: 4.3%;
  width: 13.5%; height: 18.5%;
  background: black;
  z-index: 1;
}
<div class = "container text-center">
  <span class = "overlay" id = "overlay4"></span>
  <img src = "https://media.geeksforgeeks.org/wp-content/uploads/unique-rectangles-formed-using-n-unit-squares.png" usemap = "#image-map">
  <map id = "map" name = "image-map">
    <area target = "_self" alt = "1" title = "1" href = "#" onclick = "eating(1)" coords = "21,385,24,309,100,309,101,385" shape = "poly">
    <area target = "_self" alt = "2" title = "2" href = "#" onclick = "eating(2)" coords = "102,305,23,304,23,228,101,227" shape = "poly">
    <area target = "_self" alt = "3" title = "3" href = "#" onclick = "eating(3)" coords = "103,225,26,228,25,149,99,151" shape = "poly">
    <area target = "_self" alt = "4" title = "4" href = "#" onclick = "eating(4)" coords = "103,147,102,65,25,70,23,147" shape = "poly">
  </map>
</div>

Другие вопросы по теме