继上一篇,设置弹框次数以及自适应图片弹框,部分机型(vivo)老手机不显示的问题

上一篇写的本来测试好多型号都无事, 今天下午公司的战斗机vivo横空冒出…
晕 弹框直接显示都出不来了,现在还有用这种老的机型的,但是没办法咯~ 前端遇到这种兼容性的问题就要勇于解决
主要解决了这几点:

// 添加图片加载事件
<imgv-if="imageUrl":src="imageUrl"@load="handleImageLoad"@error="handleImageError"@click="handleImgClick"
/>// 图片加载完成后再显示
const handleImageLoad = () => {console.log('图片加载完成');imageLoaded.value = true;showPopup();
};

这确保了只有在图片真正加载完成后才显示弹框,避免了空白或闪烁。

多重渲染保护:

const showPopup = () => {requestAnimationFrame(() => {setTimeout(() => {isVisible.value = true;if (popupRef.value) {popupRef.value.style.transform = 'translateZ(0)';}}, 100);});
};

使用 requestAnimationFrame 和 setTimeout 的组合,确保在浏览器的下一帧渲染时才显示,这解决了 vivo 手机上的渲染时机问题。

显示状态控制:
const isVisible = ref(false);
const imageLoaded = ref(false);

const containerStyle = computed(() => ({
visibility: imageLoaded.value ? ‘visible’ : ‘hidden’
}));
使用独立的状态控制显示,而不是直接依赖数据加载。

硬件加速和性能优化:
.popup-container {
-webkit-transform: translateZ(0);
transform: translateZ(0);
backface-visibility: hidden;
perspective: 1000;
will-change: transform;
}

这些 CSS 属性强制启用硬件加速,提高渲染性能。
成功的关键在于:
正确的渲染时机:等待图片加载完成
可靠的显示控制:使用多重状态检查
性能优化:启用硬件加速
渲染队列:使用 requestAnimationFrame 确保正确的渲染顺序
这解决了 vivo 手机上的几个典型问题:
渲染时机不对导致的白屏
硬件加速缺失导致的显示问题
图片加载时机导致的布局问题
建议在类似场景下:
总是等待资源加载完成
使用多重渲染保护
添加必要的性能优化属性
保持良好的状态管理

