最终效果

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

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

<!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. VB 读取列表文件名

    Private Sub Command1_Click()Dim d As String, s As String If Dir(App.Path & "\down", vb ...

  2. Spring-boot集成RabbitMQ踩过的坑

    1.java.net.SocketException: socket closed 官方文档已经说明,新建user和guest的账户是没有远程登录的权限的 需要对登录所用账户授权 解决方法: rabb ...

  3. 【信号与线性系统】为什么求解零输入响应时转移算子H(p)不能约分,但计算单位冲激响应时却可以约分?

    为什么求零输入响应rZI时转移算子H(p)不能约分? . . . 我们知道,求零输入响应rZI的实质其实是求解微分方程 D(p)r(t) = N(p)e(t) 的解.由于这里 e(t)=0 ,所以这是 ...

  4. IOS11导航栏自定义返回按钮被遮挡

    将file作为请求体传入到服务端. { WaitForSingleObject(handle, INFINITE); printf(" -- by MoreWindows( http://b ...

  5. O365 Manager Plus帮助台委派功能一览表

    O365 Manager Plus帮助台委派介绍 虽然Office 365允许您在全球任何地方工作,但它提供的管理功能十分不足.当一个组织分布在多个国家/地区时,一个管理员很难单独管理所有用户和邮箱. ...

  6. Linux的历史发展及应用

    Linux的基本介绍: Linux的历史: 操作系统,英语Operating System简称为OS.说道操作系统就需要先讲一讲Unix,UNIX操作系统,是一个强大的多用户.多任务操作系统,支持多种 ...

  7. 解决Chrome 70及以上版本的证书问题:Failed to load resource: net::ERR_CERT_SYMANTEC_LEGACY

    1.桌面必须要有Chrome 快捷方式 2.进入快捷方式属性 3.修改目标为:"C:\Program Files (x86)\Google\Chrome\Application\chrome ...

  8. Python开发——11.异常及异常处理

    一.异常 1.定义 异常及时程序运行时发生错误的信号 2.种类 异常分为语法错误和逻辑错误,语法错误在程序执行之前就应该改正. 常用异常 AttributeError 试图访问一个对象没有的树形,比如 ...

  9. 自学Python第一天

    大学毕业后在一家第三方小程序公司做客服,心有不甘,看着同学们有做安防售前的,有在政府.企业里面做网络工程师的.更有甚者天天搭建个云计算啥的都是家常便饭,再想想自己,堂堂网络工程专业,却做了客服,还是没 ...

  10. 基于面向方面和UML的实时系统建模研究

    一.基本信息 标题:基于面向方面和UML的实时系统建模研究 时间:2010 出版源:计算机技术与发展 领域分类:面向方向:实时系统:横切关注点:统一建模语言: 二.研究背景 问题定义:实时系统建模研究 ...