教你用长图片实现悬浮动效(阿里云首页动效图标)

最近看阿里云首页上的鼠标悬浮动效图标很好看,比较好奇怎么做的。

然后自己空闲时间实现了一个,现将步骤列出如下(想直接看代码的拉到最后):

1、

首先你需要这样一张图,像展开的gif一样,把所有的动画帧竖列排开拼成一张长图,就比如这个:

 图源:阿里云首页

这张图片的尺寸很有讲究,示例的这张长图的每一张小图都是64px * 64px的,一共20张,整体是64px * 1280px的大小,注意这几个数值,后续都会用到。

2、

创建一个div,把图片设置为其背景图,div大小与单独的一张图片大小完全一致,初始时竖直方向上位于第一张图片的位置。

<div id="anime_icon" class="anime-icon"></div>
.anime-icon{
   width: 64px;/*这个尺寸不能乱动,按照图片的尺寸来*/
   height: 64px;
   cursor: pointer;
   background-image: url('1.png');
   background-size: 100%; /*使图片和div的大小匹配*/
   background-position-y: 0; /*竖直方向上位于第一张图片的位置*/
}

3、

再之后需要两个animation,一个负责鼠标移入时的动画,一个负责鼠标移出时的动画,内容很简单,就是对图片的竖直方向位置进行修改,即background-position-y的值

@keyframes mouse-in{
    /*鼠标移入时从第一张移动到最后一张*/
    from{
        background-position-y: 0; 
    }
    to{
        background-position-y: -1280px;/*1280px就是图片的总长度,即64px 20张*/
    }
}
@keyframes mouse-out{
    /*鼠标移出时从最后一张移动回第一张*/
    from{
        background-position-y: -1280px;
    }
    to{
        background-position-y: 0;
    }
}

4、

最关键的一步来了,把动画绑定到类上,但是此时不能直接把mouse-out动画丢进anime-icon类里,因为这样会导致页面加载的时候就自动播放了一次从”最后一张图片到第一张图片“的动画,所以这里需要借助jquery,当触发了hover事件的时候,把mouse-out-class类丢上去。具体如下:

.anime-icon:hover{
    /*hover时用0.5s执行mouse-in动画*/
    animation: mouse-in .5s;

    /*这一句极其重要,将mouse-in拆成20个步骤执行(还记得我们那张长图总共有多少张小图吗)*/
    animation-timing-function:steps(20);
 
    /*动画执行结束后,停在最后一帧上*/
    animation-fill-mode:forwards;
}
.mouse-out-class{
    /*0.5s执行移出动画*/
    animation: mouse-out .5s;

    /*移出动画依然分成20步骤*/
    animation-timing-function:steps(20);

    /*动画结束时停在最后一帧*/
    animation-fill-mode:forwards;
}

然后在页面加载完成后,把mouse-out-class添加到div上即可:

$("#anime_icon").hover(function(){
    $(this).addClass('mouse-out-class');
})

注意上面这种添加的方式是非常常见的,但是hover函数有个细节:只定义一个function的时候,mouseover和mouseout都会去执行这个方法,等于是addClass在每次hover的时候都会执行两次。而我们又不能在mouseout的function里删除mouse-out-class,动画会失效。所以对于强迫症来说,下面的方法细节上会更好:

$("#anime_icon").one('mouseover', function(){
    $(this).addClass('mouse-out-class');
})

one方法只会在mouseover的时候执行一次,以后不再执行。one后面的第一个参数只能是mouseover而不能是hover,这里就涉及另一个细节:hover严格来说不算是个事件,它是mouseover和mouseout的一个合体,one函数第一个参数只能接受事件。

补充:

  • 其实我一直想找不使用jquery参与的实现方式,但是问题就卡在了页面加载的时候会自动执行一次mouse-out动画这里,如果能有办法使这个动画在页面加载时不执行,hover以后再生效就完美了。但目前搜索到的方案都不是很满意。如果有好方法也感谢在下面评论。
  • 动效尺寸的放缩由于div的尺寸不能乱改我能想到的估计就是scale了,没深入研究,不排除有别的方法可以改变生成的动效大小,也就是64px的小图,最后动效图标不是64px的,而是想要的任意尺寸。(或许同时修改width、height、background-size能行?不知道,懒得试。)
  • 长图片不一定要求竖直排列,水平排列也行,无非就是改background-position-x。但是无论竖直还是水平,不能换行。
  • div不需要overflow,因为长图是背景图,不是div的内容物。
  • 不止阿里云,其实包括腾讯云首页上的那些动效,都是这么实现的(当然人家不一定用jquery,是有自己的框架和组件的)。

至此,想要的动效就实现完了。

最后提供一下完整代码,其中1.png就是上面的那张长图,jquery文件你自己去找好啦。

<html>
    <header>
        <script src="jquery.min.js"></script>
        <style>
        @keyframes mouse-in{
            from{
                background-position-y: 0;
            }
            to{
                background-position-y: -1280px;
            }
        }
        @keyframes mouse-out{
            from{
                background-position-y: -1280px;
            }
            to{
                background-position-y: 0;
            }
        }
        .anime-icon{
            width: 64px;
            height: 64px;
            cursor: pointer;
            background-image: url('1.png');
            background-size: 100%;
            background-position-y: 0;
        }
        .anime-icon:hover{
            animation: mouse-in .5s;
            animation-timing-function:steps(20);
            animation-fill-mode:forwards;
        }
        .mouse-out-class{
            animation: mouse-out .5s;
            animation-timing-function:steps(20);
            animation-fill-mode:forwards;
        }
        </style>
    </header>
    <body>
        <div id="anime_icon" class="anime-icon"></div>
        <script>
            $("#anime_icon").one('mouseover', function(){
                $(this).addClass('mouse-out-class');
            })
            
            // $("#anime_icon").hover(function(){
            //     $(this).addClass('mouse-out-class');
            // })
        </script>
    </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值