0 javascript css jquery animation
我正在尝试制作一种效果,当单击技能图标时,它会进行“冷却”,类似于《魔兽世界》等典型 MMO 中技能的冷却时间。
我找到了下面的代码来实现这样的效果,但它没有记录,我不太理解它,但想对其进行更改。
html:
<table>
<tr>
<td>
<div class="skill"></div>
</td>
<td>
<div class="skill"></div>
</td>
<td>
<div class="skill"></div>
</td>
<td>
<div class="skill"></div>
</td>
<td>
<div class="skill"></div>
</td>
</tr>
</table>
Run Code Online (Sandbox Code Playgroud)
CSS:
.skill {
margin: 0px;
padding: 0px;
position: relative;
border: 1px solid #36393E;
border-radius: 5%;
width: 44px;
height: 44px;
overflow: hidden;
background-color: transparent;
background-image: url("skill.png");
background-repeat: no-repeat;
background-size: 100%;
}
.cooldown {
position: absolute;
opacity: 0.8;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
Run Code Online (Sandbox Code Playgroud)
js:
function cooldown(container, percent) {
var div = $(container);
div.empty();
var total = 100;
if(percent < total) {
var data = [percent, total - percent];
var width = div.width();
var height = div.height();
var cx = width / 2;
var cy = height / 2;
var r = cx * Math.SQRT2;
var colors = [null, '#AAA'];
var svgns = "http://www.w3.org/2000/svg";
var chart = document.createElementNS(svgns, "svg:svg");
chart.setAttribute("width", width);
chart.setAttribute("height", height);
chart.setAttribute("viewBox", "0 0 " + width + " " + height);
var angles = []
for(var i = 0; i < data.length; i++) angles[i] = data[i] / total * Math.PI * 2;
startangle = 0;
for(var i = 0; i < data.length; i++) {
var endangle = startangle + angles[i];
var x1 = cx + r * Math.sin(startangle);
var y1 = cy - r * Math.cos(startangle);
var x2 = cx + r * Math.sin(endangle);
var y2 = cy - r * Math.cos(endangle);
var big = 0;
if (endangle - startangle > Math.PI) big = 1;
var path = document.createElementNS(svgns, "path");
var d = "M " + cx + "," + cy + " L " + x1 + "," + y1 +
" A " + r + "," + r + " 0 " + big + " 1 " +
x2 + "," + y2 + " Z";
path.setAttribute("d", d);
if(colors[i]) {
path.setAttribute("fill", colors[i]);
} else {
path.setAttribute("opacity", 0);
}
chart.appendChild(path);
startangle = endangle;
}
chart.setAttribute('overflow', 'hidden');
div.append(chart);
}
}
$(window).ready(function() {
$('.skill').each(function() {
var skill = $(this);
var div = $('<div />').appendTo(skill).addClass('cooldown');
var radius = div.parent().width() / 2;
skill.click(function() {
$({pct: 0}).animate({pct: 100}, {
duration: 5000,
step: function (curLeft) { cooldown(div, curLeft); }
});
});
});
});
Run Code Online (Sandbox Code Playgroud)
我设法对其进行了一项我想要的更改,即添加带有冷却时间的文本,如下所示:(尚未在 js 中完成更新,但我认为这是我自己可以做的事情)
<div class="skill"><div class="text">5</div></div>
.skill .text {
font-size: 14px;
color: #E1E5EB;
text-shadow: 1px 1px 1px #000000;
line-height: 44px;
text-align: center;
background-color: transparent;
}
Run Code Online (Sandbox Code Playgroud)
我需要帮助的其他更改是:
逆时针而不是顺时针填充。
翻转填充/未填充部分的不透明度(当前填充部分较暗,未填充部分较亮,但我想要相反的情况)
另一种方法是将conic-gradient与一些CSS 变量一起使用。这样我们就不需要构建 SVG。
PS:JS中有注释解释其工作原理。
const SECOND_IN_MS = 1000;
const UPDATE_INTERVAL = SECOND_IN_MS / 60; // Update 60 times per second (60 FPS)
const SKILL_CLASS = 'skill';
const DISABLED_CLASS = 'disabled';
// Cooldowns per skill in milliseconds
const COOLDOWN_MAP = new Map([
['run', 1000],
['jump', 2000],
['crawl', 3000],
['slide', 4000],
['tumble', 5000],
]);
// Get skills table from the DOM
const skillsTable = document.querySelector('.skills-table');
// Activate clicked skill
const activateSkill = (event) => {
const {target} = event;
// Exit if we click on anything that isn't a skill
if(!target.classList.contains(SKILL_CLASS)) return;
target.classList.add(DISABLED_CLASS);
target.style = '--time-left: 100%';
// Get cooldown time
const skill = target.dataset.skill;
let time = COOLDOWN_MAP.get(skill) - UPDATE_INTERVAL;
// Update remaining cooldown
const intervalID = setInterval(() => {
// Pass remaining time in percentage to CSS
const passedTime = time / COOLDOWN_MAP.get(skill) * 100;
target.style = `--time-left: ${passedTime}%`;
// Display time left
target.textContent = (time / SECOND_IN_MS).toFixed(2);
time -= UPDATE_INTERVAL;
// Stop timer when there is no time left
if(time < 0) {
target.textContent = '';
target.style = '';
target.classList.remove(DISABLED_CLASS);
clearInterval(intervalID);
}
}, UPDATE_INTERVAL);
}
// Add click handler to the table
skillsTable.addEventListener('click', activateSkill, false);Run Code Online (Sandbox Code Playgroud)
.skill {
position: relative;
border: 1px solid #36393E;
border-radius: 5%;
width: 44px;
height: 44px;
overflow: hidden;
cursor: pointer;
}
/* Prevents you from clicked the button multiple times */
.skill.disabled {
pointer-events: none;
}
/* Makes sure we click the skill not anything in it */
.skill > * {
pointer-events: none;
}
.skill::before {
content: "";
background: conic-gradient(
rgba(0, 0, 0, 0.7) var(--time-left),
rgba(0, 0, 0, 0.1) var(--time-left));
position: absolute;
opacity: 0.8;
top: 0;
left: 0p;
height: 100%;
width: 100%;
}Run Code Online (Sandbox Code Playgroud)
<table class='skills-table'>
<tr>
<td>
<!-- data-skill refers to the COOLDOWN_MAP in JS -->
<div class="skill" data-skill='run'></div>
</td>
<td>
<!-- data-skill refers to the COOLDOWN_MAP in JS -->
<div class="skill" data-skill='jump'></div>
</td>
<td>
<!-- data-skill refers to the COOLDOWN_MAP in JS -->
<div class="skill" data-skill='crawl'></div>
</td>
<td>
<!-- data-skill refers to the COOLDOWN_MAP in JS -->
<div class="skill" data-skill='slide'></div>
</td>
<td>
<!-- data-skill refers to the COOLDOWN_MAP in JS -->
<div class="skill" data-skill='tumble'></div>
</td>
</tr>
</table>Run Code Online (Sandbox Code Playgroud)