这篇文章发布于 2019年05月17日,星期五,23:23,归类于 CSS相关。 阅读 22073 次, 今日 3 次 13 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8629
本文可全文转载,个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。
一、不是所有CSS属性都能动画
经常和CSS打交道的人肯定都知道,不是所有的CSS属性都能使用animation
属性实现动画效果,最典型的例子就是background-image
渐变。
一个典型的线性渐变是由角度,颜色和位置组成,例如:
.gradient { background-image: linear-gradient(45deg, red 50%, blue 50%); }
其中无论是角度(45deg
),颜色(red
, blue
)还是位置(50%
)单独作为属性者都是可以动画过渡的,但是合在一起作为渐变背景的时候是无法产生过渡效果的,因为background-image
的语义是图片。
那有没有什么办法可以让背景图片也能实现动画过渡呢,至少CSS渐变可以实现?
经过我的研究和探索,找到了一种解决方案,虽称不上百分百完美,但足够应用于项目中,能让以前很多不支持CSS动画的属性,也支持原生的动画效果。
二、变量种子计数器
Chrome等浏览器(不包括Safari)有个特性,就是当我们使用@keyframes
定义关键帧的时候,关键帧里面设置的属性也是会运行的(几年前改变的,原先不是),典型的案例就是content
属性与内容变化。
例如实现一个“正在加载中…”打点效果可以下面CSS和HTML:
dot::before { content: '...'; position: absolute; animation: dot 3s infinite step-start both; } dot:after { content: '...'; color: transparent; } @keyframes dot { 33% { content: '.'; } 66% { content: '..'; } }
<button>正在加载中<dot></dot></button>
实时效果如下:
根据我的测试发现,不仅普通的CSS属性可以在CSS动画关键帧中运行,CSS自定义属性(CSS变量)也可以在CSS动画关键帧中运行。例如:
@keyframes var { 33% { --someVar: 33%; } 66% { --someVar: 66%; } }
这种特性就非常有启发,如果我们某一个CSS属性值是基于这个--someVar
变量构成的,那岂不是就算这个属性值不支持CSS动画,我只要让每一个百分比值的间隙足够的小,不也能够实现一个平滑的动画效果?
具体做法就是,把CSS动画关键帧从0%-100%
分成101份,然后每一份从0开始依次计数,就像是个计数器一样,然后把这个计数器分配给一个特定的CSS变量。最终我们可以得到一个如下所示的CSS动画“变量种子计数器”。
@keyframes seed { 0%{--seed:0}1%{--seed:1}2%{--seed:2}3%{--seed:3}4%{--seed:4}5%{--seed:5}6%{--seed:6}7%{--seed:7}8%{--seed:8}9%{--seed:9}10%{--seed:10}11%{--seed:11}12%{--seed:12}13%{--seed:13}14%{--seed:14}15%{--seed:15}16%{--seed:16}17%{--seed:17}18%{--seed:18}19%{--seed:19}20%{--seed:20}21%{--seed:21}22%{--seed:22}23%{--seed:23}24%{--seed:24}25%{--seed:25}26%{--seed:26}27%{--seed:27}28%{--seed:28}29%{--seed:29}30%{--seed:30}31%{--seed:31}32%{--seed:32}33%{--seed:33}34%{--seed:34}35%{--seed:35}36%{--seed:36}37%{--seed:37}38%{--seed:38}39%{--seed:39}40%{--seed:40}41%{--seed:41}42%{--seed:42}43%{--seed:43}44%{--seed:44}45%{--seed:45}46%{--seed:46}47%{--seed:47}48%{--seed:48}49%{--seed:49}50%{--seed:50}51%{--seed:51}52%{--seed:52}53%{--seed:53}54%{--seed:54}55%{--seed:55}56%{--seed:56}57%{--seed:57}58%{--seed:58}59%{--seed:59}60%{--seed:60}61%{--seed:61}62%{--seed:62}63%{--seed:63}64%{--seed:64}65%{--seed:65}66%{--seed:66}67%{--seed:67}68%{--seed:68}69%{--seed:69}70%{--seed:70}71%{--seed:71}72%{--seed:72}73%{--seed:73}74%{--seed:74}75%{--seed:75}76%{--seed:76}77%{--seed:77}78%{--seed:78}79%{--seed:79}80%{--seed:80}81%{--seed:81}82%{--seed:82}83%{--seed:83}84%{--seed:84}85%{--seed:85}86%{--seed:86}87%{--seed:87}88%{--seed:88}89%{--seed:89}90%{--seed:90}91%{--seed:91}92%{--seed:92}93%{--seed:93}94%{--seed:94}95%{--seed:95}96%{--seed:96}97%{--seed:97}98%{--seed:98}99%{--seed:99}100%{--seed:100} }
上面这段@keyframes seed{}
相关CSS代码就是一个可以无限使用的“动画种子”,无论是那些原本支持CSS动画的属性,还是不支持CSS动画的属性,只要它的属性值是与数值相关的,都能够借助这个“动画种子”实现动画效果。
举个渐变旋转的例子
例如一开始那个线性渐变的例子,我们可以让渐变旋转角度和我们“动画种子”中的--seed
变量相关联,配合animation
属性就能实现渐变旋转的效果了:
.gradient {
width: 150px; height: 150px;
background-image: linear-gradient(calc(3.6deg * var(--seed)), red 50%, blue 50%);
animation: seed 1s linear infinite;
}
<div class="gradient"></div>
实时效果如下(如果不动请点击这里)作者张鑫旭,非本站没有效果,点击这里查看效果https://www.zhangxinxu.com/wordpress/?p=8629::
原本不支持CSS动画的渐变背景也有了动画变换效果。
三、更进一步的动画效果
配合“变量种子计数器”,我们最实现过去很难实现的密集型背景图形动画效果,例如下面这张平铺的圈圈放大效果:
CSS和HTML代码如下:
.radial-gradient { padding: 50%; background-image: radial-gradient(#cd0000 calc(2% * var(--seed)), transparent calc(2% * var(--seed))); background-size: 80px 80px; animation: seed 1s linear infinite; }
<div class="radial-gradient"></div>
只要把我们的径向渐变的边缘使用var(--seed)
种子变量表示就可以了。使用2%
计算而不是使用1%
是为了红色铺满之后有一定的延时,否则效果体验的时候眼睛会闪瞎。
眼见为实,如果是Chrome浏览器或者Android设备,您可以狠狠地点击这里:CSS变量与径向渐变动画demo
您可以在上面提供的demo页面中修改一些数值,体验不同的效果。
四、兼容性及结语
“变量种子计数器”实现动画技术的兼容性如下:
- Chrome浏览器和Android设备上完全无障碍使用的;
- Firefox浏览器也是支持动画帧里面设置CSS变量的,但是需要应用动画的属性也写在其中,也就是每一帧中都要把
background-image
也写上,但这样就完全没有重用性,成本较高,所以价值有限; - IE浏览器和Safari浏览器则完全不支持;
由于Safari不支持,导致iOS手机上是没有效果的,大大制约了实用价值。
更新于2024年7月13日
经过鄙人的测试,Firefox和Safari现在也都支持这种方式了。
不过更优雅的实现应该是使用@property规则进行重定义。
但是放在特殊场合,也不是不能使用,我们可以使用增强实现某些特殊的效果,例如这篇文章介绍的新颖的交互动效:“你用的那些CSS转场动画可以换一换了”。
研究之路漫漫,按照我以往研究技术的经验,之后一定会发现更好的实现方法的,拭目以待吧。
就说这么多,感谢阅读,希望本文内容可以对你有所启示。
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=8629
(本篇完)
- 第五届CSS大会主题分享之CSS创意与视觉表现 (0.428)
- 小tips:了解CSS变量var (0.419)
- CSS文字和背景color自动配色技术简介 (0.419)
- CSS var变量的局部作用域(继承)特性 (0.419)
- 你用的那些CSS转场动画可以换一换了 (0.418)
- 纯CSS实现蜡烛、火焰以及熄灭后烟雾效果 (0.327)
- CSS届的绘图板CSS Paint API简介 (0.318)
- 如何在HTML和JS中设置和获取var CSS变量 (0.308)
- 小tips: 如何借助content属性显示CSS var变量值 (0.308)
- 哇哦,font-palette支持动画和palette-mix()混合函数了 (0.301)
- JS检测CSS属性浏览器是否支持的多种方法 (RANDOM - 0.010)
骚操作啊
未来不用这个啦,CSS.registerProperty 可以注册自定义属性,自定义属性也能动起来啦。 See https://developer.mozilla.org/en-US/docs/Web/API/CSS/RegisterProperty
现在又多了个 CSS 语法,直接 @property –my-property {} 来定义CSS 变量的类型,浏览器就知道怎么 animate 你的变量惹。https://developer.mozilla.org/en-US/docs/Web/CSS/@property
好东西 但这种特性的成长周期是非常长的 不知道啥时候才有实用价值
看完不错的文章习惯想去点赞
第一次在张大神网站留言,
起点现在是怎么啦,我在起点里看小说的,感觉最近很动荡啊
尝试在这里问问情况怎么样,希望能收到张大神回复。
不清楚
这可是太秀了,学到了
这个配上mask蒙版,花里胡哨的切换效果不就出来了吗
贵在尝试,几年前的尝鲜属性,现在不是可以很方便的使用了嘛~~
这个东西如果配合css 的 mask ,就能支持图片动画切换了
简单写了个demo ,css3万岁 https://codepen.io/forx-js/full/LojozK
你怎么知道我接下来要写的文章内容,哈哈。
斯 斯锅伊