都在写抖音上的网红罗盘时钟,我也用vue仿写一个

先看效果

都在写抖音上的网红罗盘时钟,我也用vue仿写一个

直接上代码

<template>
  <div class="container">
    <div class="dateTimeBox yearBox isActive">{{nowYear}}年</div>
    <div id="monthArea" ref="monthArea">
      <div class="dateTimeBox" ref="monthBox" v-for="(item,index) in monthList" :key=""
        :class="{'isActive': item.isActive}">{{item.value}}
      </div>
    </div>
    <div id="dateArea" ref="dateArea">
      <div class="dateTimeBox" ref="dateBox" v-for="(item,index) in dateList" :key=""
        :class="{'isActive': item.isActive}">{{item.value}}</div>
    </div>
    <div id="hourArea" ref="hourArea">
      <div class="dateTimeBox" ref="hourBox" v-for="(item,index) in hourList" :key=""
        :class="{'isActive': item.isActive}">{{item.value}}</div>
    </div>
    <div id="minuteArea" ref="minuteArea">
      <div class="dateTimeBox" ref="minuteBox" v-for="(item,index) in minuteList" :key=""
        :class="{'isActive': item.isActive}">{{item.value}}
      </div>
    </div>
    <div id="secondArea" ref="secondArea">
      <div class="dateTimeBox" ref="secondBox" v-for="(item,index) in secondList" :key=""
        :class="{'isActive': item.isActive}">{{item.value}}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      nowYear: '',//当前年份
      monthList: [],//月份数组
      dateList: [],//日期数组
      hourList: [],//小时数组
      minuteList: [],//分钟数组
      secondList: [],//秒钟数组
    }
  },
  mounted() {
    var that = this;
    that.initTimeList();
  },
  methods: {
    //设置刻度
    initTimeList() {
      var that = this;
      for (var i = 1; i < 13; i++) {
        that.monthList.push({
          value: i + "月",
          isActive: false
        });
      }
      for (var i = 1; i < 32; i++) {
        that.dateList.push({
          value: i + "日",
          isActive: false
        });
      }
      for (var i = 0; i < 24; i++) {
        that.hourList.push({
          value: i + "时",
          isActive: false
        });
      }
      for (var i = 0; i < 60; i++) {
        that.minuteList.push({
          value: i + "分",
          isActive: false
        });
      }
      for (var i = 0; i < 60; i++) {
        that.secondList.push({
          value: i + "秒",
          isActive: false
        });
      }
      that.$nextTick(function () {
        that.initData();
      });
    },
    //初始化样式
    initData() {
      var that = this;
      //初始化月份样式
      that.setRoundStyle(that.$refs.monthBox, 60, 30);
      //初始化日期样式
      that.setRoundStyle(that.$refs.dateBox, 120, 360 / 31);
      //初始化小时样式
      that.setRoundStyle(that.$refs.hourBox, 180, 15);
      //初始化分钟样式
      that.setRoundStyle(that.$refs.minuteBox, 240, 6);
      //初始化秒钟样式
      that.setRoundStyle(that.$refs.secondBox, 300, 6);
      that.setNowDate();
      that.run();
    },
    /**
     * 设置圆圈样式
     * dataList:刻度数组, radius:半径, eachDeg:每个刻度间的度数
     */
    setRoundStyle(dataList, radius, eachDeg) {
      for (var i = 0; i < dataList.length; i++) {
        var translateX = Math.round(Math.cos(i * eachDeg * (Math.PI / 180)) * 1000000) / 1000000 * radius;
        var translateY = Math.round(Math.sin(i * eachDeg * (Math.PI / 180)) * 1000000) / 1000000 * radius;
        var rotateDeg = i * eachDeg;
        dataList[i].style.transform = "translate(" + translateX + "px, " + translateY + "px) rotate(" + rotateDeg + "deg)";
      }
    },
    //设置当前时间
    setNowDate() {
      var that = this;
      var nowDate = new Date();
      //当前年份
      that.nowYear = nowDate.getFullYear();
      //当前月份
      that.rotateBox(that.$refs.monthArea, nowDate.getMonth() * (-360 / 12), that.monthList[nowDate.getMonth()], nowDate.getMonth() - 1 < 0 ? that.monthList[that.monthList.length - 1] : that.monthList[nowDate.getMonth() - 1]);
      //当前日期
      that.rotateBox(that.$refs.dateArea, (nowDate.getDate() - 1) * (-360 / 31), that.dateList[nowDate.getDate() - 1], nowDate.getDate() - 2 < 0 ? that.dateList[that.dateList.length - 1] : that.dateList[nowDate.getDate() - 2]);
      //当前小时
      that.rotateBox(that.$refs.hourArea, nowDate.getHours() * (-360 / 24), that.hourList[nowDate.getHours()], nowDate.getHours() - 1 < 0 ? that.hourList[that.hourList.length - 1] : that.hourList[nowDate.getHours() - 1]);
      //当前分钟
      that.rotateBox(that.$refs.minuteArea, nowDate.getMinutes() * (-360 / 60), that.minuteList[nowDate.getMinutes()], nowDate.getMinutes() - 1 < 0 ? that.minuteList[that.minuteList.length - 1] : that.minuteList[nowDate.getMinutes() - 1]);
      //当前秒钟
      that.rotateBox(that.$refs.secondArea, nowDate.getSeconds() * (-360 / 60), that.secondList[nowDate.getSeconds()], nowDate.getSeconds() - 1 < 0 ? that.secondList[that.secondList.length - 1] : that.secondList[nowDate.getSeconds() - 1]);
    },
    /**
     * 旋转刻度
     * dateTimeArea:要旋转的区域,rotateDeg:转到当前时间所需要旋转的度数,dateTimeBox:当前时间刻度,lastdateTimeBox:前一个高亮的刻度
     */
    rotateBox(dateTimeArea, rotateDeg, dateTimeBox, lastdateTimeBox) {
      var that = this;
      dateTimeArea.style.transform = "rotate(" + rotateDeg + "deg)";
      dateTimeBox.isActive = true;
      lastdateTimeBox.isActive = false;
    },
    //动起来
    run() {
      var that = this;
      var timer;
      clearInterval(timer);
      timer = setInterval(function () {
        that.setNowDate();
      }, 1000);
    }
  }
}
</script>

