一个页面里GIF动画“联动”的问题

我们在前端页面里通常会使用GIF/WEBP图片显示一些动画来增加页面的丰富程度及交互体验,一般来说一个GIF在页面中只会出现一次,但是有时候在功能需求上一张相同的gif在页面可能会同时显示多张,今天我们主要介绍下页面里出现多次同一个GIF的时候可能会出现的问题及解决办法。

场景及出现的问题

一个常见的场景就是上传组件,在一些业务场景中比如同时需要用户上传多个图片且不能用同一个上传组件一次性上传多张,而是需要多个上传组件分别上传,因为它们可能不仅仅以列表的形式展现,每张上传的图片可能还需要展示对应的其他信息等,所以需要多个上传组件同时渲染在页面里;而上传组件本身会有些自定义的GIF动画来增加可交互性,比如以这个上传组件为例会有3个阶段:

  • 默认鼠标未hover进来时,就是默认的灰色静态图,
  • 鼠标hover进来时会有一个展开的动画,鼠标移开之前会固定在最后一帧
  • 鼠标离开区域后会有一个缩起来的动画,恢复到最开始的样子

比如下面这个demo里的问题:

从上图我们可以看到页面里出现了多次同一张GIF,当上面的组件鼠标移出后,又hover进下面的组件,这时下面的组件把图片切走了,但是上面那个组件的GIF也跟着动了,这个就是同一张GIF(url完全一致)展示多次可能出现的动画"联动"的问题。

问题的原因就是浏览器会把url一致的GIF当做同一张图,当要在某个地方播放动画时,其他地方的相同url的GIF也会跟着一起动(相当于只有一个动画实例),那对于这个问题我们应该如何解决呢?

解决方案

既然上面的问题是因为url一样导致的,那我们的第一个办法就是确保同一页面每次请求的url不一致:

url后面加参数

最简单粗暴的方法就是url后面加个随机数:

js 复制代码
function generateRandomUrl(url) {
  return `${url}?${Math.random()}`
}

但是这种方式如果用户移进移出太多或者pv比较大的话会导致请求很多,可能会影响CDN一直回源,我们在这基础上再优化下就是可以使用自增数,1,2,3。。。,这样的话即使是不同用户也可能拿到的是之前已有的url,而且还能保证自己页面里是唯一的,如:

js 复制代码
function createUrlGenerator() {
  let num = 0
  return (url) => {
    return `${url}?n=${++num}`
  }
}
const generateImgUrl = createUrlGenerator()
const url1 = generateImgUrl(url)
const url2 = generateImgUrl(url)

重置图片状态

一般情况下当鼠标移出区域时替换的GIF的最后一帧与最开始默认的静态图是相同的,我们也可以在hover out的时候直接把图片切换为默认静态图。当然如果最后一帧在设计上有不同的展现的话那就不能用这种方案,还是得用上面加url参数的方式。

再来看下修改后的demo,页面中同时显示多个,鼠标来回hover in/out也可以正常展示了:

总结

本文主要介绍了当页面同时多次展现同一个url的GIF图片时出现同时播放动画的问题,以及常见的解决办法,当然如果能用SVG做动画的话还是不要用GIF比较好,毕竟常规动画SVG的效果更好,而且本身是文本便于压缩,具有更好的可操控性,可以通过脚本自己去控制动画及其不同的状态等优点。

相关推荐
漂流瓶jz2 小时前
BEM、OOCSS、SMACSS、ITCSS、AMCSS、SUITCSS:CSS命名规范简介
前端·css·代码规范
陈随易6 小时前
真的,你可以不用TypeScript
前端·后端·程序员
郑州光合科技余经理7 小时前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
唐璜Taro7 小时前
Vue3 + TypeScript 后台管理系统完整方案
前端·javascript·typescript
dustcell.7 小时前
haproxy七层代理
java·开发语言·前端
掘金酱8 小时前
「寻找年味」 沸点活动|获奖名单公示🎊
前端·人工智能·后端
颜酱8 小时前
栈的经典应用:从基础到进阶,解决LeetCode高频栈类问题
javascript·后端·算法
患得患失9498 小时前
【前端】前端动画优化的核心
前端
Xin_z_8 小时前
Vue3 + Sticky 锚点跳转被遮挡问题解决方案
前端·javascript·vue.js
REDcker8 小时前
WebCodecs VideoDecoder 的 hardwareAcceleration 使用
前端·音视频·实时音视频·直播·webcodecs·videodecoder