React8+taro開發微信小程序,實現lottie動畫

安裝核心依賴

npm install lottie-miniprogram @tarojs/plugin-html --save

修改 Taro 配置 (config/index.js)

const config = {plugins: ['@tarojs/plugin-html',// 其他插件...],mini: {canvas: true,webpackChain(chain) {chain.merge({module: {rule: {'lottie-loader': {test: /\.json$/,use: {loader: 'lottie-miniprogram/webpack-loader',options: {limit: 10240 // 10KB以下文件直接內聯}}}}}})}}
}

app.config.js里添加配置

export default defineAppConfig({// 其他代碼...requiredBackgroundModes: ['canvas'],// 其他代碼...})

封裝組件commonLottie

import React, { useEffect, useRef, useState } from 'react'
import Taro, { createSelectorQuery } from '@tarojs/taro'
import { View, Canvas } from '@tarojs/components'const CommonLottie = React.forwardRef(({animationData,width = 24,height = 24,loop = false,autoplay = true,canvasId = 'lottie-canvas' // 新增動態 ID 支持},ref) => {const canvasRef = useRef(null)const lottieInstance = useRef(null)const animationDuration = useRef(1500) // 固定1秒時長// 暴露方法給父組件React.useImperativeHandle(ref, () => ({play: () => {if (lottieInstance.current) {// 先重置再播放lottieInstance.current.goToAndStop(0, true)lottieInstance.current.play()}},pause: () => lottieInstance.current?.pause()}))const calculateSizes = () => {//   const systemInfo = Taro.getSystemInfoSync()const dpr = 1// 邏輯尺寸 → 物理像素尺寸const physicalWidth = width * dprconst physicalHeight = height * dpr// Lottie 內部使用邏輯單位,需要反向縮放const lottieWidth = width / dprconst lottieHeight = height / dprreturn {physicalWidth,physicalHeight,lottieWidth,lottieHeight,dpr}}// 使用重構后的尺寸配置const { physicalWidth, physicalHeight, lottieWidth, lottieHeight, dpr } =calculateSizes()// 微信小程序專屬初始化邏輯const initWechatCanvas = async () => {try {// 使用 Taro.nextTick 確保 DOM 更新完成await new Promise((resolve) => Taro.nextTick(resolve))// 增加重試次數和間隔let retryCount = 0const MAX_RETRY = 5const getNode = () =>new Promise((resolve, reject) => {createSelectorQuery().select(`#${canvasId}`).fields({ node: true, size: true }).exec((res) => {if (res[0]?.node) resolve(res[0].node)else if (retryCount < MAX_RETRY) {retryCount++setTimeout(() => getNode().then(resolve).catch(reject),200 * retryCount)} else {reject(new Error(`Canvas 節點未找到 (ID: ${canvasId})`))}})})const node = await getNode()//動態加載 Lottieconst Lottie = await import('lottie-miniprogram')// 計算播放速度const originalDuration =((animationData.op - animationData.ip) / animationData.fr) * 1000const playSpeed = originalDuration / animationDuration.current//創建動畫實例lottieInstance.current = Lottie.loadAnimation({canvas: node,renderer: 'canvas',animationData,loop,autoplay,rendererSettings: {context: node.getContext('2d'),dpr: 1,scaleMode: 2, // 1: 按比例填充容器,2: 完全填充preserveAspectRatio: 'xMidYMid meet' // 保持寬高比}})// 新增適配邏輯const animation = lottieInstance.currentanimation.resize(lottieWidth, lottieHeight) // 強制刷新尺寸animation.setSubframe(false) // 關閉子幀優化// 設置播放速度animation.setSpeed(playSpeed)// 自動銷毀// animation.addEventListener('complete', () => {//   animation.destroy()// })} catch (err) {console.error('初始化失敗:', err)}}useEffect(() => {if (process.env.TARO_ENV !== 'weapp') returnif (!animationData) returnconst timer = setTimeout(() => {initWechatCanvas()}, 300) // 增加初始化延遲return () => {clearTimeout(timer)lottieInstance.current?.destroy()}}, [animationData])return (<Viewstyle={{width: `${width}px`,height: `${height}px`,overflow: 'visible',// 修復定位問題position: 'relative'}}><Canvasid={canvasId}canvasId={canvasId} // 必須同時設置 id 和 canvasIdtype="2d"style={{width: `${physicalWidth}px`,height: `${physicalHeight}px`,transform: `translateZ(0)`, // 強制啟用 GPU 加速transformOrigin: '0 0',imageSmoothingQuality: 'high' // 高清渲染}}ref={canvasRef}/></View>)}
)export default CommonLottie

頁面中使用

import { View, Button, Image, Text, WebView } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { useState, useEffect, useRef } from 'react'
import './index.module.less'
import styles from './index.module.less'
import animationData from '@/assets/doc/tab_2_on.json'
import CommonLottie from '@/components/commonLottie'definePageConfig({navigationStyle: 'custom',backgroundColor: '#191919'
})export default function ExperiencePage() {const lottieRef = useRef(null)const play = () => {lottieRef.current.play()console.log(' lottieRef.current', lottieRef.current)}return (<View className={styles['experience-wrap']}><Button onClick={play}>按鈕</Button><CommonLottieref={lottieRef}canvasId={'lottie-canvas-test'}animationData={animationData}width={36}height={24}/></View>)
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/76450.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/76450.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/76450.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

有效壓縮 Hyper-v linux Centos 的虛擬磁盤 VHDX

參考&#xff1a; http://www.360doc.com/content/22/0505/16/67252277_1029878535.shtml VHDX 有個不好的問題就是&#xff0c;如果在里面存放過文件再刪除&#xff0c;那么已經使用過的空間不會壓縮&#xff0c;導致空間一直被占用。那么就需要想辦法壓縮空間。 還有一點&a…

【力扣hot100題】(089)最長有效括號

這題目真是越做越難了。 但其實只是思路很難想到&#xff0c;一旦會了方法就很好做。 但問題就在方法太難想了…… 思路還是只要遍歷一遍數組&#xff0c;維護動態規劃數組記錄截止至目前位置選取該元素的情況下有效括號的最大值。 光是知道這個還不夠&#xff0c;看了答案…

Ajax------免刷新地前后端交互

本文略帶PHP代碼需要在PHP環境下使用 介紹 AJAX (Asynchronous JavaScript and XML) 是一種創建快速動態網頁應用的開發技術&#xff0c;它允許網頁在不重新加載整個頁面的情況下&#xff0c;與服務器交換數據并更新部分網頁內容。例如&#xff0c;在我們做爬蟲的時候發現有些…

Android 中支持舊版 API 的方法(API 30)

Android 中最新依賴庫的版本支持 API 31 及以上版本&#xff0c;若要支持 API30&#xff0c;則對應的依賴庫的版本就需要使用舊版本。 可通過修改模塊級 build.gradle 文件來進行適配。 1、android 標簽的 targetSdk 和 compileSdk 版本號 根據實際目標設備的 android 版本來…

JDBC注入無外網(上):從HertzBeat聊聊SnakeYAML反序列化

上周日聯合Ar3h 師傅一起&#xff0c;在【代碼審計知識星球】里發布了一個Springboot的小挑戰&#xff1a;https://t.zsxq.com/tSBBZ&#xff0c;這個小挑戰的核心目標是在無法連接外網的情況下&#xff0c;如何利用PSQL JDBC注入漏洞。我會分兩篇文章來講講Java安全的不出網利…

QTreeWidget 手動設置選中項后不高亮的問題

當使用Qt編程QTreeWidget setCurrentItem() 方法設置 QTreeWidget 的當前項時&#xff0c;如果發現選中項顯示為灰色而不是高亮狀態&#xff0c;這通常是由以下幾個原因導致的&#xff1a; 方法1. 焦點問題 ? 確保 QTreeWidget 有焦點 ? 解決方案&#xff1a; cpp treeWidge…

javaSE學習(前端基礎知識)

文章目錄 前言一、HTML1、< th >、< tr > 和 < td >標簽&#xff1a;2、< button > 標簽&#xff1a;3、< input type"text" >&#xff1a;4、< br >&#xff1a; 二、CSS1、選擇器2、聲明塊3、常用屬性及值 三、JS1、Vue 實例對…

c# 數據結構 鏈表篇 有關單鏈表的一切

本人能力有限,本文僅作學習交流與參考,如有不足還請斧正 目錄 0.單鏈表好處 0.5.單鏈表分類 1.無虛擬頭節點情況 圖示: 代碼: 頭插/尾插 刪除 搜索 遍歷全部 測試代碼: 全部代碼 2.有尾指針情況 尾插 全部代碼 3.有虛擬頭節點情況 全部代碼 4.循環單鏈表 幾個…

藍橋杯C++組算法知識點整理 · 考前突擊(上)【小白適用】

【背景說明】本文的作者是一名算法競賽小白&#xff0c;在第一次參加藍橋杯之前希望整理一下自己會了哪些算法&#xff0c;于是有了本文的誕生。分享在這里也希望與眾多學子共勉。如果時間允許的話&#xff0c;這一系列會分為上中下三部分和大家見面&#xff0c;祝大家競賽順利…

pipe匿名管道實操(Linux)

管道相關函數 1 pipe 是 Unix/Linux 系統中的一個系統調用&#xff0c;用于創建一個匿名管道 #include <unistd.h> int pipe(int pipefd[2]); 參數說明&#xff1a; pipefd[2]&#xff1a;一個包含兩個整數的數組&#xff0c;用于存儲管道的文件描述符&#xff1a; pi…

centos-stream-9上安裝nvidia驅動和cuda-toolkit

這里寫目錄標題 驅動安裝1. 更新系統2. NVIDIA GPU安裝檢查系統是否安裝了 NVIDIA GPU2.1 首先&#xff0c;使用以下命令更新 DNF 軟件包存儲庫緩存&#xff1a;2.2 安裝編譯 NVIDIA 內核模塊所需的依賴項和構建工具2.3 在 CentOS Stream 9 上添加官方 NVIDIA CUDA 軟件包存儲庫…

LDAP高效數據同步:Syncrepl復制模式實戰指南

#作者&#xff1a;朱雷 文章目錄 一、Syncrepl 復制簡介1.1. 什么是復制模式1.2. 什么是 syncrepl同步復制 二、Ldap環境部署三、配置復制類型3.1. 提供者端配置3.2. 消費者端配置3.3.啟動服務3.4.測試同步是否生效 四、總結 一、Syncrepl 復制簡介 1.1. 什么是復制模式 Ope…

Linux 內核網絡協議棧中的 struct packet_type:以 ip_packet_type 為例

在 Linux 內核的網絡協議棧中,struct packet_type 是一個核心數據結構,用于注冊特定協議類型的數據包處理邏輯。它定義了如何處理特定協議的數據包,并通過協議類型匹配機制實現協議分發。本文將通過分析 ip_packet_type 的定義和作用,深入探討其在網絡協議棧中的重要性。 …

QT Sqlite數據庫-教程001 創建數據庫和表-下

【1】創建帶名稱的數據庫 #include <QtSql/QSqlDatabase> #include <QtSql/QSqlQuery> #include <QtSql/QSqlRecord> QString path QDir::currentPath(); QApplication::addLibraryPath(pathQString("/release/plugins")); QPluginLoader loader…

Cannot find module ‘vue‘ or its corresponding type declarations

在使用vue3vite創建新的工程時&#xff0c;在新增.vue文件時會出現Cannot find module vue這個錯誤。 只需要我們在項目中的.d.ts文件中添加以下代碼即可 declare module *.vue {import { defineComponent } from vue;const component: ReturnType<typeof defineComponent&…

SSRF打靶總結

文章目錄 一. PortSwigger1、本地服務器的基本SSRF2、基本的目標不是漏洞機3、Referer標頭的外帶SSRF4、簡單黑名單的SSRF黑名單繞過思路&#xff1a; 5、重定向的SSRF6. 簡單的白名單SSRF白名單繞過思路&#xff1a; 二、BWAPP1. SSRF 文件包含漏洞 | 內網探測2. XXE -> S…

STL-函數對象

1.函數對象 1.1 概念 重載函數調用操作符的類&#xff0c;其對象被稱為函數對象 函數對象使用重載的&#xff08;&#xff09;時&#xff0c;行為類似函數調用&#xff0c;也成為仿函數 本質&#xff1a;函數對象&#xff08;仿函數&#xff09;是一個類&#xff0c;不是一…

多線程(Java)

注&#xff1a;本文為本人學習過程中的筆記 1.導入 1.進程和線程 我們希望我們的程序可以并發執行以提升效率&#xff0c;此時引入了多進程編程。可是創建進程等操作開銷太大&#xff0c;于是就將進程進一步拆分成線程&#xff0c;減少開銷。進程與進程之間所涉及到的資源是…

在 Dev-C++中編譯運行GUI 程序介紹(三)有趣示例一組

在 Dev-C中編譯運行GUI程序介紹&#xff08;三&#xff09;有趣示例一組 前期見 在 Dev-C中編譯運行GUI 程序介紹&#xff08;一&#xff09;基礎 https://blog.csdn.net/cnds123/article/details/147019078 在 Dev-C中編譯運行GUI 程序介紹&#xff08;二&#xff09;示例&a…

【高校主辦】2025年第四屆信息與通信工程國際會議(JCICE 2025)

重要信息 會議網址&#xff1a;www.jcice.org 會議時間&#xff1a;2025年7月25-27日 召開地點&#xff1a;哈爾濱 截稿時間&#xff1a;2025年6月15日 錄用通知&#xff1a;投稿后2周內 收錄檢索&#xff1a;EI,Scopus 會議簡介 JCICE 2022、JCICE 2023、JCICE 2…