用代码实现中国腕表史66年以来第一枚GPHG奖-蓝色星球

1,470 阅读7分钟

内容介绍

瑞士时间2021年11月4日晚18:30点,日内瓦高级钟表大赏公布了第21届获奖名单,来自中国的原创设计师腕表品牌CIGA design玺佳凭借年度新品U系列·蓝色星球荣膺中国腕表史66年以来第一枚GPHG奖牌,荣耀之战,为国争光!

产品的设计灵感来源于2020年全球疫情爆发,以“蓝色星球”为主题,融入陆地、山脉、海洋等自然元素,真实还原地球的地貌,旨在唤醒每一个人对于地球环境、自然万物的守护意识,希望人类在这方寸之间,从这一刻开始,以微薄之力一起守护人类赖以生存的家园“蓝色星球”,这款腕表的意义即让环保践行恒动不息。

首先我要声明一点,这不是一个广告!是因为喜欢,但也是因为买不起,所以我用另一种形式表达了我对它的喜欢。虽然不够完美,但我想我展现了它所要表达的含义。我是一个不爱戴手表的人,但是我喜欢这款手表是因为它的设计理念和设计灵感。

买不起,但是我可以已另一种形式拥有它。我把它用代码写了出来!虽然不是百分之百的还原,但是我把它该有的都呈现了出来。

WechatIMG829.png

功能实现

因为突然看见这款手表,临时起意想去用代码实现出来他的功能,所以没有事先想好怎么搭建结构,所以实现的步骤有些让人难以理解。

我认为按照常规的逻辑是先从最外圈的表盘部分去写,然后是里圈的表盘部分。最后写内圈的地球。再加上js使其动起来。

但我写的是先从里圈去写,然后是内圈的地球部分,最后写的外圈。因为这个顺序的原因在实现起来还是有点坑的。

里圈表盘实现-分针部分

html部分

 <div class="earth_main">
   <div class="branch"></div>
 </div>

css部分

<style>
        .earth_main {
            width: 100%;
            height: 100vh;
            background: #fff;
            display: flex;
            justify-content: center;
            align-items: center;
        }
         .branch {
            width: 394px;
            height: 394px;
            border-radius: 394px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            /*为了写出立体感,加了一个渐变颜色*/
            background-image: radial-gradient(rgba(0, 0, 0, 1), rgba(139, 139, 139, 250));
            transition: 1s linear;
        }
 </style>

效果

image.png

把地球扣上去

或许有小伙伴会问,为什么分针的表盘和中间的地球指针不是父子关系,而是兄弟关系?最初我也是写成了父子关系的两个div,但是因为这个分针表盘是会转的(每分钟转6度),中间的地球部分也是会转的(每分钟2.5度)。它俩同时转起来的时候如果是父子关系将会影响中间地球部分的转动效果。所以我把他写成兄弟关系,使用定位让其中间地球部分保持在中间位置不变。

html部分

    <div class="earth_main">
         <!-- 里圈的表盘-表示的是分针部分 -->
        <div class="branch"></div>
        <!-- 最中间的地球-表示指针的部分 -->
        <div class="earth">
            <img src="./images/earth.png" alt="">
        </div>
    </div>

css部分

.earth {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -162px;
            margin-left: -162px;
            width: 324px;
            height: 324px;
            border-radius: 324px;
            /*地图是从原图上扣下来的,有点瑕疵,所以我给加了个阴影部分遮饰一下*/
            box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 1);
            z-index: 5000;
            /*让指针转动变得平滑*/
            transition: 1s linear;
        }

        .earth img {
            width: 100%;
            height: 100%;
            border-radius: 100%;
            z-index: 2000;
            background: transparent;
        } 

效果图

image_1.png

实现分针的刻度

分针部分的刻度是60个,每两个刻度之间相差6度。所以使用for循环循环出60个li标签,但每隔五分钟显示数字。用(i%5===0)来实现这个效果。