<style scoped>
.container {
  width: 700px;
  height: 700px;
  position: relative;
  background-color: #000;
  color: #666;
}
.dateTimeBox {
  position: absolute;
  width: 80px;
  height: 20px;
  text-align: center;
  top: 50%;
  margin-top: -10px;
  left: 50%;
  margin-left: -40px;
}
#monthArea,
#dateArea,
#hourArea,
#minuteArea,
#secondArea {
  position: absolute;
  width: 100%;
  height: 100%;
  transition: transform 1s;
}
.isActive {
  color: #fff;
}
</style>

小结

比较简单的一个demo,就,也没想到有什么地方要特别交代的,代码都在上面,直接全部复制拉进一个vue页面就能用。本来想封装成一个组件,但想想也没有什么组件化的必要,就先这样,有问题可以问我。

注意

有小伙伴提问,就补一下:
就是有一个地方要注意一下,在vue中,mounted()阶段不会承诺所有的子组件也都一起被挂载,所以在此阶段,dom结构还没加载完的时候,如果直接在mounted里面操作dom比如要获取页面某些元素,console的时候能打出列表但length为0,直接用下标也无法获取对应内容而是直接出现undefined。

重现此问题的方法:
在mounted()里面对在页面上循环的数组内容进行初始化赋值,然后操作dom去取其中的元素。

解决方法:
想要确保所有的dom加载完,只要把相应的代码写在this.nextTick()的回调函数中就可以了。

上一篇:JS计算某个日期距今时间


下一篇:判断当前时间是否在某时间段内