推特简单又惊艳的like button动画

74 阅读3分钟

有趣的例子

近日看到国外帖子有分享在一款很好看的的like button动画,效果如下: GIF 2023-9-13 16-48-10.gif

作为前端工程师的我,第一反应是wc,第二反应是咋实现的,还没等我想出来,就看到一个国外网友已经实现了,附上codepen地址,看完实现后,觉得原理很简单啊,就是一个雪碧图逐帧播放,但是有个问题,取消like时没有动画,因此自己在这个基础上修改了一下(上面的gif动画就是改良版)。

/**** css ****/
button[aria-pressed=true] img {
    animation: like steps(var(--frames)) var(--speed) both;
}
button[aria-pressed=false] img {
    animation: dislike steps(var(--frames)) var(--speed) both;
}
@keyframes like {
    to {
        object-position: 100% 0;
    }
}
@keyframes dislike {
    from {
        object-position: 100% 0;
    }
    to {
        object-position: 0% 0;
    }
}

<!--html -->
<button>
    <img src="./transparent-sprite-apple.png">
</button>

主要就是去掉了button的aria-pressed属性,然后添加了dislike动画,说完这个动画后,想针对object-开头的属性多说几句。

object-position

object-position可以设置图片在img容器中的位置,还可以用来做动画,因此可以实现一些有意思的效果,比如hover上去图片的滑动,这里我写了一个例子

GIF 2023-9-13 17-55-10.gif

我们例子中使用的都是百分比,这里说明一下,这个百分比并不是相对于可替换元素的宽,而是以(containerWidth - imgWidth)为基准的,因此设置50%可以实现水平居中,垂直方向也是类似的,这一点和background-position是一样的。

object-view-box

object-view-box是去年新加的一个属性,MDN上似乎还没有相关的说明,它的主要作用可以用来裁剪或者缩放图片,取值有三种:<inset()> | <rect()> | <xywh()>,下面简单介绍一下他们的用法:

1. inset

其完整语法定义为inset(<length-percentage>{1,4} [round<border-radius>]?),length-percentage控制我们可视矩形区域的四个边,round可选参数控制矩形的圆角,但是round我试过了,没有效果,不清楚浏览器是否还未支持。

img {
    aspect-ratio: 3 / 2;
    width: 300px;
    object-view-box: inset(var(--top) var(--right) var(--bottom) var(left));
}

微信截图_20230913191839.png

这里需要说明的是object-view-box是作用于原始图片的,inset四个值得设置和margin/padding很像,中间剩余的就是我们最终看到的区域。有一个很直观的例子,可以实际体验一下效果。

负值

上面的例子中length-percentage都是大于等于0的值,实现放大的效果,如果设置的值是小于0的呢,其实是缩小了图片,负值相当于给原始图片添加了空白的外边距,大家可以试试看,另外对于rect和xywh来说都适用,后面就不展开说了。

2. rect

rect也是定义一个可视的矩形,其语法定义为rect([<length-percentage>|auto]{1,4} [round<border-radius>]?),那么和inset有何不同呢?

...
object-view-box: rect(offsetY1, offsetX2, offsetY2, offsetX1);
...

微信截图_20230914115140.png

因此可以得出: 矩形宽 = offsetX2 - offsetX1; 矩形高 = offsetY2 - offsetY1;

3. xywh

通过名字就能看出他的四个值是什么意思了,x和y表示矩形的左上角位置,w和h代表矩形的宽和高,使用也很简单

...
object-view-box: rect(x, y, w, h);
...

最后

除了object-position和object-view-box,还有一个比较重要的属性object-fit,这个属性比较简单,MDN上有详细的介绍,我就不多说了。