CSS 复刻 iPhone14,并接到了优弧的电话😏,还不快接电话?

6,023 阅读5分钟

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

最近 iPhone14 上市新增了一个所谓的 “灵动岛” 的功能,我看着我手里上个月才刚买的 iPhone13,想了一下,还能再战5年,不过在看 apple 官网的视频介绍中,关于 iPhone14 的 “灵动岛” 效果还挺有趣,今天我们就来复刻一下 iPhone14 中 “灵动岛” 的效果。老规矩,我们先来看一下最终实现的效果,如下所示:

demo1.gif

当我们将鼠标移入手机时,屏幕会变亮,并且会收到 优弧 打来的电话,点击顶部的 “灵动岛” ,它会展开并展示两个按钮及左侧打电话的人;当鼠标再次点击时,“灵动岛” 会收起来,移出手机后,屏幕会变黑。下面我们就一起来盘一下这个效果。

iPhone14 外观

首先我们先把 iPhone14 的外观画出来,我们先来看一下相关的 html,代码如下:

<div class="box">
    <div class="inner"></div>
    <i class="btn btn1"></i>
    <i class="btn btn2"></i>
    <i class="btn btn3"></i>
    <i class="rightSldeBtn"></i>
</div>

最外层的 box 就是整个手机的 ”壳“,里面又包含了 ”屏幕“、”声音按键“、”开机键“ 等功能,接下来我们一起来看一下如何通过 CSS 将 iPhone14 画出来,相关 CSS 代码如下:

