ios 中使用 animation-play-state: paused 属性失效的问题

本文详细解析了在iOS设备上使用CSS3动画时遇到的暂停动画消失问题,并提供了解决方案。通过调整关键帧动画的transform属性,确保动画在暂停状态下的稳定性。

前言

因为要做一个播放器的播放图片旋转动画,像这样子
在这里插入图片描述
当音乐播放就转动,停止就暂停。

开始

于是很自然地想到了使用Css3的 animation 动画属性
CSS3 animation(动画) 属性

  • animation-name 指定要绑定到选择器的关键帧的名称
  • animation-duration 动画指定需要多少秒或毫秒完成
  • animation-timing-function 设置动画将如何完成一个周期
  • animation-delay 设置动画在启动前的延迟间隔。
  • animation-iteration-count 定义动画的播放次数。
  • animation-direction 指定是否应该轮流反向播放动画。
  • animation-fill-mode 规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。
  • animation-play-state 指定动画是否正在运行或已暂停。
    刚开始我是这样写的
<img
   v-if="playerInfo.singerPic"
   :src="playerInfo.singerPic"
   :class="[
     'play_photo',
     { rotate_animation: isPlayBarShow },
     { animation_paused: !isPlaying },
     { animation_play: isPlaying }
   ]"/>
@keyframes rotate_img {
  0% {
    transform: translate(-50%, -50%) scale(0.9) rotate(0deg);
  }
  100% {
    transform: translate(-50%, -50%) scale(0.9) rotate(360deg);
  }
}

.rotate_animation {
  animation: rotate_img 10s linear infinite;
}
.animation_paused {
  animation-play-state: paused;
}
.animation_play {
  animation-play-state: running;
}

.play_photo {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: -1;
  }

问题

在 chrome 里调试没有任何问题,但是真机测试时,出现bug:

  1. IOS 浏览器中音乐点击暂停,动画直接消失,图片跟没有添加 animation 一样, 直接现出原形,再点播放,动画从刚刚停止的位置继续。这样的体验很不好。
  2. android 正常。

分析解决

刚开始我怀疑 IOS 系统是不是不支持 animation-play-state: paused 这个属性,但是查阅了一番资料之后,又重新修改了一下代码,主要是 Css,如下:

