iPhone12纯色系搭配工具

css3dcss变量

作为一名小屏党,新年计划入手iphone12mini,于是针对相关信息作了些搜索,最后决定等明年的13/12s。
而在浏览电商平台时,针对手机的颜色搭配也思忖了许久,于是乎撸了个颜色搭配器(非自动)来方便配色。

配色范围

  • 主色
  • 侧边色
  • 镜头块色
  • 镜头边框色
  • logo色

预览

跳转预览
a01-1

技术点

三维建模

所谓 css3d , 其本质是在利用2维元素去拼装3维形态。操作的对象仍然是2维的平面的盒子模型,即只有长(width)宽(height),没有高。
如果把手机模型视为一个矩形,那么拼装一部手机至少需要6个平面(上下左右前后)。
透视图

<div class="iphone-device">
    <!-- 前 -->
    <div class="iphone-front"></div>
    <!-- 后 -->
    <div class="iphone-back"></div>
    <!-- 侧边-左 -->
    <div class="iphone-left iphone-side"></div>
     <!-- 侧边-右 -->
    <div class="iphone-right iphone-side"></div>
     <!-- 侧边-上 -->
    <div class="iphone-top iphone-side"></div>
     <!-- 侧边-下 -->
    <div class="iphone-bottom iphone-side"></div>
</div>

设模型长宽高分别为:

  • l:508px;
  • w:239.99952px;
  • h:30px;

Transform:

  • 前后两面分别以Y轴旋转0度与180度,并增加z轴距离为1/2h。
  • 左右两面分别以Y轴旋转-90度与90度,并增加z轴距离为1/2h 和 w-1/2h。
  • 上面先以Y轴90度,再以Z轴旋转-90度;下面先以Y轴-90度,再以Z轴旋转-90度,并增加z轴距离为l

前后
左右
上下

圆角欺骗

上一步构建的模型是个纯粹的矩形,那么如何实现3d圆角呢?因为我们依旧是在编辑平面元素,对于曲面的绘制无法像3d建模一样利用算法实现无数个线平面拼凑成一个曲面。
但是,我们可以用两个切面的角度来形成视觉欺骗,以达到曲面的效果。
圆角

css变量

模型完成之后,紧接着就是配色了,配色技术依然是老生常谈的 css变量。在根元素上申明所有的颜色变量,对应子元素以 var(--x) 的形式引用。
在Vue中,则利用 propscomputed 属性来完成对象封装。

 // index.css
.iphone-perspective {
    ...
    --main: #bf2a2a;
    --side: #ede9e8;
    --cam: #bf2a2a;
    --camRing: #ede9e8;
    --logo: #ede9e8;
    --dur: 12s;
}
.iphone-front-s,
.iphone-back-s,
.iphone-front,
.iphone-back {
    ...
    background: var(--side);
}
.iphone-brand svg{
    ...
    color: var(--logo);
}
//  PhoneColor.vue
<template>
    <div class="iphone-perspective" :style="extraRoot">
        ...
    </div>
</template>
<script>
    export default {
        name: "PhoneColor",
        props: {
            main: {
                type: String,
                default: '#bf2a2a'
            },
            side: {
                type: String,
                default: '#ede9e8'
            },
            cam: {
                type: String,
                default: '#ede9e8'
            },
            camRing: {
                type: String,
                default: '#bf2a2a'
            },
            logo: {
                type: String,
                default: '#ede9e8'
            },
            animateSpeed: {
                type:Number,
                default: 12
            }
        },
        computed:{
           extraRoot(){
               const {
                   main,
                   side,
                   cam,
                   camRing,
                   logo,
                   animateSpeed = 12
               } = this
               return {
                   '--main': main,
                   '--side': side,
                   '--cam': cam,
                   '--camRing': camRing,
                   '--logo': logo,
                   '--dur': `${animateSpeed}s`
               }
           }
        }
    }
</script>

Issue

  • 侧边的按钮实际应该与主色配色一致,代码中是懒得画了直接切的图。
  • 为了补偿圆角的冗余部分配色,前后各自增加了一个背面用来填色,从而导致了模型在旋转时会出现穿模的现象。

源码

Style Code