js部分

 const branch = document.querySelector('.branch')
 function branchFun() {
   // 创建一个ul标签
   const Ul = document.createElement('ul');
     // 写一个循环,创建60个刻度
    for (let i = 0; i < 60; i++) {
      // 创建li标签当刻度
      const Li = document.createElement('li');
      // li标签里写一个span标签,背景色为白色
      Li.innerHTML = `<span style="margin-right:10px"></span>`
      // 每隔五个刻度要显示数字
      if (i % 5 === 0) {
      // 当为第五个刻度的时候span标签背景色为透明色,然后旋转90度。
      // 数字为小于10的时候要现实05或者00,所以做了一个判断
      // 因为数字是逆时针显示,所以用55-i,请看效果图
        Li.innerHTML = `<span style="margin-right:3px;background: transparent;transform: rotate(90deg);">${(55 - i) < 10 ? ('0' + (55 - i)) : (55 - i)}</span>`
       }
       // 每个li标签以左端为中点旋转6度
       Li.style.cssText = "transform:rotate(" + (i * 6) + "deg)";
       // 将li标签插入ul标签
        Ul.appendChild(Li);
     }
      // 将ul标签插入div标签
     branch.appendChild(Ul);
  }

css部分

        .branch {
            width: 394px;
            height: 394px;
            border-radius: 394px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            background-image: radial-gradient(rgba(0, 0, 0, 1), rgba(139, 139, 139, 250));
            transition: 1s linear;
        }

        .branch>ul {
            width: 100%;
            height: 100%;
            z-index: 9999;
            display: flex;
            flex-flow: column;
            justify-content: space-between;
            align-items: center;
            position: relative;

        }

        .branch>ul>li {
            position: absolute;
            left: 50%;
            top: 50%;
            list-style: none;
            width: 50%;
            height: 2px;
            display: flex;
            flex-flow: row;
            justify-content: flex-end;
            align-content: center;
            transform-origin: left;
        }

        .branch>ul>li>span {
            width: 12px;
            height: 2px;
            background: #fff;
            color: #fff;
            font-size: 12px;
        }

效果图 image_2.png

最外圈表盘实现-时针部分

这部分是又写了个更大圆,实现同心圆。

html部分

    <div class="earth_main">
        <!-- 最外圈的表盘-表示的是时针部分 -->
        <div class="time">
          <div class="time_within">
          <!-- 里圈的表盘-表示的是分针部分 -->
            <div class="branch"></div>
           </div>
        </div>
        <!-- 最中间的地球-表示指针的部分 -->
        <div class="earth">
            <img src="./images/earth.png" alt="">
        </div>
    </div>

css部分

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .earth_main {
            width: 100%;
            height: 100vh;
            background: #fff;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .time {
            width: 465px;
            height: 465px;
            border-radius: 465px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            background: rgba(57, 57, 57, 1);
            /*同样也是为了增加立体感*/
            border: 2px solid rgba(120, 120, 120, 1);
            transition: all 30s;
            position: relative;
        }

        .branch {
            width: 394px;
            height: 394px;
            border-radius: 394px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            background-image: radial-gradient(rgba(0, 0, 0, 1), rgba(139, 139, 139, 250));
            transition: 1s linear;
        }

        .branch>ul {
            width: 100%;
            height: 100%;
            z-index: 9999;
            display: flex;
            flex-flow: column;
            justify-content: space-between;
            align-items: center;
            position: relative;

        }

        .branch>ul>li {
            position: absolute;
            left: 50%;
            top: 50%;
            list-style: none;
            width: 50%;
            height: 2px;
            display: flex;
            flex-flow: row;
            justify-content: flex-end;
            align-content: center;
            transform-origin: left;
        }

        .branch>ul>li>span {
            width: 12px;
            height: 2px;
            background: #fff;
            color: #fff;
            font-size: 12px;
        }

        .earth {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -162px;
            margin-left: -162px;
            width: 324px;
            height: 324px;
            border-radius: 324px;
            box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 1);
            z-index: 5000;
            transition: 1s linear;
        }

        .earth img {
            width: 100%;
            height: 100%;
            border-radius: 100%;
            z-index: 2000;
            background: transparent;
        } 
    </style>