@keyframes rotate_img {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.rotate_animation {
  animation: rotate_img 10s linear infinite normal both;
}
.animation_paused {
  animation-play-state: paused;
}
.animation_play {
  animation-play-state: running;
}

.play_photo {
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 50%;
    position: absolute;
    top: calc(50% - 0.35rem);
    left: calc(50% - 0.35rem);
    z-index: -1;
  }

结论

在使用 animation 的 @keyframes 里声明动画的 transform 属性时,尽量减少不变动的属性,否则会出现意想不到的bug。

如果这篇文章对你有帮助的话,点个赞吧,谢谢~
<template> <view class="tui-notice-vertical" :style="{width:width?width+&#39;rpx&#39;:&#39;100%&#39;,height:scrollHeight+&#39;px&#39;,background:background,padding:padding,borderRadius:radius+&#39;rpx&#39;}"> <view :id="elId_box" class="tui-seamless__scroll-outer"> <view :id="elId" class="tui-seamless__scroll-box" :style="{paddingTop:scrollHeight+&#39;px&#39;, &#39;animationDuration&#39;: animationDuration,&#39;-webkit-animationDuration&#39;: animationDuration,animationPlayState: webviewHide?&#39;paused&#39;:animationPlayState,&#39;-webkit-animationPlayState&#39;:webviewHide?&#39;paused&#39;:animationPlayState, animationDelay: animationDelay, &#39;-webkit-animationDelay&#39;:animationDelay}"> <slot></slot> </view> </view> </view> </template> <script> export default { name: "tui-notice-vertical", props: { //滚动容器宽度 rpx ,0 则使用屏幕宽度 width: { type: [Number, String], default: 0 }, //滚动容器高度 rpx height: { type: [Number, String], default: 400 }, background: { type: String, default: &#39;transparent&#39; }, radius: { type: [Number, String], default: 0 }, padding: { type: String, default: &#39;0&#39; }, //每秒滚动速度(距离) 默认 20px/s speed: { type: [Number, String], default: 20 }, //backwards: 动画从头开始播;forwards:动画从结束点开始播 activeMode: { type: String, default: &#39;backwards&#39; } }, watch: { height(val) { this.scrollHeight = uni.upx2px(Number(val) || 600) } }, data() { const elId = `tui_${Math.ceil(Math.random() * 10e5).toString(36)}` const elId_box = `tui_${Math.ceil(Math.random() * 10e5).toString(36)}` return { elId, elId_box, webviewHide: false, boxHeight: 0, contentHeight: 0, scrollHeight: 0, animationDuration: &#39;none&#39;, animationPlayState: &#39;paused&#39;, animationDelay: &#39;0s&#39; }; }, created() { this.scrollHeight = uni.upx2px(Number(this.height) || 600) }, mounted() { // #ifdef APP-PLUS let pages = getCurrentPages(); let page = pages[pages.length - 1]; let currentWebview = page.$getAppWebview(); currentWebview.addEventListener(&#39;hide&#39;, () => { this.webviewHide = true }) currentWebview.addEventListener(&#39;show&#39;, () => { this.webviewHide = false }) // #endif this.$nextTick(() => { setTimeout(() => { this.initAnimation() }, 50) }) }, methods: { initAnimation() { let query = [], boxHeight = 0, contentHeight = 0; let noticeQuery = new Promise((resolve, reject) => { uni.createSelectorQuery() // #ifndef MP-ALIPAY .in(this) // #endif .select(`#${this.elId}`) .boundingClientRect() .exec(ret => { this.contentHeight = ret[0].height resolve() }) }) if (this.activeMode === &#39;forwards&#39;) { let boxQuery = new Promise((resolve, reject) => { uni.createSelectorQuery() // #ifndef MP-ALIPAY .in(this) // #endif .select(`#${this.elId_box}`) .boundingClientRect() .exec(ret => { this.boxHeight = ret[0].height resolve() }) }) query.push(boxQuery) } query.push(noticeQuery) Promise.all(query).then(() => { this.animationDuration = `${this.contentHeight /(Number(this.speed) || 20)}s` if (this.activeMode === &#39;forwards&#39;) { this.animationDelay = `-${this.boxHeight / (Number(this.speed) || 20)}s` } setTimeout(() => { this.animationPlayState = &#39;running&#39; }, 1000) }) } } } </script> <style scoped> .tui-notice-vertical { width: 100%; position: relative; box-sizing: border-box; overflow: hidden; display: flex; flex-direction: column; z-index: 2; } .tui-seamless__scroll-outer { width: 100%; flex: 1; overflow: hidden; } .tui-seamless__scroll-box { width: 100%; position: absolute; left: 0; top: 0; word-break: break-all; white-space: pre-wrap; animation: notice 10s 0s linear infinite both; animation-play-state: paused; -webkit-backface-visibility: hidden; -webkit-perspective: 1000; } @keyframes notice { 100% { transform: translate3d(0, -100%, 0); } } </style>这段代码是uniapp的一个滚动组件,如何让这个组件滚动的起始位置在顶部,从顶部开始滚动
06-11
<template> <view class="container"> <!-- 光晕效果:添加在qian1后面 --> <view class="wave-container" :class="{&#39;fade-out&#39;: waveFading}" v-show="showWave"> <view v-for="i in waveCount" :key="i" class="wave" :style="{ animationDelay: `${i * 0.5}s` }" ></view> </view> <image v-show="showQian1" class="zhongQian zhongShake-animation" @animationend="handleAnimationEnd" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/luckyHomeImg/qian1.png" mode="widthFix"></image> <view class="qianXq" :class="{&#39;scale-in&#39;: showQianXq}" v-show="showQianXq" id="save-container"> <!-- 原有内容保持不变 --> <image class="bg" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/bg.png" mode="widthFix"></image> <image class="hudie" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/hudie1.gif" mode="widthFix"></image> <image class="hudian2" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/hudian2.webp" mode="widthFix"></image> <image class="hudie1" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/hudie1.gif" mode="widthFix"></image> <image class="titleBg" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/titleBg.png" mode="widthFix"></image> <image class="qianXian" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/qianXian.png" mode="widthFix"></image> <image class="bestQian" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/qian.png" mode="widthFix"></image> <image class="shai" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/shai.png" mode="widthFix"></image> <image class="fenxiangText" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/fenxiangText.png" mode="widthFix"></image> <image class="xiangce" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/xiangce.png" @click="shareClick" mode="widthFix"></image> <view class="title"> <view class="title1">{{ titleArray[0] }}</view> <view class="title2">{{ titleArray[1] }}</view> <view class="title3">{{ titleArray[2] }}</view> </view> <view class="time">{{currentDate }}</view> <view class="qianCon" :class="{ &#39;qianCon-centered&#39;: isQianConCentered, &#39;qianCon-original&#39;: !isQianConCentered, [`qianCon-${signCharCount}`]: true }" >{{ signContent.sign }}</view> <!-- 修改jiyu,添加动画类 --> <view class="jiyu" :class="{&#39;jiyu-slide-in&#39;: showJiyu}" v-show="showJiyu" > <view class="jiyu1">{{ signDescPart1 }}</view> <view class="jiyu2">{{ signDescPart2 }}</view> </view> <view class="qianText">属于你的·专属签</view> <image class="close" src="https://shoujinshang.oss-cn-beijing.aliyuncs.com/static/bestFortune/close.png" mode="" @click="handleClose"></image> </view> <!-- 画布容器,用于生成图片 --> <canvas style="position: fixed; left: -10000rpx; top: -10000rpx;" canvas-id="shareCanvas" id="shareCanvas" ></canvas> </view> </template> <script setup> import { ref, onMounted, defineProps, defineEmits, computed, nextTick } from &#39;vue&#39;; // 定义props,接收父组件传递的参数 const props = defineProps({ // 可以添加需要的props,比如签文内容 qianContent: { type: String, default: &#39;暴 富&#39; } }); // 定义emit事件 const emit = defineEmits([&#39;close&#39;]); // 控制显隐:初始显示qian1/光晕,隐藏qianXq const showQian1 = ref(true); const showWave = ref(true); const showQianXq = ref(false); const waveFading = ref(false); // 控制光晕淡出动画 const waveCount = 4; // 新增状态变量 const isQianConCentered = ref(true); // 控制qianCon是否居中 const showJiyu = ref(false); // 控制jiyu是否显示 // 签文内容 const signContent = ref({ sign: &#39;&#39;, signDesc: &#39;&#39;, signType: null // 0:大吉签, 1:上上签 }); // 计算当前日期 const currentDate = computed(() => { const now = new Date(); const year = now.getFullYear(); // 十天干 const heavenlyStems = [&#39;甲&#39;, &#39;乙&#39;, &#39;丙&#39;, &#39;丁&#39;, &#39;戊&#39;, &#39;己&#39;, &#39;庚&#39;, &#39;辛&#39;, &#39;壬&#39;, &#39;癸&#39;]; // 十二地支 const earthlyBranches = [&#39;子&#39;, &#39;丑&#39;, &#39;寅&#39;, &#39;卯&#39;, &#39;辰&#39;, &#39;巳&#39;, &#39;午&#39;, &#39;未&#39;, &#39;申&#39;, &#39;酉&#39;, &#39;戌&#39;, &#39;亥&#39;]; // 计算干支纪年(以公元3年为基准点,3年为癸亥年,4年为甲子年) const stemIndex = (year - 3) % 10; const branchIndex = (year - 3) % 12; // 处理负数情况(确保索引为非负) const stem = heavenlyStems[(stemIndex + 10) % 10]; const branch = earthlyBranches[(branchIndex + 12) % 12]; const ganZhiYear = `${stem}${branch}年`; const month = String(now.getMonth() + 1).padStart(2, &#39;0&#39;); const day = String(now.getDate()).padStart(2, &#39;0&#39;); return `${ganZhiYear} ${year}.${month}.${day}`; }); // 计算标题数组 const titleArray = computed(() => { if (signContent.value.signType === 0) { return [&#39;大&#39;, &#39;吉&#39;, &#39;签&#39;]; // 大吉签 } else { return [&#39;上&#39;, &#39;上&#39;, &#39;签&#39;]; // 上上签 } }); // 计算签文描述的两个部分 const signDescPart1 = computed(() => { const desc = signContent.value.signDesc || &#39;&#39;; // 去掉逗号、句号等标点符号 const cleanedDesc = desc.replace(/[,。、;,.;]/g, &#39;&#39;); const words = cleanedDesc.split(&#39;&#39;); const midIndex = Math.ceil(words.length / 2); return words.slice(0, midIndex).join(&#39;&#39;); }); const signDescPart2 = computed(() => { const desc = signContent.value.signDesc || &#39;&#39;; // 去掉逗号、句号等标点符号 const cleanedDesc = desc.replace(/[,。、;,.;]/g, &#39;&#39;); const words = cleanedDesc.split(&#39;&#39;); const midIndex = Math.ceil(words.length / 2); return words.slice(midIndex).join(&#39;&#39;); }); // 设置签文内容的方法(供父组件调用) const setSignContent = (content) => { signContent.value = { ...signContent.value, ...content }; }; const loadFontLocal = () => { let fontSource = &#39;&#39;; try { // 尝试获取plus对象 if (typeof plus !== &#39;undefined&#39; && plus.io) { fontSource = `url(${plus.io.convertLocalFileSystemURL(&#39;/static/luckyFonts/MaokenAssortedSans/MaoKenShiJinHei-2.ttf&#39;)})`; } else { fontSource = &#39;url(/static/luckyFonts/MaokenAssortedSans/MaoKenShiJinHei-2.ttf)&#39;; } } catch (error) { // 出错时使用相对路径 fontSource = &#39;url(/static/luckyFonts/MaokenAssortedSans/MaoKenShiJinHei-2.ttf)&#39;; } uni.loadFontFace({ family: &#39;MaokenAssortedSans&#39;, source: fontSource, success() { console.log(&#39;字体加载成功&#39;); }, fail(e) { console.log(&#39;字体加载失败&#39;, e); } }); }; const signCharCount = computed(() => { const sign = signContent.value.sign || &#39;&#39;; return sign.replace(/\s/g, &#39;&#39;).length; }); // 动画结束:隐藏qian1/光晕,显示qianXq const handleAnimationEnd = () => { // 1. 先立即隐藏qian1 showQian1.value = false; // 2. 等待0.5秒后,开始光晕淡出动画 setTimeout(() => { waveFading.value = true; // 开始淡出动画 // 3. 在淡出动画结束后隐藏wave-container setTimeout(() => { showWave.value = false; }, 500); // 淡出动画持续0.5秒 // 4. 在光晕淡出动画开始后,延迟0.2秒开始显示qianXq,让过渡更自然 setTimeout(() => { showQianXq.value = true; // 5. qianXq显示后,等待1秒开始后续动画 setTimeout(() => { // 5.1 qianCon回到原来位置 isQianConCentered.value = false; // 5.2 等待0.5秒后,jiyu从右侧滑入 setTimeout(() => { showJiyu.value = true; }, 500); // 等待qianCon回到原位后开始滑入 }, 1000); // 等待1秒 }, 200); }, 500); // 等待0.5秒 }; // 关闭组件 const handleClose = () => { emit(&#39;close&#39;); }; // 重置组件状态(当重新显示时需要) const resetComponent = () => { showQian1.value = true; showWave.value = true; showQianXq.value = false; waveFading.value = false; isQianConCentered.value = true; showJiyu.value = false; // 重置签文内容为默认值 // signContent.value = { // sign: &#39;暴 富 福 福&#39;, // signDesc: &#39;所 念 皆 有 成 有&#39;, // signType: 0 // }; }; onMounted(async () => { loadFontLocal(); // 兜底:动画事件失效时,3秒后强制切换 setTimeout(() => { if (showQian1.value) { showQian1.value = false; setTimeout(() => { waveFading.value = true; setTimeout(() => { showWave.value = false; }, 500); setTimeout(() => { showQianXq.value = true; // 同样执行后续动画 setTimeout(() => { isQianConCentered.value = false; setTimeout(() => { showJiyu.value = true; }, 500); }, 1000); }, 200); }, 500); } }, 3000); }); // 暴露方法,用于直接显示详情(跳过动画) const showDirectly = () => { resetComponent(); // 先重置 // 手动设置状态,跳过动画 showQian1.value = false; showWave.value = false; showQianXq.value = true; // 直接执行后续动画 setTimeout(() => { isQianConCentered.value = false; setTimeout(() => { showJiyu.value = true; }, 500); }, 100); }; // 暴露方法给父组件 defineExpose({ resetComponent, setSignContent, showDirectly // 新增方法 }); </script> <style scoped> .container { position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; background: #000000; /* opacity: 0.8; */ background: rgba(0, 0, 0, 0.8); z-index: 1000; } .bg { position: absolute; width: 618rpx; height: 990rpx; left: 72rpx; top: 174rpx; opacity: 1; } /*调整wave-container的位置和大小*/ .wave-container { position: absolute; width: 500rpx; /* 扩大宽度 */ height: 800rpx; /* 扩大高度 */ display: flex; align-items: center; justify-content: center; /* 将光晕放在qian1的背后中间位置 */ left: 390rpx; /* qian1的left */ top: 17%; /* qian1的top */ /* 使用transform让光晕容器居中在qian1位置 */ transform: translateX(-50%); z-index: 1; opacity: 1; } /* 修改2:调整wave的样式,使用淡金色 */ .wave { position: absolute; border-radius: 50%; border: 3rpx solid; /* 加粗边框 */ /* 使用淡金色:#FFD700是金色,rgba(255, 215, 0, 0.8)是带透明度的金色 */ border-color: rgba(255, 215, 0, 0.6); /* 淡金色,透明度0.6 */ /* 添加内部阴影增强光晕效果 */ box-shadow: 0 0 20rpx rgba(255, 215, 0, 0.4) inset; animation: waveSpread 3s infinite ease-in-out; } /* 光晕淡出动画 */ @keyframes fadeOut { 0% { opacity: 1; } 100% { opacity: 0; } } .wave-container.fade-out { animation: fadeOut 0.5s ease-out forwards; } .wave-container.fade-out .wave { animation-play-state: paused; } /*扩大waveSpread动画的范围 */ @keyframes waveSpread { 0%, 100% { width: 150rpx; /* 扩大初始大小 */ height: 150rpx; opacity: 0; border-width: 4rpx; /* 开始时边框较粗 */ } 50% { width: 700rpx; /* 大大扩大最大尺寸 */ height: 700rpx; opacity: 0.8; /* 提高最大透明度 */ border-width: 1rpx; /* 扩散时边框变细 */ border-color: rgba(255, 215, 0, 0.3); /* 扩散时颜色变淡 */ box-shadow: 0 0 30rpx rgba(255, 215, 0, 0.2) inset; /* 扩散时阴影变淡 */ } } /* 签1样式 */ .zhongQian { position: absolute; width: 120rpx; height: 520rpx; left: 325rpx; top: 30%; z-index: 2; /* 确保在光晕前面 */ transform-origin: 50% 50%; } /* 晃动动画 */ @keyframes shake { 0% { transform: rotate(0deg); } 20% { transform: rotate(5deg); } 40% { transform: rotate(-5deg); } 60% { transform: rotate(3deg); } 80% { transform: rotate(-3deg); } 100% { transform: rotate(0deg); } } .zhongShake-animation { animation: shake 0.5s ease-in-out 5; animation-fill-mode: forwards; } /* 签详情样式 */ .qianXq { position: absolute; width: 100%; height: 100%; /* 初始状态:缩小到很小,完全透明 */ transform: scale(0.3); opacity: 0; /* 设置变换原点为中心 */ transform-origin: center center; } /* qianXq缩放显示动画 - 使用关键帧动画 */ @keyframes scaleIn { 0% { transform: scale(0.3); opacity: 0; } 60% { transform: scale(1.05); opacity: 1; } 80% { transform: scale(0.95); } 100% { transform: scale(1); opacity: 1; } } /* 应用缩放动画 */ .qianXq.scale-in { animation: scaleIn 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; } .qianXq .titleBg { position: absolute; width: 200rpx; height: 74rpx; left: 282rpx; top: 406rpx; } .qianXian { position: absolute; width: 228rpx; height: 12rpx; left: 264rpx; top: 490rpx; } .bestQian { position: absolute; width: 258rpx; height: 30rpx; left: 252rpx; top: 898rpx; } .shai { position: absolute; width: 324rpx; height: 110.3rpx; left: 217.04rpx; top: 1128rpx; } .fenxiangText { position: absolute; width: 182rpx; height: 20rpx; left: 288rpx; top: 1196rpx; } .xiangce { position: absolute; width: 324rpx; height: 106rpx; left: 218rpx; top: 1250rpx; } .title { font-family: MaokenAssortedSans; font-size: 44rpx; color: #FDF8D1; line-height: 52rpx; text-align: left; font-style: normal; } .title .title1 { position: absolute; left: 306rpx; top: 410rpx; } .title .title2 { position: absolute; left: 356rpx; top: 410rpx; } .title .title3 { position: absolute; left: 412rpx; top: 410rpx; } .qianXq .hudie { position: absolute; transform: scaleX(-1); width: 100.38rpx; height: 78rpx; left: 530rpx; top: 288rpx; } .hudie1 { position: absolute; width: 110rpx; height: 82rpx; left: 82rpx; top: 900rpx; } .qianXq .hudian2 { position: absolute; width: 100.38rpx; height: 78rpx; left: 150rpx; top: 980rpx; } .time { position: absolute; width: 202rpx; height: 34rpx; left: 274rpx; top: 498rpx; font-family: PingFangSC, PingFang SC; font-weight: 400; font-size: 24rpx; color: #C69D5E; line-height: 34rpx; text-align: left; font-style: normal; } /* qianCon基础样式 */ .qianCon { position: absolute; top: 630rpx; height: 168rpx; font-family: MaokenAssortedSans; color: #B78543; line-height: 84rpx; text-align: left; font-style: normal; transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94); display: flex; align-items: center; /* writing-mode: vertical-rl; text-orientation: upright; white-space: nowrap; */ } /* 2个字:默认样式 */ .qianCon.qianCon-2 { left: 290rpx; width: 72rpx; font-size: 70rpx; } /* 3个字:调整位置和大小 */ .qianCon.qianCon-3 { left: 280rpx; /* 左移10rpx */ width: 72rpx; font-size: 65rpx; /* 稍小一点 */ } /* 4个字:进一步调整 */ .qianCon.qianCon-4 { left: 270rpx; /* 再左移10rpx */ width: 72rpx; font-size: 60rpx; /* 再小一点 */ } /* 5个字及以上:最小字体,居中显示 */ .qianCon.qianCon-5, .qianCon.qianCon-6, .qianCon.qianCon-7, .qianCon.qianCon-8 { left: 50%; transform: translateX(-50%); width: 72rpx; font-size: 55rpx; text-align: center; } /* qianCon居中状态 */ .qianCon.qianCon-centered { left: 50% !important; top: 45%; width: 72rpx; transform: translate(-50%, -50%) !important; font-size: 80rpx !important; text-align: center !important; } /* qianCon居中状态 */ /* .qianCon.qianCon-centered { left: 50%; top: 45%; transform: translate(-50%, -50%); font-size: 80rpx; text-align: center; } */ /* qianCon回到原位的动画 */ .qianCon.qianCon-original { left: 290rpx; top: 630rpx; width: 72rpx; transform: translate(0, 0); font-size: 70rpx; text-align: left; } /* 修改jiyu容器样式 */ .jiyu { position: absolute; /* 初始位置在屏幕右侧外 */ left: 750rpx; top: 596rpx; /* 隐藏jiyu内容,等滑入后再显示 */ opacity: 0; /* 滑入动画 */ transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94); } /* jiyu滑入动画 */ .jiyu.jiyu-slide-in { left: 390rpx; opacity: 1; } .jiyu1 { position: absolute; left: 0rpx; top: 0rpx; width: 30rpx; height: 240rpx; font-family: PingFangSC, PingFang SC; font-weight: 400; font-size: 28rpx; color: #B78543; line-height: 40rpx; text-align: left; font-style: normal; } .jiyu2 { position: absolute; left: 44rpx; top: 2rpx; width: 30rpx; height: 240rpx; font-family: PingFangSC, PingFang SC; font-weight: 400; font-size: 28rpx; color: #B78543; line-height: 40rpx; text-align: left; font-style: normal; } .qianText { position: absolute; left: 296rpx; top: 944rpx; width: 168rpx; height: 32rpx; font-family: PingFangSC, PingFang SC; font-weight: 500; font-size: 22rpx; color: #C69D5E; line-height: 32rpx; text-align: left; font-style: normal; } .close { position: absolute; width: 60rpx; height: 60rpx; left: 346rpx; top: 1390rpx; } /* 添加样式确保生成图片时布局正常 */ #save-container { position: relative; width: 750rpx; height: 1334rpx; background: transparent; } </style> 实现点击shareClick,将页面截图为图片,保存到手机相册中,使用的技术是u你app、
最新发布
12-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值