Как сделать счетчик нажатий с прогресс баром и лимитом нажатий?
вот здесь нажали на картинку 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 шт):
Для решения можно использовать подход с двумя элементами
- заполненный
- незаполненный
Расположив их один поверх другого, изменяя ширину можно добиться эффекта прогресса
Например
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"> </p><!-- элемент дублирующий основной счетчик -->
</div>
</div>
</div>
Есть несколько вариантов запомнить данные для последующего вывода и взаимодействия. Но, основываясь на вашей разметке и пожеланиях в комментариях и чате, могу предложить сохранять прогресс голосования в локальном хранилище - работа с ним немного понятнее и проще. (Здесь лишь демонстрационный пример учёта голосов и шкалы заполнения. Чтобы использовать сохранение и вывод после обновления страницы, раскомментируйте некоторые участки кода и запустите там, где поддерживается 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>
Если возникнут вопросы, то задайте их в комментариях к этому ответу.