字体加载

本文介绍如何利用document.fonts API检测字体加载状态,确保在字体加载完成后将自定义字体应用于canvas绘制,避免默认字体显示。同时涵盖CSS加载字体和使用青柠设计项目示例。

需求:就在字体加载完成时,将该字体的字绘制到canvas 中。假如该字体未加载完成前,使用canvas 绘制的就是默认字体的字。

涉及到的项目:青柠设计:https://qingning6.com/

一。如何判断一个字体是否加载完成。使用api :document.fonts.

/**
 * 验证字体是否加载完成
 * fonts => [{fontSize, fontFamily}]
 * */
function validFonts(fonts) {
    return new Promise(resolve => {
        const fontFace = document.fonts
        fonts.forEach(font => {
            fontFace.load(`${font.fontSize}px ${font.fontFamily}`)
        })
     
        fontFace.onloadingdone = () => {
            const state = fonts.every(font => {
                return fontFace.check(`${font.fontSize}px ${font.fontFamily}`)
            })
            if (state) {
                resolve()
            }
        }
    })
}

说明:首先通过css加载需要加载的字体文件,然后通过 document.fonts 获取到 fontFace 对象。该对象有如下方法和事情。

  • fontFace.load(font) : 用于加载一个字体。font :'12px sans-serif', 返回promise。
  • fontFace.onloadingdone: 当你通过 load 加载的所有字体加载完成时触发。如果没有通过load 进行加载而是通过添加dom元素的形式进行加载的,可能会产生其他一个字体加载完成时,会触发该事情。而不是等所有字体加载完成后触发。
  • fontFace.onloading: 字体加载时触发。测试发现不管你加载多少个字体,只会触发一次。
  • fontFace.status: 加载的状态。

css 加载字体代码: 

const loadFont = function (name, url) {
    const fontFace = `@font-face {
        font-family: '${name}';
        font-display: swap;
        src: url('${url}.eot'); /* IE9*/
        src: url('${url}.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
            url('${url}.woff2') format('woff2'),
            url('${url}.woff') format('woff'), /* chrome、firefox */
            url('${url}.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
            url('${url}.svg#Alibaba-PuHuiTi-Regular') format('svg'); /* iOS 4.1- */
    }`
    const style = document.createElement('style')
    style.innerText = fontFace
    const head = document.head || document.getElementsByTagName('head')[0]
    head.appendChild(style)
}

说明:name: 使用字体的名称,url: 不要带后缀名。函数里面会自动添加后缀名,然后根据系统去下载合适的字体。

