最终效果

其实主要难点在于最左边的小时钟

指针的实现方式很简单,就是通过绝对定位将指针移到中间,然后以下边中间的位置为圆心旋转即可。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.clock-wrapper {
background-color: blue;
height: 200px;
width: 200px;
position: relative;
}
.pointer {
height: 80px;
width: 6px;
background-color: silver;
position: absolute;
top: 20px;
left: 97px; /* 100 - 6/2 */
transform: rotateZ(30deg);
transform-origin: center bottom;
}
</style>
</head>
<body>
<div class="clock-wrapper">
<div class="pointer"></div>
</div>
</body>
</html>

效果

秒针转起来的效果也很简单,通过定时器setInterval每隔一秒更新秒针的角度。

setInterval(() => {
let secAngle = new Date().getSeconds() * 6
let pointer = document.getElementsByClassName('pointer')[0]
pointer.style.transform = `rotateZ(${secAngle}deg)`
}, 1000)

现在就可以看到指针一跳一跳的了。但是呢,我希望指针平缓的走,那么可以设置CSS的 transition 属性

transition: all linear 1s;

安静的等待1s 会发现,当秒针从59到60的时候,会反向旋转。因为此时角度是变小的,360->0,所以考虑当指针刚好走一圈的那一秒,去除 transition 属性。

这样虽然不会倒转了,但是那一秒还是会蹦一下。

于是又想到每100ms更新一次,这样到360度时蹦的那一下就不明显了。感觉没有直接解决问题,是绕开了。。

这样一个会围绕圆心转的指针就做完了。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.clock-wrapper {
background-color: blue;
height: 200px;
width: 200px;
position: relative;
}
.pointer {
height: 80px;
width: 6px;
background-color: silver;
position: absolute;
top: 20px;
left: 97px; /* 100 - 6/2 */
transform-origin: center bottom;
}
</style>
</head>
<body>
<div class="clock-wrapper">
<div class="pointer"></div>
</div>
<script>
function getAngle() {
let date = new Date()
let secAngle = date.getSeconds() * 6 + date.getMilliseconds() * 6 / 1000;
return secAngle;
}
window.onload = () => {
let pointer = document.getElementsByClassName('pointer')[0];
pointer.style.transform = `rotateZ(${getAngle()}deg)`;
let timer = setInterval(() => {
let secAngle = getAngle();
pointer.style.transform = `rotateZ(${getAngle()}deg)`;
if (!secAngle) {
pointer.style.transition = null;
} else {
pointer.style.transition = 'all linear 100ms';
}
}, 100);
}
</script>
</body>
</html>