效果图

image_3.png

外圈表盘实现-时针部分

跟分钟表盘逻辑一样,但是时针表盘的刻度比较密,每个刻度之间是2.5度,所以我需要循环出144个指针。

js部分

function timeFun() {
  // 创建一个ul标签
  const Ul = document.createElement('ul');
    // 写一个循环,创建60个刻度
    for (let i = 0; i < 144; i++) {
      // 创建li标签当刻度
      const Li = document.createElement('li');
        // li标签里写一个span标签,背景色为白色
        Li.innerHTML = `<span style="margin-right:5px"></span>`
        // 每隔3个刻度要显示显示加重的刻度
        if (i % 3 === 0) {
           // 增加了span的宽度
           Li.innerHTML = `<span style="width: 12px;margin-right:5px"></span>`
         }
         // 表盘一共显示12个小时
         if (i % 12 === 0) {
           Li.innerHTML = `<span style="height:3px;width: 8px;margin-right:5px"><i>${i / 12 + 1}</i></span>`
          }
          // 每个刻度之间时2.5度
          Li.style.cssText = "transform:rotate(" + (i * 2.5) + "deg)";
          // 将li标签插入ul标签
          Ul.appendChild(Li);
    }
    // 将ul标签插入div标签
    time.appendChild(Ul);
}

css部分

        .time {
            width: 465px;
            height: 465px;
            border-radius: 465px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            background: rgba(57, 57, 57, 1);
            border: 2px solid rgba(120, 120, 120, 1);
            transition: all 30s;
            position: relative;
        }

         .time_within {
            width: 397px;
            height: 397px;
            border-radius: 397px;
            background: #000;
            display: flex;
            justify-content: center;
            align-items: center;
            position: absolute;
            left: 50%;
            top: 50%;
            margin-top: -198.5px;
            margin-left: -198.5px;
        }

        .time>ul {
            width: 100%;
            height: 100%;
            z-index: 9999;
            display: flex;
            flex-flow: column;
            justify-content: space-between;
            align-items: center;
            position: relative;
        }

        .time>ul>li {
            position: absolute;
            left: 50%;
            top: 50%;
            margin-top: -.5px;
            list-style: none;
            width: 50%;
            height: 2px;
            display: flex;
            flex-flow: row;
            justify-content: flex-end;
            align-content: center;
            transform-origin: left;
        }

        .time>ul>li>span {
            width: 6px;
            height: 2px;
            background: #fff;
            color: #fff;
            font-size: 12px;
            position: relative;
        }

        .time>ul>li>span>i {
            position: absolute;
            right: 12px;
            top: -6px;
            transform: rotate(90deg);
            font-style: normal;
        }

效果图

image_4.png

整体的html结构

让表盘整体旋转-60度。保证00分和12时向上。这也就是html的整体结构了。

<div class="earth_main">
        <div class="clock_dial">
        <!-- 最外圈的表盘-表示的是时针部分 -->
            <div class="time">
                <div class="time_within">
                    <!-- 里圈的表盘-表示的是分针部分 -->
                    <div class="branch"></div>
                </div>
            </div>
        </div>
        <!-- 最中间的地球-表示指针的部分 -->
        <div class="earth">
            <img src="./images/earth.png" alt="">
        </div>
    </div>

整体的css样式

