• 技术文章 >web前端 >css教程

    CSS高阶技巧:实现图片渐隐消的多种方法

    青灯夜游青灯夜游2023-01-14 19:36:34转载112

    将专注于实现复杂布局,兼容设备差异,制作酷炫动画,制作复杂交互,提升可访问性及构建奇思妙想效果等方面的内容。

    在兼顾基础概述的同时,注重对技巧的挖掘,结合实际进行运用,欢迎大家关注。

    正文从这里开始。

    在过往,我们想要实现一个图片的渐隐消失。最常见的莫过于整体透明度的变化,像是这样:

    <div class="img"></div>
    div {
        width: 300px;
        height: 300px;
        background: url(image.jpg);
        transition: .4s;
    }
    .img:hover {
        opacity: 0;
    }

    但是,CSS 的功能如此强大的今天。我们可以利用 CSS 实现的渐隐效果已经不再是如此的简单。【推荐学习:css视频教程

    想想看,下面这样一个效果,是 CSS 能够实现的么?

    答案是肯定的!本文就将一步一步,从零开始,仅仅使用一个标签,实现上述的图片渐隐效果。

    这里,有两个核心的点:

    莫慌,让我们一步一步来解决他们。

    强大的 Mask

    首先,我们需要用到 Mask。

    在 CSS 中,mask 属性允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。

    语法

    最基本,使用 mask 的方式是借助图片,类似这样:

    div {
        width: 300px;
        height: 300px;
        background: url(image.jpg);
        transition: .4s;
    }
    .img:hover {
        opacity: 0;
    }

    当然,使用图片的方式后文会再讲。借助图片的方式其实比较繁琐,因为我们首先还得准备相应的图片素材,除了图片,mask 还可以接受一个类似 background 的参数,也就是渐变。

    类似如下使用方法:

    {
        mask: linear-gradient(#000, transparent)                      /* 使用渐变来做遮罩 */
    }

    那该具体怎么使用呢?一个非常简单的例子,上述我们创造了一个从黑色到透明渐变色,我们将它运用到实际中,代码类似这样:

    下面这样一张图片,叠加上一个从透明到黑色的渐变,

    {
        background: url(image.png) ;
        mask: linear-gradient(90deg, transparent, #fff);
    }

    image

    应用了 mask 之后,就会变成这样:

    image

    这个 DEMO,可以先简单了解到 mask 的基本用法。

    这里得到了使用 mask 最重要结论:图片与 mask 生成的渐变的 transparent 的重叠部分,将会变得透明。

    值得注意的是,上面的渐变使用的是 linear-gradient(90deg, transparent, #fff),这里的 #fff 纯色部分其实换成任意颜色都可以,不影响效果。

    CodePen Demo -- 使用 MASK 的基本使用

    使用 mask 实现 hover 隐藏图片

    了解了 mask 的简单用法后,我们来看这样一个非常简单的例子,我们改造下上述的第一个 DEMO。

    <div class="img"></div>
    div {
        width: 300px;
        height: 300px;
        background: url(image.jpg);
    }
    .img:hover {
        mask: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0));
    }

    是的,利用 Mask,我们同样也可以得到近似的消失效果:

    如果对于 Mask 你还不了解,你需要首先看看这篇:奇妙的 CSS MASK

    当然,对于现在这个效果,有个很大的缺陷,那就是缺少了动画。图片是瞬间消失的。所以,我们还需要给上述的借助 mask 实现的图片消失效果添加上动画。

    而这,就需要用上 CSS @property 了。

    强大的 CSS @property

    CSS @property,大家应该不那么陌生了。

    @property CSS at-rule 是 CSS Houdini API 的一部分, 它允许开发者显式地定义他们的 CSS 自定义属性,允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。

    如果你对 CSS @property 还有所疑惑,建议你先快速读一读这篇文章 -- CSS @property,让不可能变可能

    回到我们的正题,如果我们想给上述使用 Mask 的代码,添加上动画,我们期望代码大概是这样:

    div {
        width: 300px;
        height: 300px;
        background: url(image.jpg);
        mask: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 1));
    }
    .img:hover {
        mask: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0));
    }

    这里,mask 的是从 mask: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 1))mask: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0)) 变化的。

    但是实际上,这样并不会产生任何的动画效果。

    原因在于,我们 Mask 属性本身是不支持过渡动画的!

    但是,利用上 CSS @property,整个效果就不一样了。借助,CSS @property,我们改造一下代码:

    @property --m-0 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    div {
        width: 300px;
        height: 300px;
        background: url(image.jpg);
        mask: linear-gradient(90deg, rgba(0, 0, 0, var(--m-0)), rgba(0, 0, 0, var(--m-0)));
        transition: --m-0 0.5s;
    }
    div:hover {
        --m-0: 0;
    }

    我们利用 CSS @property 定义了一个名为 --m-0 的变量,然后,我们将整个动画过渡效果赋予了这个变量,而不是整个 mask。

    利用这个小技巧,我们就可以成功的实现基于 mask 属性的动画效果:

    借助多重 mask 分割图片

    到了这一步,后面的步骤其实就很明朗了。

    由于 mask 拥有和 background 一样的特性。因此,mask 是可以有多重 mask 的。也就是说,我们可以设置多个不同的 mask 效果给同一个元素。

    什么意思呢?上面的效果只有一重 mask,我们稍微添加一些 mask 代码,让它变成 2 重 mask:

    @property --m-0 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    @property --m-1 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    div {
        mask: 
            linear-gradient(90deg, rgba(0, 0, 0, var(--m-0)), rgba(0, 0, 0, var(--m-0))),
            linear-gradient(90deg, rgba(0, 0, 0, var(--m-1)), rgba(0, 0, 0, var(--m-1)));
        mask-size: 50% 100%;
        mask-position: left, right;
        mask-repeat: no-repeat;
        transition: 
            --m-0 0.3s,
            --m-1 0.25s 0.15s;
    }
    div:hover {
        --m-0: 0;
        --m-1: 0;
    }

    这样,我们的步骤大概是:

    看看效果:

    继续切割为 4 重 mask

    好,既然 2 重 mask 效果没问题,那么我们可以再进一步,将整个效果切割为 4 个 mask。代码还是如法炮制,这里我再贴上核心代码:

    @property --m-0 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    @property --m-1 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    @property --m-2 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    @property --m-3 {
       syntax: "<number>";
       initial-value: 1;
       inherits: false;
    }
    div {
        mask: 
            linear-gradient(90deg, rgba(0, 0, 0, var(--m-0)), rgba(0, 0, 0, var(--m-0))),
            linear-gradient(90deg, rgba(0, 0, 0, var(--m-1)), rgba(0, 0, 0, var(--m-1))),
            linear-gradient(90deg, rgba(0, 0, 0, var(--m-2)), rgba(0, 0, 0, var(--m-2))),
            linear-gradient(90deg, rgba(0, 0, 0, var(--m-3)), rgba(0, 0, 0, var(--m-3)));
        mask-size: 50% 50%;
        mask-repeat: no-repeat;
        mask-position: left top, right top, left bottom, bottom right;
        transition: 
            --m-0 0.3s,
            --m-1 0.15s 0.1s,
            --m-2 0.25s 0.21s,
            --m-3 0.19s 0.15s;
    }
    div:hover {
        --m-0: 0;
        --m-1: 0;
        --m-2: 0;
        --m-3: 0;
    }

    这样,我们就可以得到 4 块分割图片的 mask 消失效果:

    好,再依次类推,我们就可以得到分割为 9 块的,分割为 16 块的。由于代码太多,就简单看看效果:

    CodePen Demo -- 基于 @property 和 mask 的图片渐隐消失术

    基于 SCSS 简化代码

    那么,如果我们要分割为 100 块呢?或者 400 块呢?还要手写这些代码吗?

    当然不需要,由于上面的代码的规律非常的明显,我们可以借助预处理器很好的封装整个效果。从而快速的实现切割成任意规则块数的效果。

    完整的代码如下:

    $count: 400;
    $sqrt: 20;
    $per: 100% / $sqrt;
    $width: 300px;
    $perWid: 15;
    
    @for $i from 1 to ($count + 1) {
        @property --m-#{$i} {
           syntax: "<number>";
           initial-value: 1;
           inherits: false;
        }
    }
    @function bgSet($n) {
        $bg : radial-gradient(rgba(0, 0, 0, var(--m-1)), rgba(0, 0, 0, var(--m-1)));
        
        @for $i from 2 through $n {         
            $bg: $bg, radial-gradient(rgba(0, 0, 0, var(--m-#{$i})), rgba(0, 0, 0, var(--m-#{$i})));
        }
        
        @return $bg;
    }
    @function positionSet($n) {
        $bgPosition: ();
    
        @for $i from 0 through ($n) {   
            @for $j from 0 through ($n - 1) {  
                $bgPosition: $bgPosition, #{$i * $perWid}px #{$j * $perWid}px;
            }
        }
        
        @return $bgPosition;
    }
    @function transitionSet($n) {
        $transition: --m-1 0.1s 0.1s;
    
        @for $i from 1 through $n {   
            $transition: $transition, --m-#{$i} #{random(500)}ms #{random(500)}ms;
        }
        
        @return $transition;
    }
    div {
        width: $width;
        height: $width;
        background: url(image.jpg);
        mask: bgSet($count);
        mask-size: $per $per;
        mask-repeat: no-repeat;
        mask-position: positionSet($sqrt); 
        transition: transitionSet($count);
    }
    div:hover {
        @for $i from 1 through $count {         
            --m-#{$i}: 0;
        }
    }

    这里,简单解释一下,以生成 400 块小块为例子:

    这样,我们就实现了 400 分块的渐隐效果。效果如下:

    CodePen Demo -- 基于 @property 和 mask 的图片渐隐消失术

    调整过渡变量,控制方向

    当然,上面我们的对每一个小块的 transition 的过渡时间和过渡延迟时间的设置,都是随机的:

    @function transitionSet($n) {
        $transition: --m-1 0.1s 0.1s;
    
        @for $i from 1 through $n {   
            $transition: $transition, --m-#{$i} #{random(500)}ms #{random(500)}ms;
        }
        
        @return $transition;
    }

    我们完全可以通过一定的控制,让过渡效果不那么随机,譬如有一定的方向感。

    下面,我们通过让动画的延迟时间与 $i,也就是 mask 小块的 index 挂钩:

    @function transitionSet($n) {
        $transition: --m-1 0.1s 0.1s;
    
        @for $i from 1 through $n {   
            $transition: $transition, --m-#{$i} #{100 + random(500)}ms #{($i / 50) * random(100)}ms;
        }
        
        @return $transition;
    }

    那么,整个动画的方向就是从左往右逐渐消失:

    CodePen Demo -- 基于 @property 和 mask 的图片渐隐消失术 2

    当然,有意思的是,这个效果,不仅仅能够运用在图片上,它其实可以作用在任何元素之上!

    譬如,我们有的只是一段纯文本,同样适用这个效果:

    CodePen Demo -- 基于 @property 和 mask 的文本渐隐消失术

    总结

    到这里,简单总结一下。本文,我们核心利用了 CSS @propery 和 mask,实现了一些原本看上去需要非常多 div 才能实现或者是需要借助 Canvas 才能实现的效果。同时,我们借助了 SCSS 预处理器,在寻找到规律后,极大的简化了 CSS 代码的书写量。

    到今天,强大的 CSS 已经允许我们去做越来越多更有意思的动效,CSS @propery 和 mask 这两个属性在现代 CSS 发挥了非常重要的作用,非常建议大家认真掌握以下这两个属性。

    原文链接:https://juejin.cn/post/7167160342101884935

    作者:chokcoco

    (学习视频分享:web前端

    以上就是CSS高阶技巧:实现图片渐隐消的多种方法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:前端 CSS JavaScript
    上一篇:手把手教你用CSS实现简单大气的输入框 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 带你使用CSS+jQuery实现一个文字转语音机器人• 巧用纯CSS实现鼠标点击拖拽效果,让交互更加生动!• 聊聊CSS新特性content-visibility,助你提升页面渲染性能• 手把手教你使用CSS实现酷炫六边形网格背景图• 聊聊怎么利用CSS实现波浪进度条效果• 手把手教你用CSS实现简单大气的输入框
    1/1

    PHP中文网