现在的问题是 表盘的刻度。实现12个小竖线,然后分别旋转。虽然我没有less不可以使用for循环,但是react可以循环啊……定位还是绝对定位,和指针一样。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<style>
.clock-wrapper {
background-color: blue;
height: 200px;
width: 200px;
border-radius: 100px;
position: relative;
}
.grad {
height: 10px;
width: 4px;
background-color: #fff;
position: absolute;
left: 98px;
top: 5px;
transform-origin: center 95px;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class Clock extends React.Component {
render() {
let hourArr = [...new Array(12).keys()]
let grad = hourArr.map((item) => {
return <div key={item} className="grad" style={{transform: `rotateZ(${item*30}deg)`}}></div>
}) return (
<div className="clock-wrapper">
{grad}
</div>
)
}
} ReactDOM.render(
<Clock />,
document.getElementById('root')
); </script>
</body>
</html>

效果:

这样完全没有难点了(本来就没有好吧……

完整代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<style>
.deTime {
position: relative;
height: 50px;
width: 300px;
padding: 5px;
background: linear-gradient(to bottom, #0071ff, #00b1ff);
display: flex;
font-family: TrebuchetMS,Rotobo,"Microsoft YaHei",sans-serif;
} .deTime .container {
position: relative;
height: 50px;
width: 50px;
border-radius: 150px;
box-shadow: #353535 0px 0px 1px 0px;
background: radial-gradient(#0040ff, #6adbff);
} .deTime .second {
height: 20px;
width: 1px;
top: 5px;
left: 24px;
background-color: #ff6363;
} .deTime .minute {
height: 16px;
width: 2px;
top: 9px;
left: 24px;
background-color: #8e8e8e;
} .deTime .hour {
height: 12px;
width: 2px;
top: 13px;
left: 24px;
background-color: #8e8e8e;
} .deTime .second, .deTime .minute, .deTime .hour {
position: absolute;
transform-origin: center bottom;
box-shadow: 0px 0px 2px 0px #000;
} .deTime .center {
width: 2px;
height: 2px;
border-radius: 1px;
background-color: #ffffff;
box-shadow: 0px 0px 3px 1px #8c8c8c;
position: absolute;
top: 24px;
left: 24px;
} .deTime .time {
line-height: 50px;
font-size: 36px;
color: #fff;
margin-left: 15px;
} .deTime .time span {
font-size: 22px;
} .deTime .date {
font-size: 13px;
color: #fff;
display: flex;
flex-flow: column;
margin-left: 15px;
padding: 6px 0;
} .deTime .date > div {
flex-basis: 50%;
} .grad {
height: 2px;
width: 1px;
background-color: #fff;
position: absolute;
left: 25px;
top: 1px;
transform-origin: center 24px;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class DeTime extends React.Component {
TRANSITION = '100ms linear';
NUMBER_TRANSLATION = ['日', '一', '二', '三', '四', '五', '六']; constructor() {
super()
this.state = {
hourAngle: 0,
minAngle: 0,
secAngle: 0,
transition: this.TRANSITION
}
} updateTime() {
let date = new Date() let secAngle = (date.getSeconds() + date.getMilliseconds() / 1000) * 6;
let minAngle = date.getMinutes() * 6 + secAngle / 60;
let hourAngle = (date.getHours() % 12) * 30 + minAngle / 12; let transition = this.TRANSITION
// 当秒针走到 0 的时候 角度其实是变小了 所以会倒着转 需要暂时删除 transition
if (this.state.secAngle > secAngle) transition = null; this.setState({
hourAngle: hourAngle,
minAngle: minAngle,
secAngle: secAngle,
transition: transition
})
} componentWillMount() {
this.updateTime(); this.timer = setInterval(() => { this.updateTime() }, 100);
} componentWillUnmount() {
this.timer && clearTimeout(this.timer);
} leadingZero(number) {
return number < 10 ? '0' + number : number
} render() {
let hourArr = [...new Array(12).keys()]
let grad = hourArr.map((item) => {
return <div key={item} className="grad" style={{transform: `rotateZ(${item*30}deg)`}}></div>
})
let state = this.state
let now = new Date() return (
<div className="deTime">
<div className="container">
{grad}
<div className="minute" style={{transform: 'rotateZ('+state.minAngle+'deg)'}}></div>
<div className="hour" style={{transform: 'rotateZ('+state.hourAngle+'deg)'}}></div>
<div className="second" style={{transition: state.transition, transform: 'rotateZ('+state.secAngle+'deg)'}}></div>
<div className="center"></div>
</div>
<div className="time">
{this.leadingZero(now.getHours())}:{this.leadingZero(now.getHours())}<span> {this.leadingZero(now.getSeconds())}</span>
</div>
<div className="date">
<div>星期{this.NUMBER_TRANSLATION[now.getDay()]}</div>
<div>{now.getFullYear()}年{now.getMonth()}月{now.getDate()}日</div>
</div>
</div>
)
}
} ReactDOM.render(
<DeTime/>,
document.getElementById('root')
); </script>
</body>
</html>

React 实现一个时钟的更多相关文章

  1. html5制作一个时钟

    试着用html5写一个时钟 记得开始这个随笔是几天前,一直保存在草稿里面,一直感觉有个东西搁在在那里,所以今天熬夜也要写完这篇博客!!!哈哈...不多说来上代码和思路. --------------- ...

  2. 用canvas绘制一个时钟

    实现一个时钟的绘制和时间的显示 一,首先是页面的搭建html部分以及一点点的css代码,因为css这块用的比较少,所以就没有单独出来: <!DOCTYPE html> <html l ...

  3. 深夜,用canvas画一个时钟

    深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...

  4. 通过H5的新标签canvas做出一个时钟的全过程,希望对初学者有帮助

    最近学习了H5中的一个新标签canvas并且用它做出了一个时钟,最下面是成品图像,还不错吧,这只是我学习中的一个小demo,做得有点粗糙,但终究是做出来了,以后再写自己的网页主页再做一个好看点放上去. ...

  5. 用react编写一个hello world

    我要分享的是用react搭建一个简单的hello world, 一个小demo, 大神请略过 首先看一下目录结构 创建一个目录, 用于存放demo mkdir reactHello cd reactH ...

  6. 4-13 Webpacker-React.js; 用React做一个下拉表格的功能: <详解>

    Rails5.1增加了Webpacker: Webpacker essentially is the decisions made by the Rails team and bundled up i ...

  7. D3.js(v3)+react 制作 一个带坐标与比例尺的柱形图 (V3版本)

    现在用D3.js + react做一个带坐标轴和比例尺的柱形图.我已经尽力把代码全部注释上了,最后我也会把完整柱形图代码奉上.如果还有疑惑的,可以去翻看一下我之前介绍的方法,以下方法都有介绍到. 还有 ...

  8. 利用javafx编写一个时钟制作程序

    1.首先创建一个时钟类,用于编写时钟的各种特有属性 package javaclock; /** * * @author admin */import java.util.Calendar;impor ...

  9. 基于 React 实现一个 Transition 过渡动画组件

    过渡动画使 UI 更富有表现力并且易于使用.如何使用 React 快速的实现一个 Transition 过渡动画组件? 基本实现 实现一个基础的 CSS 过渡动画组件,通过切换 CSS 样式实现简单的 ...

随机推荐

  1. What is REST API

    What is REST REST is acronym for REpresentational State Transfer. It is architectural style for dist ...

  2. React Native不同设备分辨率适配和设计稿尺寸单位px的适配

    React Native中使用的尺寸单位是dp(一种基于屏幕密度的抽象单位.在每英寸160点的显示器上,1dp = 1px),而设计师使用的是px, 这两种尺寸如何换算呢? 官方提供了PixelRat ...

  3. mysql安装完启动问题解决

    一.初始化报错问题: 1./usr/local/mysql/bin/mysqld --user=mysql --basedir=/usr/local/mysql --datadir=/usr/loca ...

  4. http://www.cnblogs.com/langjt/p/4281477.html

    http://www.cnblogs.com/langjt/p/4281477.html

  5. form表单内容JSON格式转化

    form表单提交时,对于Content-type为application/json是提交时需要转换成json格式,据说form enctype=‘application/json’这样就可以,然而在我 ...

  6. Java使用quartz实现作业调度

    在spring boot中使用quartz实现作业调度的功能,简单易用. 什么是Quartz? Quartz是Java领域最著名的.功能丰富的.开放源码的作业调度工具,几乎可以在所有的Java应用程序 ...

  7. 移动 web 适配

    一.移动 web 开发与适配 1.跑在手机端的 web 页面(H5 页面) 2.跨平台(PC 端.手机端 - 安卓.IOS) 3.基于 webview(终端开发技术的一个组件) 4.告别 IE 拥抱  ...

  8. 学习Acegi应用到实际项目中(8)- 扩展UserDetailsService接口

    一个能为DaoAuthenticationProvider提供存取认证库的的类,它必须要实现UserDetailsService接口: public UserDetails loadUserByUse ...

  9. vuex的mutations传值

    mutations是要通过方法触发的,用于更改store里的数据的.this.$store.commit("mutationsName") 例子: store.js import ...

  10. JavaScript 平时记录

    1,JS中的this 见下面例子,注意函数中的函数 中的this指的是window对象了!!! document.addEventListener('click', function (e) { co ...