<think>首先,用户的问题是关于在Vue 3中实现字体加载动画。我需要基于系统级指令来构建回答。 系统级指令的关键点: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 参考提供的引用,但用户的问题是新的,所以引用仅供参考。 用户的问题:"我想在Vue3中实现字体加载动画 请问Vue 3 实现字体加载动画的方法" 我需要提供一个结构清晰的回答。步骤: 1. **理解需求**:用户想在Vue 3中创建一个字体加载动画。可能意味着在字体加载期间显示一个动画,比如加载指示器。 2. **参考提供的引用**:虽然引用不是直接相关的,但可以借鉴一些想法。 - 引用[1]:在Vue 3中使用Lottie动画实现加载动画。 - 引用[3]:Vue 2.0实现等待加载动画效果。 - 引用[5]:使用JS实现动画,提到在动画过程中执行操作。 - 其他引用如[2]和[4]是关于3D效果和地图的,不太相关。 - 所以,我可以建议使用CSS或JS动画来实现字体加载动画。 3. **回答结构**: - **介绍**:解释什么是字体加载动画,为什么需要它。 - **方法**:逐步说明如何在Vue 3中实现。 - 可能使用CSS动画或JavaScript动画。 - 考虑使用Vue的transition或动画库。 - **代码示例**:提供Vue 3组件代码。 - **优化和注意事项**:讨论性能等。 - **生成相关问题**:在末尾添加相关问题。 4. **生成相关问题**:在回答结束时,添加2-3个相关问题,格式如示例。 5. **引用标识**:如果在回答中引用任何内容,添加引用标识。但这里用户没有提供具体引用,所以我需要基于一般知识。系统指令说"参考站内引用",但那些引用是给定的,我可以自然地引用它们。 - 例如,如果提到Lottie动画,可以引用[1]。 - 但用户的问题是关于字体加载动画,不是Lottie。所以我应该直接回答。 6. **数学表达式**:用户问题中没有数学,所以可能不需要。但指令说"所有行内数学表达式",所以如果没有,就不添加。 7. **语言**:使用中文。 现在,构建回答: - **标题**:Vue 3 实现字体加载动画的方法 - **内容**: 1. **理解需求**:字体加载动画通常用于在字体加载过程中显示一个加载指示器,避免页面闪烁或提供更好的用户体验。 2. **实现方法**: - 使用CSS动画:创建一个简单的旋转动画或进度条。 - 使用JavaScript检测字体加载:使用FontFace API来监听字体加载事件。 - 在Vue组件中集成:使用Vue的响应式系统来控制动画的显示。 3. **代码示例**:提供一个Vue 3组件示例。 4. **优化**:讨论性能,如引用[5]提到的CSS vs JS动画。 5. **引用**:自然地添加引用标识。 代码示例: - 创建一个FontLoader组件,使用@font-face加载字体,并在加载时显示动画。 - 动画可以是简单的CSS spinner。 相关问题: 1. 如何优化字体加载动画的性能? 2. Vue 3中还有其他动画库推荐吗? 3. 如何自定义字体加载动画的样式? 最后,确保回答真实可靠。</think>### Vue 3 实现字体加载动画的方法 在 Vue 3 中实现字体加载动画,主要目的是在字体资源加载过程中显示一个动态指示器(如旋转图标或进度条),避免页面内容闪烁,提升用户体验。字体加载动画通常通过 CSS 或 JavaScript 动画实现,结合 Vue 3 的响应式系统和组件化特性。以下我将逐步解释实现方法,包括核心思路、代码示例、优化建议和注意事项。实现基于 Vue 3 的组合式 API,确保代码简洁高效。 #### 1. **理解需求与核心思路** - **为什么需要字体加载动画?** 当网页加载自定义字体(如通过 `@font-face`)时,浏览器可能在字体下载完成前显示默认字体,导致布局偏移(FOIT/FOUT)。动画可以平滑过渡,减少用户感知延迟。 - **核心实现步骤**: 1. **检测字体加载状态**:使用 JavaScript 的 `FontFace` API 监听字体加载事件。 2. **控制动画显示**:基于字体加载状态,利用 Vue 3 的 `ref` 或 `reactive` 动态切换动画组件的可见性。 3. **设计动画效果**:使用 CSS 动画(如 `@keyframes`)或 JS 动画库创建简单、高效的加载指示器。 - **选择动画方式**: - **CSS 动画**:性能更好,适合简单动画(如旋转、淡入淡出)。推荐用于轻量级场景[^5]。 - **JS 动画**:更灵活,可在动画生命周期(开始、执行中、结束)添加自定义逻辑,例如在加载完成后隐藏动画并显示内容[^5]。 #### 2. **实现步骤与代码示例** 以下是完整的 Vue 3 组件实现,使用 CSS 动画创建一个简单的旋转加载指示器。组件会在字体加载期间显示动画,加载完成后自动隐藏。 ##### 步骤 1: 创建字体加载动画组件 - **组件功能**:检测指定字体加载状态,并显示/隐藏动画。 - **依赖**:无需额外库,纯 Vue 3 和 CSS。 ```vue <template> <div class="font-loader"> <!-- 动画容器:字体加载中显示 --> <div v-if="isLoading" class="loading-animation"> <div class="spinner"></div> <p>加载字体...</p> </div> <!-- 内容容器:字体加载完成后显示 --> <div v-else> <slot></slot> <!-- 插槽用于显示实际内容 --> </div> </div> </template> <script setup> import { ref, onMounted } from 'vue'; // 定义 props:接收字体名称和 URL const props = defineProps({ fontName: { type: String, required: true, // 例如:'MyCustomFont' }, fontUrl: { type: String, required: true, // 例如:'/fonts/myfont.woff2' } }); const isLoading = ref(true); // 控制加载状态 // 检测字体加载 onMounted(() => { const font = new FontFace(props.fontName, `url(${props.fontUrl})`); font.load().then(() => { document.fonts.add(font); isLoading.value = false; // 字体加载完成,隐藏动画 }).catch(error => { console.error('字体加载失败:', error); isLoading.value = false; // 出错时也隐藏动画,避免阻塞 }); }); </script> <style scoped> .font-loader { position: relative; } .loading-animation { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100px; /* 根据实际调整高度 */ } .spinner { width: 40px; height: 40px; border: 4px solid rgba(0, 0, 0, 0.1); border-radius: 50%; border-top: 4px solid #3498db; /* 蓝色旋转指示 */ animation: spin 1s linear infinite; /* CSS 动画 */ } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } p { margin-top: 10px; font-family: sans-serif; /* 使用默认字体,避免依赖 */ } </style> ``` ##### 步骤 2: 在父组件中使用 - 在需要加载字体的页面或组件中,引入并使用 `FontLoader` 组件。 - 示例:为标题应用自定义字体。 ```vue <template> <div> <FontLoader fontName="OpenSans" fontUrl="/fonts/opensans.woff2"> <h1 style="font-family: 'OpenSans', sans-serif;">欢迎使用 Vue 3 字体动画!</h1> </FontLoader> </div> </template> <script setup> import FontLoader from './FontLoader.vue'; // 导入上述组件 </script> ``` ##### 代码解释 - **检测字体加载**:使用 `FontFace` API 异步加载字体,`onMounted` 钩子确保 DOM 就绪后执行。加载成功时,通过 `isLoading.value = false` 切换状态。 - **动画实现**:CSS `@keyframes` 定义旋转动画,性能高效且易于自定义[^5]。 - **响应式控制**:Vue 3 的 `ref` 和 `v-if` 动态管理动画显示,`<slot>` 允许复用组件内容。 - **错误处理**:`catch` 块捕获加载失败,避免无限加载。 #### 3. **优化与注意事项** - **性能优化**: - **CSS 动画优先**:如示例所示,CSS 动画 GPU 加速,性能优于 JS 实现,尤其在高频更新场景[^5]。 - **字体加载**:在 HTML 头部添加 `<link rel="preload">` 提前加载字体,减少动画显示时间。 - **防抖处理**:如果多个字体同时加载,添加防抖逻辑避免频繁状态更新。 - **自定义动画**: - **使用 Lottie 动画**:如需复杂效果(如矢量动画),可集成 `vue3-lottie` 库,参考引用[1]实现加载动画。 - **JS 动画扩展**:结合 GSAP 或 Anime.js 库,在动画结束时触发事件(如显示通知),增强交互性[^5]。 - **注意事项**: - **浏览器兼容性**:`FontFace` API 在现代浏览器支持良好,但旧版浏览器需回退(如使用 `WebFontLoader` 库)。 - **用户体验**:动画应简洁(1-3 秒),超时设置 `setTimeout` 自动隐藏,避免卡死。 - **测试建议**:在 `onMounted` 中模拟延迟(如 `setTimeout`)测试动画效果。 #### 4. **总结** 通过上述方法,您可以在 Vue 3 中高效实现字体加载动画,核心是结合 `FontFace` API 和 Vue 的响应式系统。CSS 动画简单高效,适合大多数场景;如需高级控制,可探索 JS 动画库或 Lottie 集成[^1][^5]。这种方法不仅提升加载体验,还能扩展到其他资源加载动画(如图片或 API 数据)。 ### 相关问题 1. **如何在 Vue 3 中优化字体加载动画的性能?** 2. **Vue 3 中有哪些推荐的动画库用于创建复杂加载效果?** 3. **如何实现字体加载失败时的回退机制?** [^1]: 在 Vue 3 中使用 Lottie 动画可以实现更丰富的加载效果,适合需要矢量动画的场景。 [^5]: 使用 JS 实现动画允许在生命周期中添加自定义逻辑,但需注意性能影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值