Раскрашивание 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
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Раскрытие чувствительных данных
Раскрытие чувствительных данных
Все внешние компоненты, рассмотренные здесь до сих пор, взаимодействуют с клиентской стороной. Однако, если они подвергаются атаке, они не...
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Руководство ChatGPT по продаже мини JS-файлов
Руководство ChatGPT по продаже мини JS-файлов
JS-файл - это файл, содержащий код JavaScript. JavaScript - это язык программирования, который в основном используется для добавления интерактивности...
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>

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