简单的滚动效果
VueToCounter 提供了下列组件,他们用于滚动不同类型的数据:
- VueToNumber:
number
,bigint
- VueToDatetimeDuration:
Date
- VueToString:
string
仅使用默认的配置,即可获得一个看起来不错的滚动效果。
TIP
点击 按钮,观察数值的改变。
使数字滚动
想像一下,现实生活中的水表,它会不断地滚动,显示当前的用水量。VueToCounter 可以帮助你实现这样的效果。
![水表](/assets/Water_meter_register.EttztuEZ.jpg)
011011044055011044
点击查看代码
vue
<script setup>
import { ref } from "vue";
const number = ref(114514);
function switchNumber() {
number.value = Math.floor(Math.random() * 1000000);
}
</script>
<template>
<div class="text-center">
<vue-to-counter-number :value="number" />
</div>
<hr />
<div class="flex gap-4">
<input class="border border-solid p-1" v-model="number" />
<button class="border border-solid p-1" @click="switchNumber">切换</button>
</div>
</template>
<style scoped></style>
vue
<script setup>
import StackblitzLogo from "../assets/stackblitz-logo.svg";
import { ref, toRefs } from "vue";
import { getCodeStackblitzParams } from "./generate-stackblitz-params";
import sdk from "@stackblitz/sdk";
import packageInfo from "../../vue-to-counter/package.json";
const props = defineProps({
title: {
type: String,
required: true,
},
});
const { title } = toRefs(props);
const containerRef = ref();
function handleStackblitz() {
if (!containerRef.value) return;
const tabs = containerRef.value.querySelectorAll(".tabs > label");
const blocks = containerRef.value.querySelectorAll(".blocks > div code");
if (tabs.length !== blocks.length) {
window.alert("The number of tabs and code blocks should be the same.");
return;
}
const files = Array.from(tabs).map((tab, index) => ({
filename: tab.textContent.trim(),
content: blocks[index].textContent,
}));
const params = getCodeStackblitzParams(files, {
title: `${title.value} - vue-to-counter@${packageInfo.version}`,
});
sdk.openProject(params, {
openFile: "src/demo.vue",
});
}
</script>
<template>
<div ref="containerRef" class="demo-container">
<div class="flex relative">
<span class="flex-auto" />
<span
title="Open In Stackblitz"
class="inline-block p-1 cursor-pointer hover:outline hover:outline-[#1389FD] outline-1"
@click="handleStackblitz"
>
<img
class="h-4 w-4 pointer-events-none"
:src="StackblitzLogo"
alt="CodeSandbox Logo"
/>
</span>
</div>
<hr />
<slot />
</div>
</template>
<style lang="scss">
.demo-container {
@apply flex flex-col justify-center border p-4 rounded-lg mt-4 text-sm;
.vue-to-counter {
@apply font-mono text-4xl;
}
.custom-block {
@apply m-0;
}
}
</style>
倒计时效果
我相信你已经见过很多的倒计时,但大部分的变化是生硬的,没有过渡。VueToCounter 可以让你的倒计时效果更加平滑。
~
点击查看代码
vue
<script setup>
import { ref } from "vue";
import { DurationPartType } from "vue-to-counter";
const from = ref("2024-12-01T00:00:00");
const to = ref("2024-12-31T00:05:30");
function switchDatetime() {
[from.value, to.value] = [to.value, from.value];
}
const precision = ref(DurationPartType.Second);
</script>
<template>
<div class="text-center">
<vue-to-counter-datetime-duration
:value="[from, to]"
:precision="precision"
/>
</div>
<hr />
<div class="flex gap-4">
<div>
<input
class="border border-solid p-1"
v-model="from"
type="datetime-local"
/>
~
<input
class="border border-solid p-1"
v-model="to"
type="datetime-local"
/>
</div>
<button class="border border-solid p-1" @click="switchDatetime">
切换
</button>
</div>
<div class="flex gap-4 mt-4">
<label>
时间范围精度
<select
class="border border-solid p-1 appearance-auto"
v-model="precision"
>
<option
v-for="precision in [
DurationPartType.Year,
DurationPartType.Month,
DurationPartType.Day,
DurationPartType.Hour,
DurationPartType.Minute,
DurationPartType.Second,
]"
:key="precision"
:value="precision"
>
{{ precision }}
</option>
</select>
</label>
</div>
</template>
<style scoped></style>
vue
<script setup>
import StackblitzLogo from "../assets/stackblitz-logo.svg";
import { ref, toRefs } from "vue";
import { getCodeStackblitzParams } from "./generate-stackblitz-params";
import sdk from "@stackblitz/sdk";
import packageInfo from "../../vue-to-counter/package.json";
const props = defineProps({
title: {
type: String,
required: true,
},
});
const { title } = toRefs(props);
const containerRef = ref();
function handleStackblitz() {
if (!containerRef.value) return;
const tabs = containerRef.value.querySelectorAll(".tabs > label");
const blocks = containerRef.value.querySelectorAll(".blocks > div code");
if (tabs.length !== blocks.length) {
window.alert("The number of tabs and code blocks should be the same.");
return;
}
const files = Array.from(tabs).map((tab, index) => ({
filename: tab.textContent.trim(),
content: blocks[index].textContent,
}));
const params = getCodeStackblitzParams(files, {
title: `${title.value} - vue-to-counter@${packageInfo.version}`,
});
sdk.openProject(params, {
openFile: "src/demo.vue",
});
}
</script>
<template>
<div ref="containerRef" class="demo-container">
<div class="flex relative">
<span class="flex-auto" />
<span
title="Open In Stackblitz"
class="inline-block p-1 cursor-pointer hover:outline hover:outline-[#1389FD] outline-1"
@click="handleStackblitz"
>
<img
class="h-4 w-4 pointer-events-none"
:src="StackblitzLogo"
alt="CodeSandbox Logo"
/>
</span>
</div>
<hr />
<slot />
</div>
</template>
<style lang="scss">
.demo-container {
@apply flex flex-col justify-center border p-4 rounded-lg mt-4 text-sm;
.vue-to-counter {
@apply font-mono text-4xl;
}
.custom-block {
@apply m-0;
}
}
</style>
字符串也可以滚动
看到首页上那个会动的标题了吗?在静态网页上,这样的效果会让你的页面更加生动。
TIP
请注意,默认配置下最长支持 17 个字符。如果你需要更多的字符长度,请参阅如何解除字符长度限制。
0HH0ee0ll0ll0oo0,,0 0WW0oo0rr0ll0dd0!!
点击查看代码
vue
<script setup>
import { ref } from "vue";
const string = ref("Hello, World!");
const strings = [
"Hello, World!",
"你好,世界!",
"こんにちは、世界!",
"안녕하세요, 세계!",
// 太长了
// "Bonjour, le monde!",
"Hallo, Welt!",
"Ciao, mondo!",
"Olá, mundo!",
"Привет, мир!",
"¡Hola, mundo!",
"Hej, världen!",
"Merhaba, Dünya!",
"مرحبا بالعالم!",
"שלום, עולם!",
"नमस्ते, दुनिया!",
"سلام دنیا!",
];
let stringIndex = 0;
function switchString() {
stringIndex = (stringIndex + 1) % strings.length;
string.value = strings[stringIndex];
}
</script>
<template>
<div class="text-center">
<vue-to-counter-string :value="string" />
</div>
<hr />
<div class="flex gap-4">
<input class="border border-solid p-1" v-model="string" />
<button class="border border-solid p-1" @click="switchString">切换</button>
</div>
</template>
<style scoped></style>
vue
<script setup>
import StackblitzLogo from "../assets/stackblitz-logo.svg";
import { ref, toRefs } from "vue";
import { getCodeStackblitzParams } from "./generate-stackblitz-params";
import sdk from "@stackblitz/sdk";
import packageInfo from "../../vue-to-counter/package.json";
const props = defineProps({
title: {
type: String,
required: true,
},
});
const { title } = toRefs(props);
const containerRef = ref();
function handleStackblitz() {
if (!containerRef.value) return;
const tabs = containerRef.value.querySelectorAll(".tabs > label");
const blocks = containerRef.value.querySelectorAll(".blocks > div code");
if (tabs.length !== blocks.length) {
window.alert("The number of tabs and code blocks should be the same.");
return;
}
const files = Array.from(tabs).map((tab, index) => ({
filename: tab.textContent.trim(),
content: blocks[index].textContent,
}));
const params = getCodeStackblitzParams(files, {
title: `${title.value} - vue-to-counter@${packageInfo.version}`,
});
sdk.openProject(params, {
openFile: "src/demo.vue",
});
}
</script>
<template>
<div ref="containerRef" class="demo-container">
<div class="flex relative">
<span class="flex-auto" />
<span
title="Open In Stackblitz"
class="inline-block p-1 cursor-pointer hover:outline hover:outline-[#1389FD] outline-1"
@click="handleStackblitz"
>
<img
class="h-4 w-4 pointer-events-none"
:src="StackblitzLogo"
alt="CodeSandbox Logo"
/>
</span>
</div>
<hr />
<slot />
</div>
</template>
<style lang="scss">
.demo-container {
@apply flex flex-col justify-center border p-4 rounded-lg mt-4 text-sm;
.vue-to-counter {
@apply font-mono text-4xl;
}
.custom-block {
@apply m-0;
}
}
</style>