This is the sixth day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
This day to visit the blog to see a lot of big guy’s website have a clock thief pull style, I want to own a whole, think of as a front-end developer, reflect the front-end development technology moment to <())>, with CSS draw a! Let me show you the results:
Front knowledge
Here’s a summary of the knowledge points used:
rotateZ()function
RotateZ () The CSS function rotateZ() defines how to rotate elements on the Z axis without distorting them. The degree of its motion is defined by the specified Angle; If it is positive, it rotates clockwise, if it is negative, it rotates counterclockwise.
rotate()function
transform-origin
attribute
The transform-origin CSS property lets you change the origin of an element’s deformation.
The clock to achieve
-
Draw the center of the circle
Here I’m using the background vertical horizontal center +before pseudo-class drawn directly on the background
-
Draw the hour, minute and second hands and give them a scheduled task to make them spin
This is where rotateZ() is used, and the core code is as follows
<template> <div class="clock"> <! - clockwise - > < div class = "hour" > < div ref = "hr" class = "hr" > < / div > < / div > <! - the minute hand -- -- > < div class = "min" > < div ref = "mn" class = "mn" > < / div > < / div > <! - the second hand -- -- > < div class = "SEC" > < div ref = "sc" class = "sc" > < / div > < / div > < / div > < / template > < script lang = "ts" > import {ref, onMounted, onUnmounted } from 'vue' export default { setup() { const hr = ref<HTMLElement | null>(null) const mn = ref<HTMLElement | null>(null) const sc = ref<HTMLElement | null>(null) const timeChange = () => { let day = new Date() let hh = Day.gethours () * 30 // one hour to 30 degrees let mm = day.getminutes () * 6 // one scale let ss = day.getseconds () * 6 // one scale; (hr.value as HTMLElement).style.transform = `rotateZ(${hh + mm / 12}deg)` ; (mn.value as HTMLElement).style.transform = `rotateZ(${mm}deg)` ; (sc.value as HTMLElement).style.transform = `rotateZ(${ss}deg)` } let timer: any = null onMounted(() => { timeChange() timer = setInterval(timeChange, 1000) }) onUnmounted(() => { timer && window.clearInterval(timer) }) return { hr, mn, sc, } } } </script> <style scoped lang="scss"> .clock { width: 300px; height: 300px; border-radius: 50%; display: flex; justify-content: center; align-items: center; position: relative; &:before { content: ''; width: 15px; height: 15px; border-radius: 50%; position: absolute; z-index: 10; } .hour, .min, .sec { position: absolute; } .hour, .hr { width: 160px; height: 160px; } .min, .mn { width: 200px; height: 200px; } .sec, .sc { width: 230px; height: 230px; } .hr, .mn, .sc { display: flex; justify-content: center; border-radius: 50%; } .hr::before { content: ''; width: 8px; height: 80px; //background-color: #b03232; border-radius: 6px; } .mn::before { content: ''; width: 4px; height: 95px; //background-color: #fff; border-radius: 6px; } .sc::before { content: ''; width: 2px; height: 150px; //background-color: #fff; border-radius: 4px; } } </style>Copy the code
In the actual rotation, an entire element is rotated, not a pointer
-
Draw the dial background
This is where the most complex part of drawing a clock is, if we just use the Rotate () and transform-Origin properties, we’ll see the dial scale look like this
Why is that? The reason is very simple, because in the traversal process, each scale has its own height, with the accumulation of height, the origin of rotation of each scale is different, simply speaking, the center of the circle moves. Here’s the solution. Just center them with position: absolute.
<template> <div class="light"> <div class="clock"> <ul class="scaleBg"> <li v-for="i in 60" :key="i" class="scale" :style="scale(i)"></li> <li v-for="i in 12" :key="i" class="scaleNum" :style="scaleNum(i)"> <span :style="fScaleNum(i)">{{ i }}</span> </li> </ul> <div class="hour"> <div ref="hr" class="hr"></div> </div> <div class="min"> <div ref="mn" class="mn"></div> </div> <div class="sec"> <div ref="sc" class="sc"></div> </div> </div> </div> </template> <script lang="ts"> import { ref, onMounted, onUnmounted } from 'vue' export default { setup() { const hr = ref<HTMLElement | null>(null) const mn = ref<HTMLElement | null>(null) const sc = ref<HTMLElement | null>(null) const timeChange = () => { let day = new Date() let hh = Day.gethours () * 30 // one hour to 30 degrees let mm = day.getminutes () * 6 // one scale let ss = day.getseconds () * 6 // one scale; (hr.value as HTMLElement).style.transform = `rotateZ(${hh + mm / 12}deg)` ; (mn.value as HTMLElement).style.transform = `rotateZ(${mm}deg)` ; (sc.value as HTMLElement).style.transform = `rotateZ(${ss}deg)` } let timer: any = null onMounted(() => { timeChange() timer = setInterval(timeChange, 1000) }) onUnmounted(() => { timer && window.clearInterval(timer) }) const scale = (i: number) => { if (i === 0 || i % 5 === 0) { return { transform: `rotate(${i * 6}deg)`, height: '16px' } } else { return { transform: `rotate(${i * 6}deg)` } } } const scaleNum = (i: number) => { if (i === 12) { return { left: '146px', transform: `rotate(${i * 30}deg)` } } else { return { transform: Rotate (${I * 30}deg) '}}} const fScaleNum = (I: number) => {return {display: 'block', transform: `rotate(${-i * 30}deg)` } } return { hr, mn, sc, scale, scaleNum, fScaleNum } } } </script> <style scoped lang="scss"> .clock { width: 300px; height: 300px; border-radius: 50%; display: flex; justify-content: center; align-items: center; position: relative; //box-shadow: 0-15px rgba(255, 255, 255, 0.05), inset 0-15px rgba(255, 255, 255, 0.05), // 0 15px rgba(255, 255, 0.05), 255, 0.05), inset 0 15px 15px rgba(255, 255, 255, 0.05); &:before { content: ''; width: 15px; height: 15px; border-radius: 50%; position: absolute; //background: #fff; z-index: 10; } .hour, .min, .sec { position: absolute; } .hour, .hr { width: 160px; height: 160px; } .min, .mn { width: 200px; height: 200px; } .sec, .sc { width: 230px; height: 230px; } .hr, .mn, .sc { display: flex; justify-content: center; border-radius: 50%; } .hr::before { content: ''; width: 8px; height: 80px; //background-color: #b03232; border-radius: 6px; } .mn::before { content: ''; width: 4px; height: 95px; //background-color: #fff; border-radius: 6px; } .sc::before { content: ''; width: 2px; height: 150px; //background-color: #fff; border-radius: 4px; } } .scaleBg { position: relative; width: 100%; height: 100%; .scale { width: 2px; height: 6px; background: #fff; position: absolute; left: 150px; top: 0; transform-origin: center 150px; } .scaleNum { position: absolute; display: flex; justify-content: center; left: 148px; top: 30px; font-size: 12px; transform-origin: center 120px; } } .light { .clock { box-shadow: 0-15px 15px rgba(255, 255, 255, 0.05), inset 0-15px 15px rgba(255, 255, 255, 0.05), 0 15px 15px rgba(255, 255, 255, 255, gba, 0 Inset 0 15px 15px rgba(255, 255, 255, 0.05); &:before { background: #181818; } .hr::before { background-color: #b03232; } .mn::before { background-color: #525252; } .sc::before { background-color: #383737; } .scale { background: #181818; } } } .dark { .clock { box-shadow: 0-15px 15px rgba(255, 255, 255, 0.05), inset 0-15px 15px rgba(255, 255, 255, 0.05), 0 15px 15px rgba(255, 255, 255, 255, gba, 0 Inset 0 15px 15px rgba(255, 255, 255, 0.05); &:before { background: #fff; } .hr::before { background-color: #b03232; } .mn::before { background-color: #fff; } .sc::before { background-color: #fff; } .scale { background: #fff; } } } </style>Copy the code
conclusion
Technology to flexible use ah, CSS really strong ah!!