.box {
    position: relative;
    width: 300px;
    height: 600px;
    background: #666;
    border-radius: 50px;
    
    &::before {
        content: '';
        position: absolute;
        inset: 3px;
        background: #000;
        border-radius: 48px;
    }
    
    .inner {
        position: absolute;
        inset: 3px;
        border-radius: 48px;
        border: 10px solid #000;
        display: flex;
        justify-content: center;
        opacity: 0;
        transition: 0.3s;
    }
    
    .btn {
        position: absolute;
        top: 110px;
        left: -2px;
        width: 3px;
        height: 26px;
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
        background: radial-gradient(#ccc, #666, #222);
        z-index: 10;

        &.btn2 {
            top: 160px;
            height: 40px;
        }

        &.btn3 {
            top: 220px;
            height: 40px;
        }
    }

    .rightSldeBtn {
        position: absolute;
        top: 170px;
        right: -2px;
        width: 3px;
        height: 70px;
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
        background: radial-gradient(#ccc, #666, #222);
        z-index: 10;
    }
}

上面的样式代码都很简单,通过 flex 布局将页面中的元素排列好位置,然后通过设置不同的背景色渲染出来,上述的代码最终实现的样子如下图所示:

image.png

乍一看,这个样子跟 iPhone 前面几代几乎没有什么区别,如果不是 iPhone14 新增了一个 ”灵动岛“ 效果,基本看前面的屏幕都看不出什么区别来。既然说到 ”灵动岛“,那我们接下来就一起来看一下如何实现它吧!

”灵动岛“

目前为止,我们的手机屏幕还是黑的,并且还没有相关的壁纸,因此我们需要先添加一个壁纸,然后当鼠标移入屏幕的时候让它亮起来,相关代码如下:

.box .inner {
    position: absolute;
    inset: 3px;
    background: url('https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3f6c1f4d91e64c8584a770696b211e1a~tplv-k3u1fbpfcp-watermark.image');
    background-size: cover;
    background-position: center;
    border-radius: 48px;
    border: 10px solid #000;
    display: flex;
    justify-content: center;
    opacity: 0;
    transition: 0.3s;
}
.box:hover {
    .inner {
        opacity: 1;
    }
}

通过改变 box 里面 inner 的透明度,让整个屏幕亮起来,实现的效果如下图所示:

demo2.gif

现在屏幕已经亮了,接下来就需要画出 ”灵动岛“ 了,我们需要更新一下相关的 html 代码,如下:

<div class="inner">
    <div class="island-popup">
        <div class="content">
            <div class="details">
                <div class="imgBx">
                    <img src="https://p3-passport.byteimg.com/img/user-avatar/7e4a7c01e7022917f7242419f19a6c03~100x100.awebp" />
                </div>
                <p>优弧</p>
            </div>
            <div class="action">
                <ion-icon name="call" class="red"></ion-icon>
                <ion-icon name="call" class="green"></ion-icon>
            </div>
        </div>
    </div>
</div>

inner 内部,我们添加一个 div 元素,里面就包含了 ”灵动岛“ 相关的内容,这里因为用到了两个听筒📞的 icon,因此引入了一个第三方的图标库,但是由于这个第三方库需要添加到 body 最后,而码上掘金没有相关的功能,因此这里只能通过 js 代码动态将整个图标库插入到 body 中,相关代码如下:

const s = document.createElement('script');
s.src = 'https://unpkg.com/ionicons@5.0.0/dist/ionicons.js';
document.body.appendChild(s);

接着我们继续来写 ”灵动岛“ 相关的 CSS 样式,代码如下:

// less
.island-popup {
    position: absolute;
    top: 10px;
    width: 90px;
    height: 25px;
    background: #000;
    border-radius: 20px;
    transition: 0.5s ease-in-out;
    display: flex;
    align-items: center;
    justify-content: space-between;

    &:hover {
        width: 200px;
        height: 25px;

        p {
            visibility: visible !important;
            opacity: 1 !important;
            transition-delay: 0.25s;
        }

        .action {
            visibility: visible !important;
            opacity: 1 !important;
            transition-delay: 0.25s;
        }
    }

    &.active {
        width: 260px;
        height: 60px;
        border-radius: 50px;

        p {
            visibility: visible !important;
            opacity: 1 !important;
            transition-delay: 0.25s;
        }

        .action {
            visibility: visible !important;
            opacity: 1 !important;
            transition-delay: 0.25s;
            top: 12px;
        }
    }

    .content {
        position: relative;
        display: flex;
        width: 100%;
        justify-content: space-between;
        padding: 10px;
        line-height: 25px;

        p {
            color: #fff;
            font-size: 0.6em;
            cursor: default;
            visibility: hidden;
            opacity: 0;
            transition: 0.5s;
        }

        .details {
            position: relative;
            display: flex;
            align-items: center;

            .imgBx {
                position: relative;
                width: 0;
                height: 0;
                background: #fff;
                border-radius: 50%;
                overflow: hidden;
                transition: 0.5s;

                img {
                    position: absolute;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    object-fit: cover;
                }
            }
        }
    }

    .action {
        position: relative;
        top: 5px;
        color: #fff;
        display: flex;
        gap: 12px;
        transition: 0.5s;
        visibility: hidden;
        opacity: 0;

        ion-icon.red {
            color: #fd443b;
            transform: rotate(135deg);
            cursor: pointer;
            transition: 0.5s;
        }

        ion-icon.green {
            color: #31d059;
            cursor: pointer;
            transition: 0.5s;
        }
    }

    &.active {
        ion-icon.red { 
            background-color: #fd443b;
            color: #fff;
            border-radius: 50%;
            box-shadow: 0 0 0 8px #fd443b;
            margin-right: 12px;
        }

        ion-icon.green {
            background-color: #31d059;
            color: #fff;
            border-radius: 50%;
            box-shadow: 0 0 0 8px #31d059;
            margin-right: 8px;
        }

        .details {
            .imgBx {
                width: 40px;
                height: 40px;
                margin-right: 8px;
            }
        }
    }
}

上述的样式主要是将屏幕中间的 ”灵动岛“ 渲染在屏幕正中间,并且添加了一个 hover 动画效果,最终实现如下图所示:

demo3.gif

到这里也快收尾了,但是还差一步。还记得我们前面说的可以点击 ”灵动岛“ 进行展开吗?这里我们需要添加几行 js 来实现这个效果,相关代码如下:

let popup = document.querySelector('.island-popup');
popup.onclick = function () {
    popup.classList.toggle('active');
};

我们只需要给中间的 ”灵动岛“ 添加一个简单的点击事件,不断的切换 ”灵动岛“ 上面的 className ,就能实现最终的 ”灵动岛“ 展开与收起。最终实现的效果在这里进行查看:

总结

iPhone 系列经过卖了这么多年,最近出的 iPhone14 越发觉得 apple 是不是已经江郎才尽了,iPhone14iPhone13 进行对比,除了电池容量以及芯片的升级,外加这个 ”灵动岛“ 效果,真心觉得没有更多的亮点了,对此,你怎么看?你会买 iPhone14 吗?

最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家

往期回顾

今年中秋的月亮真漂亮~

『 纯 CSS 实现』哇塞,彩虹🌈还能这么玩?

『 禁止吸烟🚭』纯 CSS 实现 | 禁烟也能做的这么酷炫

送你一个可爱的大圆脸😁,速来~

这么炫酷的 3D Menu 效果,真的不来看看?

产品经理:你这个效果不行,我想要一个五彩斑斓的黑!我:。。。