<template><Teleport to="body"><div v-show="isVisible" class="popup-container" :style="containerStyle"><div class="popup-content" ref="popupRef"><imgv-if="imageUrl":src="imageUrl"@load="handleImageLoad"@error="handleImageError"@click="handleImgClick"/><div class="close-btn" @click="handleClose">×</div></div></div></Teleport>
</template><script setup>
import { ref, getCurrentInstance, onMounted, computed } from "vue";
import { getAdList, getConfing } from "@/api/base";const app = getCurrentInstance();
const proxy = app?.appContext.config.globalProperties;
const adPosition = proxy?.$global.AD_POSITION_HOME_POPUP;const diaData = ref({});
const currentPopupIndex = ref(0);
const isVisible = ref(false);
const popupRef = ref(null);
const imageLoaded = ref(false);
const maxShowCount = ref(0);const imageUrl = computed(() => {return diaData.value[adPosition]?.[currentPopupIndex.value]?.pic || "";
});const containerStyle = computed(() => ({visibility: imageLoaded.value ? "visible" : "hidden",
}));const handleImageLoad = () => {console.log("图片加载完成===");imageLoaded.value = true;if (checkCanShow()) {showPopup();} else {isVisible.value = false;currentPopupIndex.value = -1;}
};const handleImageError = (error) => {console.error("图片加载失败===", error);imageLoaded.value = false;
};const showPopup = () => {if (!checkCanShow()) {isVisible.value = false;currentPopupIndex.value = -1;return;}requestAnimationFrame(() => {setTimeout(() => {isVisible.value = true;if (popupRef.value) {popupRef.value.style.transform = "translateZ(0)";}}, 100);});
};// 处理图片点击
const handleImgClick = () => {if (diaData.value?.[adPosition]?.[currentPopupIndex.value]) {proxy?.$adRouter(diaData.value[adPosition][currentPopupIndex.value]);}
};// 处理关闭按钮点击
const handleClose = () => {incrementShowCount();// 检查是否达到最大显示次数if (!checkCanShow()) {isVisible.value = false; // 隐藏整个弹框(包括遮罩)currentPopupIndex.value = -1;return;}if (currentPopupIndex.value < diaData.value[adPosition]?.length - 1) {// 切换到下一张前重置状态imageLoaded.value = false;currentPopupIndex.value++;} else {isVisible.value = false;currentPopupIndex.value = -1;}
};const getTodayShowCount = () => {const today = new Date().toDateString();const storageKey = "popupShowCount_" + today;return parseInt(localStorage.getItem(storageKey) || "0");
};const incrementShowCount = () => {const today = new Date().toDateString();const storageKey = "popupShowCount_" + today;const currentCount = getTodayShowCount();localStorage.setItem(storageKey, (currentCount + 1).toString());
};const checkCanShow = () => {const currentCount = getTodayShowCount();return currentCount < maxShowCount.value;
};onMounted(async () => {try {// 先获取配置的最大显示次数const configRes = await getConfing({ key: proxy.$global.ImageDialogCount });maxShowCount.value = parseInt(configRes.data[0].configValue || "0");console.log("最大显示次数:", maxShowCount.value);// 检查是否可以显示if (checkCanShow()) {// 获取广告数据const res = await getAdList({regionType: [adPosition],});if (res.data) {diaData.value = res.data;console.log("广告数据获取成功:", diaData.value);// 确保数据存在if (diaData.value[adPosition]?.length > 0) {currentPopupIndex.value = 0;}}} else {console.log("已达到最大显示次数");}} catch (error) {cconsole.log("err的信息", error);}
});
</script><style lang="scss" scoped>
.popup-container {position: fixed;top: 0;left: 0;right: 0;bottom: 0;width: 100vw;height: 100vh;background: rgba(0, 0, 0, 0.5);display: flex;justify-content: center;align-items: center;z-index: 999;margin: 0;padding: 0;-webkit-transform: translateZ(0);transform: translateZ(0);backface-visibility: hidden;perspective: 1000;will-change: transform;
}.popup-content {position: relative;width: fit-content;margin: auto;-webkit-transform: translateZ(0);transform: translateZ(0);img {display: block;width: 80vw;max-height: 80vh;object-fit: contain;-webkit-touch-callout: none;user-select: none;-webkit-user-select: none;pointer-events: auto;backface-visibility: hidden;-webkit-backface-visibility: hidden;}
}.close-btn {position: absolute;top: -30px;right: 0;width: 30px;height: 30px;background: rgba(255, 255, 255, 0.8);border-radius: 50%;display: flex;justify-content: center;align-items: center;cursor: pointer;font-size: 20px;color: #333;z-index: 1000;-webkit-tap-highlight-color: transparent;&:active {background: #fff;}
}
</style>

完整代码 解决~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/62472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink在Linux系统上的安装与入门

一、Flink的引入 这几年大数据的飞速发展&#xff0c;出现了很多热门的开源社区&#xff0c;其中著名的有Hadoop、Storm&#xff0c;以及后来的Spark&#xff0c;他们都有着各自专注的应用场景。Spark 掀开了内存计算的先河&#xff0c;也以内存为赌注&#xff0c;赢得了内存计…

scanf函数和printf函数的格式化输入输出

#include<stdio.h> int main() {int a;double b;char c;scanf("a%d,b%lf:c%c",&a,&b,&c); //float型输入时使用%f占位&#xff0c;double型使用%lf占位&#xff1b;输出时二者相同都是%f即可。if(a>0)printf("a%-10d,b%20.3lf,c%c",a…

《C++ 中 RNN 及其变体梯度问题的深度剖析与解决之道》

在当今人工智能蓬勃发展的浪潮中&#xff0c;递归神经网络&#xff08;RNN&#xff09;及其变体长短期记忆网络&#xff08;LSTM&#xff09;和门控循环单元&#xff08;GRU&#xff09;在处理序列数据方面展现出了强大的潜力。然而&#xff0c;当我们在 C中着手实现这些网络时…

【大数据学习 | Spark调优篇】Spark之JVM调优

1. Java虚拟机垃圾回收调优的背景 如果在持久化RDD的时候&#xff0c;持久化了大量的数据&#xff0c;那么Java虚拟机的垃圾回收就可能成为一个性能瓶颈。因为Java虚拟机会定期进行垃圾回收&#xff0c;此时就会追踪所有的java对象&#xff0c;并且在垃圾回收时&#xff0c;找…

ffmpeg.js视频播放(转换)

chrome 临时设置SharedArrayBuffer "C:\Program Files\Google\Chrome\Application\chrome.exe" --enable-featuresSharedArrayBuffer 引用的js及相关文件 ffmpeg.min.js ffmpeg.min.js.map ffmpeg-core.js ffmpeg-core.wasm ffmpeg-core.worker.js 以上几个现…

【随笔】AI大模型对软件开发的影响

随着 AI 技术的不断发展&#xff0c;AI大模型正在重塑软件开发流程&#xff0c;从代码自动生成到智能测试&#xff0c;未来&#xff0c;AI 大模型将会对软件开发者、企业&#xff0c;以及整个产业链都产生深远的影响。欢迎探讨 AI 是如何重塑软件开发的各个环节以及带来的新的流…

Java的常识

程序员分类 初级程序员(大学毕业一年以内)大概月薪:2-5K 初中级程序员(工作经验2-3年)大概月薪:6-10K 中级程序员(工作经验4-5年)大概月薪:10-15K 高级程序员(工作经验5++)大概月薪:15K++ 普通公司对于程序员的月薪资天花板25K 工作实景 微信小程序、手机APP、写…

常用的数据结构

队列(FIFO) 栈(LIFO) 链表 hash表 hash冲突处理 开放式寻址 线性探测 表示依次检查索引为 hash(key) + 1、hash(key) + 2 ... 的位置。i 是冲突后的探查步数。公式:hash(i) = (hash(key) + i) % TableSize二次探查 规则:冲突后探查的步长是平方递增的,例如,检查位置为 hash…

SpringSecurity6

1.快速入门 2.SpringSecurity底层原理 使用的是委托过滤器,委托过滤器实际上就是 sevlet 过滤器 将自己放入Sevlet环境下 然后里面是一个 过滤器链代理 代理类下又是一个代理过滤器链的集合, 对于不同请求可以有不同的过滤器链, springsecurity有个默认的过滤器链 Defau…

记 centos9 安装 docker

第一步&#xff1a;安装该dnf-plugins-core软件包&#xff08;它提供了管理 DNF 存储库的命令&#xff09; sudo dnf -y install dnf-plugins-core 第二步&#xff1a;设置存储库(这里使用的是阿里云的镜像源) sudo dnf config-manager --add-repo https://mirrors.aliyun.co…

电磁兼容(EMC):磁性材料(永磁、软磁、功能磁)详解

目录 一、磁性材料概述 二、常用磁性材料分类 1. 永磁材料 2. 软磁材料 3. 功能性磁材 三、软磁材料特点 一、磁性材料概述 磁性材料是指由过渡元素铁&#xff08;Fe&#xff09;、钴&#xff08;Co&#xff09;、镍&#xff08;Ni&#xff09;及其合金等组成的能够直接…

海盗王用golang重写的AccountServer功能

自从用golang重写了海盗王的网关gateserver以来&#xff0c;一直想把accountserver也重写了&#xff0c;但是一直没有进行。 趁上次刚写好那个golang版的更新器&#xff0c;还有些熟悉&#xff0c;于是把原来AccountServer的C代码重写读了个大概。它原版的写得太过于复杂&#…

10个Word自动化办公脚本

在日常工作和学习中&#xff0c;我们常常需要处理Word文档&#xff08;.docx&#xff09;。 Python提供了强大的库&#xff0c;如python-docx&#xff0c;使我们能够轻松地进行文档创建、编辑和格式化等操作。本文将分享10个使用Python编写的Word自动化脚本&#xff0c;帮助新…

详细分析 npm run build 基本知识 | 不同环境不同命令

目录 前言1. 基本知识2. 构建逻辑 前言 关于部署服务器的知识推荐阅读&#xff1a;npm run build部署到云服务器中的Nginx&#xff08;图文配置&#xff09; 1. 基本知识 npm run 是 npm 的一个命令&#xff0c;用于运行 package.json 中定义的脚本&#xff0c;可以通过 “s…

多组输入a+b ||:JAVA

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 计算ab 输入描述: 第一行输入一个数据组数n接下来n行每行输入两个整数 输出描述: 对于每组数据计算ab的值 示例1 输入 2 1 1 2 2 输出 2 4 代码&#xff1a; import java.util.Scan…

【AI日记】24.11.29 kaggle 比赛 Titanic-2 | 鼓励自己

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 核心工作 内容&#xff1a;学习 kaggle 入门比赛 Titanic - Machine Learning from Disaster&#xff0c;学习机器学习课程备注&#xff1a;入门比赛有很多 notebook 适合我这种新手学习&#xff0c;尤其是那…

Leetcode 每日一题 104.二叉树的最大深度

目录 问题描述 示例 示例 1&#xff1a; 示例 2&#xff1a; 约束条件 题解 方法一&#xff1a;广度优先搜索&#xff08;BFS&#xff09; 步骤 代码实现 方法二&#xff1a;递归 步骤 代码实现 结论 问题描述 给定一个二叉树 root&#xff0c;我们需要返回其最大…

数据结构--树二叉树顺序结构存储的二叉树(堆)

前言 前面我们学习了顺序表、链表、栈和队列&#xff0c;这些都是线性的数据结构。今天我们要来学习一种非线性的数据结构——树。 树的概念及结构 树的概念 树是一种非线性的数据结构&#xff0c;是由n&#xff08;n≥0&#xff09;个有效结点组成的一个具有层次关系的集合…

代码随想录第31天

56. 合并区间 class Solution:def merge(self, intervals: List[List[int]]) -> List[List[int]]:intervals.sort(keylambda p: p[0]) # 按照左端点从小到大排序ans []for p in intervals:if ans and p[0] < ans[-1][1]: # 可以合并ans[-1][1] max(ans[-1][1], p[1…

MicroSoft Project2007 安装教程

一、安装教程 访问地址 二、安装链接 通过网盘分享的文件&#xff1a;Project2007CD 链接: https://pan.baidu.com/s/1Y8VnhVPiKjcmAEh8cIR5sQ?pwdp2hk 提取码: p2hk --来自百度网盘超级会员v6的分享