自定义样式
自定义颜色
为了更容易观察填充颜色变化,调大了字体。
0110110440,,055011044
你还可以将下列属性作为文本颜色:
点击查看代码
vue
<script setup>
import { ref } from "vue";
const number = ref(114514);
function switchNumber() {
number.value = Math.floor(Math.random() * 1000000);
}
const color = ref(
"#" +
Math.floor(Math.random() * 16777215)
.toString(16)
.padStart(6, "0")
);
</script>
<template>
<div class="text-center">
<vue-to-counter-number
class="!text-8xl font-bold"
:value="number"
:color="color"
locale-number
/>
</div>
<hr />
<div class="flex gap-4">
<input class="border border-solid p-1" v-model="number" type="number" />
<button class="border border-solid p-1" @click="switchNumber">切换</button>
<span class="flex-auto" />
<input class="border border-solid p-1" v-model="color" type="color" />
</div>
<div class="flex flex-col mt-4">
<div>你还可以将下列属性作为文本颜色:</div>
<ol>
<li>
<label>
<input
type="radio"
name="color"
value="linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)"
v-model="color"
/>
CSS 渐变属性
</label>
</li>
<li>
<label>
<input
type="radio"
name="color"
value="url('https://picsum.photos/400/300')"
v-model="color"
/>
CSS 图片属性(加载图片时会有一段空白时间)
</label>
</li>
<li>
<label>
<input
type="radio"
name="color"
value="linear-gradient(rgba(255, 0, 0, 0.4), rgba(0, 0, 255, 0.4)), url('https://picsum.photos/400/300')"
v-model="color"
/>
CSS 渐变属性 + 图片属性
</label>
</li>
</ol>
</div>
<div class="flex gap-4"></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>自定义字体
可以直接通过设置 CSS 属性来自定义字体的各种属性。
0110110440,,055011044
点击查看代码
vue
<script setup>
import { ref } from "vue";
import GoogleFontPicker from "./GoogleFontPicker.vue";
const number = ref(114514);
function switchNumber() {
number.value = Math.floor(Math.random() * 1000000);
}
const italic = ref(false);
const fontSize = ref(64);
const color = ref(
"#" +
Math.floor(Math.random() * 16777215)
.toString(16)
.padStart(6, "0")
);
const fontFamily = ref("");
</script>
<template>
<div class="text-center">
<vue-to-counter-number
:value="number"
:color="color"
locale-number
:style="{
fontSize: fontSize + 'px',
lineHeight: 1.2,
fontStyle: italic ? 'italic' : 'normal',
fontFamily: fontFamily,
}"
/>
</div>
<hr />
<div class="flex gap-4">
<input class="border border-solid p-1" v-model="number" type="number" />
<button class="border border-solid p-1" @click="switchNumber">切换</button>
<span class="flex-auto" />
<input class="border border-solid p-1" v-model="color" type="color" />
</div>
<div class="flex gap-4 mt-4">
<label class="inline-flex gap-1 border border-solid p-1">
斜体
<input v-model="italic" type="checkbox" />
</label>
<label class="inline-flex gap-1 border border-solid p-1">
字号
<input v-model="fontSize" type="range" min="1" max="128" />
{{ fontSize }}px
</label>
</div>
<div class="flex gap-4 mt-4">
<google-font-picker v-model="fontFamily" />
</div>
</template>
<style scoped></style>vue
<script setup>
import { ref, onMounted, watch, computed } from "vue";
const fonts = ref([]);
const searchQuery = ref("");
const selectedFont = defineModel("modelValue");
const fetchFonts = async () => {
try {
const response = await fetch(
"https://www.googleapis.com/webfonts/v1/webfonts?" +
new URLSearchParams({
key: "AIzaSyBJPgjEPn1iDes5wLzDF-JMEst6QdR4skU",
capability: "WOFF2",
sort: "popularity",
}).toString()
); // Replace with your Google Fonts API key
const data = await response.json();
fonts.value = data.items;
} catch (error) {
console.error("Error fetching fonts:", error);
}
};
const filteredFonts = computed(() => {
if (!searchQuery.value) {
return fonts.value;
}
return fonts.value.filter((font) =>
font.family.toLowerCase().includes(searchQuery.value.toLowerCase())
);
});
const loadFont = (fontName) => {
const link = document.createElement("link");
link.href = `https://fonts.googleapis.com/css2?family=${fontName.replace(/ /g, "+")}&display=swap`;
link.rel = "stylesheet";
document.head.appendChild(link);
};
watch(selectedFont, (newFont) => {
if (newFont) {
loadFont(newFont);
}
});
onMounted(async () => {
await fetchFonts();
selectedFont.value = "Ingrid Darling";
// await nextTick();
// document
// .querySelector(`#${selectedFont.value.replaceAll(" ", "-")}`)
// ?.scrollIntoView();
});
// 自动加载选择框中可见字体的预览menu字体
watch(
filteredFonts,
(newFonts) => {
newFonts.forEach((font) => {
const previewFamily = joinPreviewFamily(font.family);
const fontFace = new FontFace(previewFamily, `url(${font.menu})`, {
display: "swap",
});
document.fonts.add(fontFace);
});
},
{ immediate: true }
);
function joinPreviewFamily(family) {
return [...family.split(" "), "PREVIEW"].join("-");
}
</script>
<template>
<div class="flex-none flex flex-col">
<input
type="text"
v-model="searchQuery"
placeholder="Search for fonts"
class="w-full border border-solid p-1 self-start"
/>
<a
href="https://developers.google.com/fonts"
target="_blank"
class="mt-1 text-xs"
>
Data provided by Google Fonts API
</a>
</div>
<div
class="flex-auto font-list-container border border-solid p-1 overflow-y-scroll h-64"
>
<div
v-for="font in filteredFonts"
:key="font.family"
:id="font.family.replace(' ', '-')"
:style="{ fontFamily: joinPreviewFamily(font.family) }"
class="font-item p-2 cursor-pointer"
:class="{
'bg-gray-200': selectedFont === font.family,
}"
@click="selectedFont = font.family"
>
{{ font.family }}
</div>
</div>
</template>
<style scoped>
.font-list-container {
max-height: 16rem;
}
.font-item:hover {
background-color: #f0f0f0;
}
</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>