我正在寻找数字滚动动画的参考,并发现了以下代码(使用SCSS,因此不会在浏览器中运行):
new Vue({
el: ".app",
data: {
number: 0
},
methods: {
setNumber(e) {
this.number = e.target.value;
}
},
computed: {
numberString() {
return String(this.number).padStart(this.total, "0");
}
},
created() {
this.total = 9;
}
});
* {
margin: 0;
padding: 0;
}
$height: 80px;
html {
height: 100%;
}
body {
font: 16px/1.5 "Helvetica Neue", Helvetica, arial;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.app {
margin: auto;
}
.wrap {
display: flex;
margin: 0 0 20px;
color: #fff;
text-align: center;
font-size: 40px;
}
.item {
flex: 0 0 auto;
margin: 0 10px 0 0;
box-shadow: 0 0 6px #0b415b;
position: relative;
padding: 4px;
border-radius: 4px;
overflow: hidden;
&:before {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient(
to bottom,
#239cc8 49.9%,
#1b6386 50%,
#1b6386 100%
);
}
&:last-child {
margin: 0;
}
&__inner {
position: relative;
background: linear-gradient(
to bottom,
#3fb9d9 49.9%,
#3596ae 50%,
#3596ae 100%
);
width: 50px;
overflow: hidden;
}
&__digit {
transition: 0.3s transform;
line-height: $height;
height: $height;
&-list {
&:before {
display: block;
$content: "";
@for $i from 0 through 9 {
$content: #{$content}#{$i}#{"\A"}#{" "};
}
content: "#{$content}";
}
}
}
}
.range {
width: 100%;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.8/vue.global.min.js"></script>
<div class="app">
<div class="wrap">
<div class="item" v-for="i in total" :key="i">
<div class="item__inner">
<div class="item__digit" :style="{
transform: `translateY(${Number(numberString.charAt(i - 1)) * -100}%)`
}">
<div class="item__digit-list"></div>
</div>
</div>
</div>
</div>
<input type="range" min="0" value="0" :max="10 ** total - 1" @input="setNumber" class="range" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
(Codepen 原文:https://codepen.io/lpjc/pen/MWpMxYa)
我了解 Vue 和 Sass 的基础知识,但对以下两部分感到非常困惑:
<div class="item__digit" :style="{
transform: `translateY(${Number(numberString.charAt(i - 1)) * -100}%)`}">
&-list {
&:before {
display: block;
$content: "";
@for $i from 0 through 9 {
$content: #{$content}#{$i}#{"\A"}#{" "};
}
content: "#{$content}";
}
}
}
}
我尝试搜索官方文档并谷歌搜索相关主题,但很难找到解释此特定案例的相关信息。
i
来自 Vue for
循环。在 Vue 模板中,可以使用元素属性定义循环和其他逻辑,称为 Vue 指令。可以使用指令
for
编写 v-for
循环。在您问题的代码中,循环的最外层元素有 v-for="i in total"
。
<div class="item" v-for="i in total" :key="i">
<div class="item__inner">
<div class="item__digit" :style="{
transform: `translateY(${Number(numberString.charAt(i - 1)) * -100}%)`
}">
<div class="item__digit-list"></div>
</div>
</div>
</div>
现在,在该元素内,
i
变量可用。在常规 JavaScript 中,这就像写作
for ( const i in total ) {
// Can use the i variable in here
}
有关
v-for
指令的更多信息,请参阅 https://vuejs.org/guide/essentials/list
如果您访问 https://www.sassmeister.com/,您可以将 SCSS 渲染为 CSS 以查看它在做什么。您会看到
content
被编译为
content: "0\a 1\a 2\a 3\a 4\a 5\a 6\a 7\a 8\a 9\a ";
(其中
\a
是换行符)。
在 SASS 中,
#{$i}
会将 $i
的值打印到该字符串中。他们没有选择输入 "0\a 1\a 2\a 3\a 4\a 5\a 6\a 7\a 8\a 9\a "
,而是选择编写一个小 @for
循环来完成同样的事情。 @for
循环从 0 计数到 9,并将当前数字附加到字符串中。
实际上,这会创建一个
::before
元素,其中包含从 0 到 9 的数字的垂直列表。该元素的父元素隐藏了溢出的内容,因此一次只能看到一个数字。