英文:
Triggering keyframe on mouseEvent
问题
我试图在鼠标悬停事件上触发CSS动画。不幸的是,它不按预期工作。
这是我尝试过的内容。我试图在鼠标悬停时实现与CSS中的关键帧声明相同的运动。
在Firefox + Chrome(移动版)中按预期工作,但在Chrome(PC版)中不起作用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
<g class="crcl">
<circle class="circ" cx="10" cy="50" r="10" fill="blue"></circle>
</g>
</svg>
</div>
</body>
</html>
const element = document.querySelector('.circ');
element.addEventListener('mouseover', function() {
console.log(1);
element.style.animation = "move 1000ms infinite ease-in-out alternate";
});
element.addEventListener('mouseout', function() {
//mouseout triggers automatically following mouseover without provocation
console.log(2);
element.style.animation = "none";
});
.circ {
pointer-events: all;
}
.rect {
pointer-events: none;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
希望这对你有所帮助。
英文:
I am trying to trigger a CSS animation on mouseover event. Sadly, it does not work as desired.
This is what I tried. I am trying to achieve the same motion on mouseover as the keyframe declaration within CSS would.
It works as desired in Firefox +Chrome(mobile) but not in Chrome (PC).
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const element = document.querySelector('.circ');
element.addEventListener('mouseover', function() {
console.log(1);
element.style.animation = "move 1000ms infinite ease-in-out alternate";
});
element.addEventListener('mouseout', function() {
//mouseout triggers automatically following mouseover without provocation
console.log(2);
element.style.animation = "none";
});
<!-- language: lang-css -->
.circ {
pointer-events: all;
}
.rect {
pointer-events: none;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
<g class="crcl">
<circle class="circ" cx="10" cy="50" r="10" fill="blue"></circle>
</g>
</svg>
</div>
</body>
</html>
<!-- end snippet -->
答案1
得分: 0
以下是您要翻译的内容:
"The animation actually works but it constantly resets itself.
The problem: your attaching the event listener to the animated circle.
As this circle will start to move on mouseover it will almost immediately trigger the mouseout event.
You should probably start and stop the animation when hovering the svg or rect instead.
const svg = document.querySelector('svg');
const element = document.querySelector('.circ');
svg.addEventListener('mouseover', function() {
element.style.animation = "move 1000ms infinite ease-in-out alternate";
});
svg.addEventListener('mouseout', function() {
//mouseout triggers automatically following mouseover without provocation
element.style.animation = "none";
});
.circ {
pointer-events: all;
}
.rect {
pointer-events: none;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
<g class="crcl">
<circle class="circ" cx="10" cy="50" r="10" fill="blue"></circle>
</g>
</svg>
</div>
Example2: start animation on hover; stop on click
const svg = document.querySelector("svg");
const circles = document.querySelectorAll(".circ");
circles.forEach((circ) => {
circ.addEventListener("mouseover", (e) => {
let current = e.currentTarget;
current.classList.add("running");
});
});
svg.addEventListener("click", function() {
togglePlayState(circles);
});
function togglePlayState(els) {
els.forEach((el) => {
let style = window.getComputedStyle(el);
if (style.animationPlayState === "running") {
el.classList.add("paused");
el.classList.remove("running");
} else if (el.classList.contains('paused')) {
el.classList.remove("paused");
el.classList.add("running");
}
});
}
.circ {
pointer-events: all;
}
.rect {}
.ani {
animation: move 1000ms infinite ease-in-out alternate;
animation-play-state: paused;
}
.running {
animation-play-state: running;
}
.paused {
animation-play-state: paused;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
<g class="crcl">
<circle class="circ ani" cx="10" cy="50" r="10" fill="blue"></circle>
<circle class="circ ani" cx="10" cy="75" r="10" fill="green"></circle>
</g>
</svg>
</div>
英文:
The animation actually works but it constantly resets itself.
The problem: your attaching the event listener to the animated circle.
As this circle will start to move on mouseover it will almost immediately trigger the mouseout event.
You should probably start and stop the animation when hovering the svg or rect instead.
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
const svg = document.querySelector('svg');
const element = document.querySelector('.circ');
svg.addEventListener('mouseover', function() {
element.style.animation = "move 1000ms infinite ease-in-out alternate";
});
svg.addEventListener('mouseout', function() {
//mouseout triggers automatically following mouseover without provocation
element.style.animation = "none";
});
<!-- language: lang-css -->
.circ {
pointer-events: all;
}
.rect {
pointer-events: none;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<!-- language: lang-html -->
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
<g class="crcl">
<circle class="circ" cx="10" cy="50" r="10" fill="blue"></circle>
</g>
</svg>
</div>
<!-- end snippet -->
Example2: start animation on hover; stop on click
<!-- begin snippet: js hide: true console: false babel: false -->
<!-- language: lang-js -->
const svg = document.querySelector("svg");
const circles = document.querySelectorAll(".circ");
circles.forEach((circ) => {
circ.addEventListener("mouseover", (e) => {
let current = e.currentTarget;
current.classList.add("running");
//current.style.animation = "move 1000ms infinite ease-in-out alternate";
});
});
svg.addEventListener("click", function() {
togglePlayState(circles);
});
function togglePlayState(els) {
els.forEach((el) => {
let style = window.getComputedStyle(el);
if (style.animationPlayState === "running") {
//el.style.animationPlayState = "paused";
el.classList.add("paused");
el.classList.remove("running");
} else if (el.classList.contains('paused')) {
//el.style.animationPlayState = "running";
el.classList.remove("paused");
el.classList.add("running");
}
});
}
<!-- language: lang-css -->
.circ {
pointer-events: all;
}
.rect {}
.ani {
animation: move 1000ms infinite ease-in-out alternate;
animation-play-state: paused;
}
.running {
animation-play-state: running;
}
.paused {
animation-play-state: paused;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<!-- language: lang-html -->
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
<g class="crcl">
<circle class="circ ani" cx="10" cy="50" r="10" fill="blue"></circle>
<circle class="circ ani" cx="10" cy="75" r="10" fill="green"></circle>
</g>
</svg>
</div>
<!-- end snippet -->
答案2
得分: 0
以下是翻译的代码部分:
可以通过在接收“keyframe”元素上叠加与之完全相同的透明元素来实现所需的效果,然后在叠加元素上添加监听器以对底部元素进行编程移动。
例如
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const data = [
[0, 0], //底部用于操作 i=0,叠加用于 i=1
[1, 1],
[2, 2]
];
const svg = d3.select('svg');
const grp =
svg
.append('g')
.classed('all', true);
const circ = grp
.selectAll('g')
.data(data)
.join('g')
.attr('id', (_, i) => i)
.attr('transform', (_, i) => `translate(0 ${20*(i+1)})`)
.selectAll('circle')
.data(function(_, i) {
return data[i]
})
.join('circle')
.attr('id', function(_, i) {
return d3.select(this).node().parentNode.id + i
})
.attr('cx', (_, i) => 20)
.attr('cy', (_, i) => 20)
.attr('r', '5')
.attr('fill', (_, i) => { if (i === 0) { return 'blue' } else { return 'transparent' } }); //底部蓝色,叠加透明
d3.selectAll('svg g.all g circle:nth-of-type(2)').on('mouseover', function(_, i) {
d3.select(
d3.select(this).node().parentElement.firstChild
).style('animation', 'move 1000ms infinite ease-in-out alternate')
})
.on('mouseout', function(_, i) {
d3.select(
d3.select(this).node().parentElement.firstChild
).style('animation', 'none')
})
<!-- language: lang-css -->
#container>svg>g>g>circle:nth-child(1) {
pointer-events: none;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
</svg>
</div>
</body>
<script src="prod.js"></script>
</html>
<!-- end snippet -->
请注意,我已经移除了注释部分以保持简洁。如果您需要任何特定的翻译或更多信息,请随时告诉我。
英文:
It is possible to achieve the desired effect with existing mouseover
and mouseout
by overlaying the exact same transparent element as the recipient keyframe
element. Then add a listener on the overlaid element to program the movement on the bottom element.
Such as
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const data = [
[0, 0], //bottom for action i=0, top for overlaying i=1
[1, 1],
[2, 2]
];
const svg = d3.select('svg');
const grp =
svg
.append('g')
.classed('all', true);
const circ = grp
.selectAll('g')
.data(data)
.join('g')
.attr('id', (_, i) => i)
.attr('transform', (_, i) => `translate(0 ${20*(i+1)})`)
.selectAll('circle')
.data(function(_, i) {
return data[i]
})
.join('circle')
.attr('id', function(_, i) {
return d3.select(this).node().parentNode.id + i
})
.attr('cx', (_, i) => 20)
.attr('cy', (_, i) => 20)
.attr('r', '5')
.attr('fill', (_, i) => { if (i === 0) { return 'blue' } else { return 'transparent' } }); //bottom blue, overlay transparent
d3.selectAll('svg g.all g circle:nth-of-type(2)').on('mouseover', function(_, i) {
d3.select(
d3.select(this).node().parentElement.firstChild
).style('animation', 'move 1000ms infinite ease-in-out alternate')
})
.on('mouseout', function(_, i) {
d3.select(
d3.select(this).node().parentElement.firstChild
).style('animation', 'none')
})
<!-- language: lang-css -->
#container>svg>g>g>circle:nth-child(1) {
pointer-events: none;
}
@keyframes move {
0% {
transform: translateX(0);
}
100% {
transform: translateX(500px);
}
}
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div id="container" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 100">
<rect x="0" y="0" width="530" height="200" fill="#EFEFEF"></rect>
</svg>
</div>
</body>
<script src="prod.js"></script>
</html>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论