Как сделать счетчик нажатий с прогресс баром и лимитом нажатий?

вот здесь нажали на картинку 6 284 раза, линия почти заполнена а на второй картинке нажали 6302 раза, border и background заполнились чуть больше. Вторую картинку вставить не получается.введите сюда описание изображения

let count = 0;

function clickButton() {
  count++;
  document.getElementById("counter").innerText = count + "/10";

  if (count >= 10) {
    document.getElementById("countButton").disabled = true;
  }
}
#countButton {
  background: none;
  color: inherit;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  outline: inherit;
}
   <div class="gold">
         <button id="countButton" onclick="clickButton()"<a href=""><img src="IMG_3948.PNG" alt="Image 4"></a></button>
         <p id="counter">0/10</p>
 </div>

Нужно добавить к картинке с верхнего левого края счетчик нажатий всего нажатий максимум может быть 100, пример оформления текста: 0/100, каждый раз когда человек будет нажимать на картинку то рамки текста закругленные на 20 пикселей будут понемногу заполнять рамки border цветом: #f3a45d, и одновременно background к примеру цветом: белый, и цифры тоже будут меняться как в примере кода, то есть одно нажатие ровняется 1% заполнения цветом border и background, после достижения лимита в 100 нажатий, на картинку больше нельзя будет нажать, заполнение цветом с лево на право.


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

Автор решения: Grundy

Для решения можно использовать подход с двумя элементами

  1. заполненный
  2. незаполненный

Расположив их один поверх другого, изменяя ширину можно добиться эффекта прогресса

Например

let count = 0;

function clickButton() {
  count++;
  document.getElementById("counter").innerText = count + "/10";
  progress.style.width = (count * 10) + '%'; // меняем ширину прогресса, в данном случае в процентах.

  if (count >= 10) {
    document.getElementById("countButton").disabled = true;
  }
}

filled.style.width = counter.offsetWidth + 'px'; // выставляем дублирующему элементу ширину такую же как в основном счетчике
#countButton {
  background: none;
  color: inherit;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  outline: inherit;
}

.wrapper {
  position: relative;
}

p {
  padding: 20px;
  border-radius: 30px;
  margin: 0;
  box-sizing: border-box;
}

#counter {
  border: 1px solid lightgray;
}

#filled {
  border: 1px solid red;
}

#progress {
  pointer-events: none;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  transition: width .2s linear;
}
<div class="gold">
  <button id="countButton" onclick="clickButton()">Add</button>
  <div class="wrapper">
    <!-- счетчик с неактивным бордером -->
    <p id="counter">0/10</p>
    <div id="progress"> <!-- элемент отвечающий за прогресс -->
      <p id="filled">&nbsp;</p><!-- элемент дублирующий основной счетчик -->
    </div>
  </div>
</div>

→ Ссылка
Автор решения: UModeL

Есть несколько вариантов запомнить данные для последующего вывода и взаимодействия. Но, основываясь на вашей разметке и пожеланиях в комментариях и чате, могу предложить сохранять прогресс голосования в локальном хранилище - работа с ним немного понятнее и проще. (Здесь лишь демонстрационный пример учёта голосов и шкалы заполнения. Чтобы использовать сохранение и вывод после обновления страницы, раскомментируйте некоторые участки кода и запустите там, где поддерживается localStorage.)

const LS = /*JSON.parse(localStorage.getItem('counters')) ||*/ {counters:{}};

[...document.querySelectorAll('.picture > img')].forEach((image) => {
  let counter = LS?.counters[image.src];
  if (counter === undefined) {
    LS.counters[image.src] = {count: 0, limit: +(image.dataset['limit'].replace(/[^0-9]/g, ''))};
    image.dataset['count'] = 0;
    image.dataset['limit'] = LS.counters[image.src].limit;
  }
  image.addEventListener('click', fCountInc);
  image.dispatchEvent(new Event('click'));
});

function fCountInc(ev) {
  let counter = this.nextElementSibling;
  let current = LS.counters[this.src];
  if (current.count < current.limit && ev.isTrusted) this.dataset['count'] = current.count += 1;
  if (current.count == current.limit) counter.setAttribute('disabled', true);
  counter.style.setProperty('--progress', 100 / current.limit * current.count + '%');
  counter.textContent = `${current.count.toLocaleString('ru-RU')}/${current.limit.toLocaleString('ru-RU')}`;
  /*localStorage.counters = JSON.stringify(LS);*/
}
body { margin: 0; display: flex; flex-wrap: wrap; justify-content: center; align-content: center; gap: .25em; min-height: 100vh; background: linear-gradient(to right bottom, #17171f, #5a2429) no-repeat; }
.picture {
  position: relative;
  margin: 0;
  padding: 0;
}
.picture > img {
  width: 150px;
  cursor: pointer;
}
.picture > .counter {
  position: absolute;
  top: .5em;
  left: .5em;
  margin: 0;
  padding: .25em;
  border: 3px solid #0000;
  border-radius: 100vh;
  box-sizing: border-box;
  font: bold 16px 'Arial';
  color: #ddd;
  background: 50% 50% / cover linear-gradient(#16141a 0 0) padding-box, 0 0 / var(--progress, 0) 100% linear-gradient(#fc0 0 0) border-box no-repeat, 50% 50% / cover linear-gradient(#1c1a22 0 0) border-box, #0000;
  pointer-events: none;
}
.picture > .counter[disabled] {
  color: #444;
  background:  #fc0;
  transition: 1s ease;
}
<figure class="picture">
  <img src="https://i.sstatic.net/MraLT.jpg" data-limit="10" alt="red wall">
  <p class="counter"></p>
</figure>
<figure class="picture">
  <img src="https://i.sstatic.net/VxVNC.jpg" data-limit="25" alt="yellow flower">
  <p class="counter"></p>
</figure>
<figure class="picture">
  <img src="https://i.sstatic.net/A9VLC.jpg" data-limit="1000" alt="green forest">
  <p class="counter"></p>
</figure>
<figure class="picture">
  <img src="https://i.sstatic.net/oYG0R.jpg" data-limit="1000000" alt="blue rose">
  <p class="counter"></p>
</figure>

Если возникнут вопросы, то задайте их в комментариях к этому ответу.

→ Ссылка