<style>
        * {
            margin: 0;
            padding: 0;
        }

        .earth_main {
            width: 100%;
            height: 100vh;
            background: #fff;
            display: flex;
            justify-content: center;
            align-items: center;
            background-image: url('./images/00011.jpeg');
            background-repeat: no-repeat;
            background-size: 100%;
        }

       .clock_dial {
            transform: rotate(-60deg);
        }

        .time {
            width: 465px;
            height: 465px;
            border-radius: 465px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            background: rgba(57, 57, 57, 1);
            border: 2px solid rgba(120, 120, 120, 1);
            transition: all 30s;
            position: relative;
        }

         .time_within {
            width: 397px;
            height: 397px;
            border-radius: 397px;
            background: #000;
            display: flex;
            justify-content: center;
            align-items: center;
            position: absolute;
            left: 50%;
            top: 50%;
            margin-top: -198.5px;
            margin-left: -198.5px;
        }

        .time>ul {
            width: 100%;
            height: 100%;
            z-index: 9999;
            display: flex;
            flex-flow: column;
            justify-content: space-between;
            align-items: center;
            position: relative;
        }

        .time>ul>li {
            position: absolute;
            left: 50%;
            top: 50%;
            margin-top: -.5px;
            list-style: none;
            width: 50%;
            height: 2px;
            display: flex;
            flex-flow: row;
            justify-content: flex-end;
            align-content: center;
            transform-origin: left;
        }

        .time>ul>li>span {
            width: 6px;
            height: 2px;
            background: #fff;
            color: #fff;
            font-size: 12px;
            position: relative;
        }

        .time>ul>li>span>i {
            position: absolute;
            right: 12px;
            top: -6px;
            transform: rotate(90deg);
            font-style: normal;
        }

        .branch {
            width: 394px;
            height: 394px;
            border-radius: 394px;
            display: flex;
            justify-content: center;
            align-items: center;
            box-sizing: border-box;
            z-index: 3000;
            background-image: radial-gradient(rgba(0, 0, 0, 1), rgba(139, 139, 139, 250));
            transition: 1s linear;
        }

        .branch>ul {
            width: 100%;
            height: 100%;
            z-index: 9999;
            display: flex;
            flex-flow: column;
            justify-content: space-between;
            align-items: center;
            position: relative;

        }

        .branch>ul>li {
            position: absolute;
            left: 50%;
            top: 50%;
            list-style: none;
            width: 50%;
            height: 2px;
            display: flex;
            flex-flow: row;
            justify-content: flex-end;
            align-content: center;
            transform-origin: left;
        }

        .branch>ul>li>span {
            width: 12px;
            height: 2px;
            background: #fff;
            color: #fff;
            font-size: 12px;
        }

        .earth {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -162px;
            margin-left: -162px;
            width: 324px;
            height: 324px;
            border-radius: 324px;
            box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 1);
            z-index: 5000;
            transition: 1s linear;
        }

        .earth img {
            width: 100%;
            height: 100%;
            border-radius: 100%;
            z-index: 2000;
            background: transparent;
        } 
    </style>

整体的js部分

