我的目的是让图像在滚动上闪烁 3 次(如亮灯,然后关闭,连续 3 次,延迟 1 秒),然后保持打开状态,直到用户向下滚动超过 3600 像素。
我添加了事件侦听器:
created() {
window.addEventListener('scroll', this.scrollAnimation)
}
在滚动 i 上发射方法scrollAnimation
:
methods: {
scrollAnimation() {
let currentPos = window.pageYOffset
if (currentPos > 3000 && currentPos < 3600) {
this.$refs.supportOff.style.display = 'none'
this.$refs.supportOn.style.display = 'block'
} else {
this.$refs.supportOff.style.display = 'block'
this.$refs.supportOn.style.display = 'none'
}
}
}
这是图像的模板:
<div class="support__image-wrapper">
<img ref="supportOff" class="support__image support__image_on" src="../../assets/images/247-off.png">
<img ref="supportOn" class="support__image support__image_off" src="../../assets/images/247-on.png">
</div>
现在这段代码有效,当我向下滚动 3000 像素但不低于 3600 像素时,它显示 247 打开的图像并隐藏 247 关闭的图像。但是,闪烁它存在一个问题,如果我使用 setInterval
每次用户在 3000 到 3600 像素之间滚动时都会触发它。实现这种闪烁的最佳方法是什么?
尝试一些方法...
- 不要开始用
$ref
操纵 dom
相反,创建一个变量,它将触发 dom 中的更改
methods: {
scrollAnimation() {
this.showSupport = window.pageYOffset > 3000 && window.pageYOffset < 3600
}
}
<div>
<img v-if="showSupport" class="blink" src="../../assets/images/247-on.png">
<img v-else src="../../assets/images/247-off.png">
</div>
- 闪烁我建议使用 css 动画 (
@keyframes
)。这样,您可以控制闪烁的时间,而无需脚本中的任何内容。一旦它在页面上可见,它就会开始闪烁。
.blink {
animation: blink 1s infinite;
}
@keyframes blink {
0% {opacity: 0}
49%{opacity: 0}
50% {opacity: 1}
}
希望这有帮助。
只是想为未来的读者添加一个快速演示,基于 t3__rry 关于未优化/去抖动的基于滚动的事件如何导致严重性能问题的评论; 以及Mulhoon关于使用CSS @keyframes
进行闪烁动画的好建议:
new Vue({
el: '#app',
data() {
return {
blinkRate: 1000,
blinkCount: 3,
blinking: false,
blinkTimeoutId: -1,
state: false,
currentPos: window.pageYOffset
}
},
mounted() {
window.addEventListener('scroll', _.debounce(() => {
this.currentPos = window.pageYOffset;
if (this.currentPos > 3000 && this.currentPos < 3600) {
this.state = true;
}
else {
this.state = false;
}
}), 100);
},
methods: {
blink() {
if (this.blinkTimeoutId > -1) {
clearTimeout(this.blinkTimeoutId);
}
this.blinking = true;
this.blinkTimeoutId = setTimeout(() => {
this.blinking = false;
}, 1000 * this.blinkCount);
}
},
watch: {
state() {
this.blink();
}
}
});
#app {
background-color: gainsboro;
height: 2000vh;
padding: 10px;
}
.page-offset {
position: fixed;
top: 20px;
right: 20px;
}
.blinker > div {
border-radius: 50%;
border: 2px solid white;
color: white;
font-weight: bold;
height: 35px;
left: 20px;
line-height: 35px;
padding: 5px;
position: fixed;
text-align: center;
top: 20px;
vertical-align: middle;
width: 35px;
}
.blinker.animate > div {
animation: blink 1s infinite;
}
.blinker .on {
background-color: green;
}
.blinker .off {
background-color: crimson;
}
@keyframes blink {
0% {
opacity: 0
}
49% {
opacity: 0
}
50% {
opacity: 1
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<div id="app">
<div :class="['blinker', { 'animate': blinking } ]">
<div class="on" v-if="state">ON</div>
<div class="off" v-else>OFF</div>
</div>
<code class="page-offset">pageYOffset: {{Math.floor(currentPos)}}</code>
</div>