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.mzph.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…