这部分也包含了最后让地球转动起来,分针表盘转动起来的js代码

      const branch = document.querySelector('.branch')
      const earth = document.querySelector('.earth')
      const time = document.querySelector('.time')

      window.onload = () => {
        branchFun()
        timeFun()
        tick()
      }
       function branchFun() {
         // 创建一个ul标签
         const Ul = document.createElement('ul');
         // 写一个循环,创建60个刻度
         for (let i = 0; i < 60; i++) {
           // 创建li标签当刻度
           const Li = document.createElement('li');
           // li标签里写一个span标签,背景色为白色
           Li.innerHTML = `<span style="margin-right:10px"></span>`
           // 每隔五个刻度要显示数字
           if (i % 5 === 0) {
             // 当为第五个刻度的时候span标签背景色为透明色,然后旋转90度。
             // 数字为小于10的时候要现实05或者00,所以做了一个判断
             // 因为数字是逆时针显示,所以用55-i,请看效果图
             Li.innerHTML = `<span style="margin-right:3px;background: transparent;transform: rotate(90deg);">${(55 - i) < 10 ? ('0' + (55 - i)) : (55 - i)}</span>`
           }
           // 每个li标签以左端为中点旋转6Li.style.cssText = "transform:rotate(" + (i * 6) + "deg)";
           // 将li标签插入ul标签
           Ul.appendChild(Li);
        }
        // 将ul标签插入div标签
        branch.appendChild(Ul);
     }

      function timeFun() {
        // 创建一个ul标签
        const Ul = document.createElement('ul');
        // 写一个循环,创建60个刻度
        for (let i = 0; i < 144; i++) {
          // 创建li标签当刻度
          const Li = document.createElement('li');
          // li标签里写一个span标签,背景色为白色
          Li.innerHTML = `<span style="margin-right:5px"></span>`
          // 每隔3个刻度要显示显示加重的刻度
          if (i % 3 === 0) {
             // 增加了span的宽度
             Li.innerHTML = `<span style="width: 12px;margin-right:5px"></span>`
            }
          // 表盘一共显示12个小时
          if (i % 12 === 0) {
              Li.innerHTML = `<span style="height:3px;width: 8px;margin-right:5px"><i>${i / 12 + 1}</i></span>`
          }
          // 每个刻度之间时2.5度
          Li.style.cssText = "transform:rotate(" + (i * 2.5) + "deg)";
          // 将li标签插入ul标签
          Ul.appendChild(Li);
          }
          // 将ul标签插入div标签
          time.appendChild(Ul);
       }

       let timerVal;
       function tick() {
         const TIME = new Date();
         const hour = TIME.getHours();
         const minute = TIME.getMinutes();
         const second = TIME.getSeconds();
         // 时针转动:转动角度是小时*30度+分钟*0.5度-52.5度。
         // 52.5度是地球上的指针默认指向的角度,所以每次转动我需要减去这部分
         earth.style.cssText = "transform:rotate(" + (775 - (775 - (hour * 30 + minute * 0.5) - 52.5)) + "deg)";
         // 分针转动:转动角度是分钟*6度+小时*30度+分钟*0.5度
         // 2度是我实在是不知道怎么产生的。我只能手动减去2度
         // console.log('分针转动:',((minute*6)+(hour * 30 + minute * 0.5))-2);
         branch.style.cssText = "transform:rotate(" + (((minute * 6) + (hour * 30 + minute * 0.5)) - 2) + "deg)";
        }
        timerVal = setInterval(tick, 1000);

最终效果

不要着急,仔细看,是会转的!

tsbea-alb5o.gif

总结

实现这个小东西我还是用了点时间的,在下文笔也不咋地,所以如果表述不清或者用词不当的地方请在评论区指正。如果有改进的建议或者更好的想法也请评论区留言。后期我准备把这个做成一个浏览器插件,当打开浏览器时就会显示这个蓝色星球。让我们一起守护我们的蓝色星球!

请大佬帮忙填坑

在这里我也把坑跟大家说一下。希望大家多多指正,如果那部分可以优化改进的也请各位大佬不吝指教。

坑一:

一开始我生成刻度时是生成刻度数的一半,然后两头当作刻度。但是这样虽然减少了循环,但是后期处理样式非常麻烦,因为每个刻度的数字都不是现在呈现的角度,需要旋转。但是这样两边的旋转角度是相反的,不好处理样式。

坑二:

第二个坑就是地球指针和分针表盘转动这部分。写的我懵懵的,一开始我是直接用小时和分钟数乘角度,当分钟角度转到360度时分钟就会从0开始,这样就会由360度迅速变回0度。当时加了一个动画过渡效果,就会瞬间转动一圈。因为不知道如何处理,所以我去掉了过渡效果。不知道怎么加比较好,如果有什么好的方法请告诉我。

坑三:

在分针表盘的js里我写了一个-2度,但是我至今不知道这2度是怎么形成的。但是不减去指针就不准确。有发现的大佬请告诉我。