/*index.css*/
*,
*:after,
*:before {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.iphone-perspective {
    position: relative;
    margin: 0px auto;
    width: 239.99952px;
    height: 508px;
    -webkit-perspective: 1200px;
    -moz-perspective: 1200px;
    perspective: 1200px;
    -webkit-perspective-origin: 50% 0%;
    -moz-perspective-origin: 50% 0%;
    perspective-origin: 50% 0%;
    --main: #bf2a2a;
    --side: #ede9e8;
    --cam: #bf2a2a;
    --camRing: #ede9e8;
    --logo: #ede9e8;
    --dur: 12s;
}
@keyframes show {
    0%,100%{
        -webkit-transform: rotateY(17deg) rotateX(17deg);
        -moz-transform: rotateY(17deg) rotateX(17deg);
        transform: rotateY(17deg) rotateX(17deg);
    }
    25%{
        -webkit-transform: rotateY(180deg) rotateX(-45deg);
        -moz-transform: rotateY(180deg) rotateX(-45deg);
        transform: rotateY(180deg) rotateX(-45deg);
    }
    50%{
        -webkit-transform: rotateY(272deg) rotateX(-45deg);
        -moz-transform: rotateY(272deg) rotateX(45deg);
        transform: rotateY(272deg) rotateX(-45deg);
    }
    75%{
        -webkit-transform: rotateY(367deg) rotateX(45deg);
        -moz-transform: rotateY(367deg) rotateX(45deg);
        transform: rotateY(367deg) rotateX(45deg);
    }
}
.iphone-device {
    position: absolute;
    width: 100%;
    height: 100%;
    -webkit-transition: -webkit-transform 0.7s ease-in-out;
    -moz-transition: -moz-transform 0.7s ease-in-out;
    transition: transform 0.7s ease-in-out;
    transform: rotateY(180deg) rotateX(1deg);
    animation: show infinite ease;
    animation-duration: var(--dur);
}
.iphone-device,
.iphone-device > div{
    position: absolute;
    -webkit-transform-style: preserve-3d;
    -moz-transform-style: preserve-3d;
    transform-style: preserve-3d;
}
.iphone-front-s,
.iphone-back-s,
.iphone-front,
.iphone-back {
    width: 239.99952px;
    height: 508px;
    border-radius: 34px;
    overflow: hidden;
    background: var(--side);
}
.notch{
    background: #040404;
    width: 60%;
    height: 30px;
    margin: 0 auto;
    border-bottom-left-radius: 24px;
    border-bottom-right-radius: 24px;
    position: relative;
}
.notch::before,
.notch::after {
    content: '';
    height: 8px;
    position: absolute;
    top: 0;
    width: 8px;
}
.notch::before {
    background: radial-gradient(circle at bottom right, transparent 0, transparent 70%, black 70%, black 100%);
    right: -8px;
}
.notch:after {
    background: radial-gradient(circle at bottom left, transparent 0, transparent 70%, black 70%, black 100%);
    left: -8px;
}
.notch .camera {
    width: 6px;
    height: 6px;
    top: 9px;
    border-radius: 100%;
    position: absolute;
    right: 20px;
    background: #0d4d71;
}
.notch .speaker {
    height: 6px;
    width: 60px;
    left: 50%;
    position: absolute;
    top: 9px;
    margin-left: -30px;
    background: #171818;
    border-radius: 6px;
}
.iphone-cam-group{
    position: relative;
    margin: 15px;
    border-radius: 24px;
    width: 35%;
    height: 20%;
    background: var(--cam);
    box-shadow: 3px 2px 5px 6px #d0cbcd;
}
.iphone-ba-cam1,
.iphone-ba-cam2{
    position: absolute;
    width: 35px;
    height: 35px;
    left: 10px;
    border: 5px solid var(--camRing);
    border-radius: 50%;
    background: radial-gradient(#2c2b31,#335fc2 12.5%,#3b3a3f 30%, #11110f 57.6%, #11110f);
}
.iphone-ba-cam1{
    top: 10px;
}
.iphone-ba-cam2{
    bottom: 10px;
}
.iphone-ba-light{
    width: 6px;
    height: 6px;
    top: 15px;
    position: absolute;
    right: 20px;
    border: 1px solid #dce5ee;
    border-radius: 50%;
    background: #181617;
}
.iphone-ba-spot{
    width: 20px;
    height: 20px;
    top: 50%;
    position: absolute;
    right: 12px;
    border: 1px solid #8a8a88;
    border-radius: 50%;
    background: radial-gradient(#ffffff,#bba99f 12.5%,#bba99f 30%, #f2e9e4 57.6%, #bba99f);
    transform: translateY(-50%);
}
.iphone-brand{
    width: 100%;
    height: 20%;
    top: 50%;
    transform: translateY(-50%);
    position: absolute;
}
.iphone-brand svg{
    color: var(--logo);
    width: 100%;
    height: 100%;
}
.iphone-top,
.iphone-bottom {
    width: 30px;
    height: 179.99952px;
    -webkit-transform-origin: 50% 0;
    -moz-transform-origin: 50% 0;
    transform-origin: 50% 0;
    background-size: 100% 100%;
}
.iphone-left,
.iphone-right {
    width: 30px;
    height: 448px;
}
.iphone-front {
    border: 10px solid #040404;
    background: #444343 url(./waller.jpg) no-repeat top right;
    background-size: cover;
    -webkit-transform: rotateY(0deg) translateZ(15px);
    -moz-transform: rotateY(0deg) translateZ(15px);
    transform: rotateY(0deg) translateZ(15px);
}
.iphone-back {
    border: 1px solid #2e2c2d;
    background: var(--main);
    -webkit-transform: rotateX(180deg) rotateZ(180deg) translateZ(15px);
    -moz-transform: rotateX(180deg) rotateZ(180deg) translateZ(15px);
    transform: rotateX(180deg) rotateZ(180deg) translateZ(15px);
}
.iphone-front-s {
    -webkit-transform: rotateY(0deg) translateZ(14px);
    -moz-transform: rotateY(0deg) translateZ(14px);
    transform: rotateY(0deg) translateZ(14px);
}
.iphone-back-s{
    -webkit-transform: rotateX(180deg) translateZ(14px);
    -moz-transform: rotateX(180deg) translateZ(14px);
    transform: rotateX(180deg) translateZ(14px);
}
.iphone-right {
    background: var(--side) url("./side-right.png") no-repeat;
    background-size: 100% 100%;
    -webkit-transform: translateY(30px) rotateY(90deg) translateZ(224.99952px);
    -moz-transform: translateY(30px) rotateY(90deg) translateZ(224.99952px);
    transform: translateY(30px) rotateY(90deg) translateZ(224.99952px);
}
.iphone-left {
    background: var(--side) url("./side-left.png") no-repeat;
    background-size: 100% 100%;
    -webkit-transform: translateY(30px) rotateY(-90deg) translateZ(15px);
    -moz-transform: translateY(30px) rotateY(-90deg) translateZ(15px);
    transform: translateY(30px) rotateY(-90deg) translateZ(15px);
}
.iphone-top {
    background: var(--side) url("./side-top.png") no-repeat;
    background-size: 100% 100%;
    -webkit-transform: rotateZ(-90deg) translateY(15px) rotateY(90deg);
    -moz-transform: rotateZ(-90deg) translateY(15px) rotateY(90deg);
    transform: rotateZ(-90deg) translateY(15px) rotateY(90deg);
}
.iphone-bottom {
    background: var(--side) url("./side-bottom.png") no-repeat;
    background-size: 100% 100%;
    -webkit-transform: rotateZ(-90deg) translateY(15px) rotateY(-90deg) translateZ(508px);
    -moz-transform: rotateZ(-90deg) translateY(15px) rotateY(-90deg) translateZ(508px);
    transform: rotateZ(-90deg) translateY(15px) rotateY(-90deg) translateZ(508px);
}
.iphone-side:before,
.iphone-side:after {
    position: absolute;
    top: -25px;
    left: 0;
    width: 30px;
    height: 23px;
    background: var(--side);
    background: -webkit-linear-gradient(bottom, var(--side) 0%, var(--side) 100%);
    background: -moz-linear-gradient(bottom, var(--side) 0%, var(--side) 100%);
    background: linear-gradient(to top, var(--side) 0%, var(--side) 100%);
    content: "";
    -webkit-transform: rotateX(22.5deg) translateZ(-7px);
    -moz-transform: rotateX(22.5deg) translateZ(-7px);
    transform: rotateX(22.5deg) translateZ(-7px);
}
.iphone-side:after {
    top: 100%;
    background: -webkit-linear-gradient(top, var(--side) 0%, var(--side) 100%);
    background: -moz-linear-gradient(top, var(--side) 0%, var(--side) 100%);
    background: linear-gradient(to bottom, var(--side) 0%, var(--side) 100%);
    -webkit-transform: rotateX(-22.5deg) translateZ(-7px);
    -moz-transform: rotateX(-22.5deg) translateZ(-7px);
    transform: rotateX(-22.5deg) translateZ(-7px);
}

参考链接

为避免广啊啊告,周边种草链接就不放了,有需要的去原站点自取。

技术链接


Mulander
527 声望17 粉丝

人生不过一场空,我不灿烂谁灿烂