11React = require ' react'
2+ PropTypes = require ' prop-types'
3+ CreateReactClass = require ' create-react-class'
24
3- module . exports = React . createClass
5+ ReactCountdownClock = CreateReactClass
46 _seconds : 0
57 _radius : null
68 _fraction : null
@@ -10,31 +12,19 @@ module.exports = React.createClass
1012
1113 displayName : ' ReactCountdownClock'
1214
13- propTypes :
14- seconds : React .PropTypes .number
15- size : React .PropTypes .number
16- weight : React .PropTypes .number
17- color : React .PropTypes .string
18- fontSize : React .PropTypes .string
19- font : React .PropTypes .string
20- alpha : React .PropTypes .number
21- timeFormat : React .PropTypes .string
22- onComplete : React .PropTypes .func
23- showMilliseconds : React .PropTypes .bool
24-
25- getDefaultProps : ->
26- seconds : 60
27- size : 300
28- color : ' #000'
29- alpha : 1
30- timeFormat : ' hms'
31- fontSize : ' auto'
32- font : ' Arial'
33- showMilliseconds : true
34-
35- componentWillReceiveProps : (props ) ->
36- @_seconds = props .seconds
37- @ _setupTimer ()
15+ componentDidUpdate : (props ) ->
16+ if props .seconds != @props .seconds
17+ @_seconds = props .seconds
18+ @ _setupTimer ()
19+
20+ if props .color != @props .color
21+ @ _clearBackground ()
22+ @ _drawBackground ()
23+ @ _updateCanvas ()
24+
25+ if props .paused != @props .paused
26+ @ _startTimer () if ! @props .paused
27+ @ _pauseTimer () if @props .paused
3828
3929 componentDidMount : ->
4030 @_seconds = @props .seconds
@@ -45,9 +35,10 @@ module.exports = React.createClass
4535
4636 _setupTimer : ->
4737 @ _setScale ()
48- @ _setupCanvas ()
38+ @ _setupCanvases ()
39+ @ _drawBackground ()
4940 @ _drawTimer ()
50- @ _startTimer ()
41+ @ _startTimer () unless @props . paused
5142
5243 _updateCanvas : ->
5344 @ _clearTimer ()
@@ -70,20 +61,32 @@ module.exports = React.createClass
7061 tick = @_seconds * tickScale
7162 if tick > 1000 then 1000 else tick
7263
73- _setupCanvas : ->
74- @_canvas = @refs .canvas
75- @_context = @_canvas .getContext ' 2d'
76- @_context .textAlign = ' center'
77- @_context .textBaseline = ' middle'
64+ _setupCanvases : ->
65+ @_background = @refs .background .getContext ' 2d'
66+ @_timer = @refs .timer .getContext ' 2d'
67+ @_timer .textAlign = ' center'
68+ @_timer .textBaseline = ' middle'
69+ if @props .onClick ?
70+ @refs .component .addEventListener ' click' , @props .onClick
7871
7972 _startTimer : ->
8073 # Give it a moment to collect it's thoughts for smoother render
8174 @_timeoutIds .push (setTimeout ( => @ _tick () ), 200 )
8275
83- _cancelTimer : ->
76+ _pauseTimer : ->
77+ @ _stopTimer ()
78+ @ _updateCanvas ()
79+
80+ _stopTimer : ->
8481 for timeout in @_timeoutIds
8582 clearTimeout timeout
8683
84+ _cancelTimer : ->
85+ @ _stopTimer ()
86+
87+ if @props .onClick ?
88+ @refs .component .removeEventListener ' click' , @props .onClick
89+
8790 _tick : ->
8891 start = Date .now ()
8992 @_timeoutIds .push (setTimeout ( =>
@@ -103,16 +106,20 @@ module.exports = React.createClass
103106 if @props .onComplete
104107 @props .onComplete ()
105108
109+ _clearBackground : ->
110+ @_background .clearRect 0 , 0 , @refs .timer .width , @refs .timer .height
111+
106112 _clearTimer : ->
107- @_context .clearRect 0 , 0 , @_canvas .width , @_canvas .height
108- @ _drawBackground ()
113+ @_timer .clearRect 0 , 0 , @refs .timer .width , @refs .timer .height
109114
110115 _drawBackground : ->
111- @_context .beginPath ()
112- @_context .globalAlpha = @props .alpha / 3
113- @_context .arc @_radius , @_radius , @_radius , 0 , Math .PI * 2 , false
114- @_context .arc @_radius , @_radius , @_innerRadius , Math .PI * 2 , 0 , true
115- @_context .fill ()
116+ @_background .beginPath ()
117+ @_background .globalAlpha = @props .alpha / 3
118+ @_background .fillStyle = @props .color
119+ @_background .arc @_radius , @_radius , @_radius , 0 , Math .PI * 2 , false
120+ @_background .arc @_radius , @_radius , @_innerRadius , Math .PI * 2 , 0 , true
121+ @_background .closePath ()
122+ @_background .fill ()
116123
117124 _formattedTime : ->
118125 decimals = (@_seconds <= 9.9 && @props .showMilliseconds ) ? 1 : 0
@@ -153,14 +160,49 @@ module.exports = React.createClass
153160 _drawTimer : ->
154161 percent = @_fraction * @_seconds + 1.5
155162 formattedTime = @ _formattedTime ()
156- @_context .globalAlpha = @props .alpha
157- @_context .fillStyle = @props .color
158- @_context .font = " bold #{ @ _fontSize (formattedTime)} #{ @props .font } "
159- @_context .fillText formattedTime, @_radius , @_radius
160- @_context .beginPath ()
161- @_context .arc @_radius , @_radius , @_radius , Math .PI * 1.5 , Math .PI * percent, false
162- @_context .arc @_radius , @_radius , @_innerRadius , Math .PI * percent, Math .PI * 1.5 , true
163- @_context .fill ()
163+ text = if (@props .paused && @props .pausedText ? ) then @props .pausedText else formattedTime
164+
165+ # Timer
166+ @_timer .globalAlpha = @props .alpha
167+ @_timer .fillStyle = @props .color
168+ @_timer .font = " bold #{ @ _fontSize (formattedTime)} #{ @props .font } "
169+ @_timer .fillText text, @_radius , @_radius
170+ @_timer .beginPath ()
171+ @_timer .arc @_radius , @_radius , @_radius , Math .PI * 1.5 , Math .PI * percent, false
172+ @_timer .arc @_radius , @_radius , @_innerRadius , Math .PI * percent, Math .PI * 1.5 , true
173+ @_timer .closePath ()
174+ @_timer .fill ()
164175
165176 render : ->
166- <canvas ref = ' canvas' className = " react-countdown-clock" width = {@props .size } height = {@props .size }></canvas >
177+ <div ref = ' component' className = " react-countdown-clock" >
178+ <canvas ref = ' background' style = { position : ' absolute' } width = {@props .size } height = {@props .size }></canvas >
179+ <canvas ref = ' timer' style = { position : ' absolute' } width = {@props .size } height = {@props .size }></canvas >
180+ </div >
181+
182+ ReactCountdownClock .propTypes =
183+ seconds : PropTypes .number
184+ size : PropTypes .number
185+ weight : PropTypes .number
186+ color : PropTypes .string
187+ fontSize : PropTypes .string
188+ font : PropTypes .string
189+ alpha : PropTypes .number
190+ timeFormat : PropTypes .string
191+ onComplete : PropTypes .func
192+ onClick : PropTypes .func
193+ showMilliseconds : PropTypes .bool
194+ paused : PropTypes .bool
195+ pausedText : PropTypes .string
196+
197+ ReactCountdownClock .defaultProps =
198+ seconds : 60
199+ size : 300
200+ color : ' #000'
201+ alpha : 1
202+ timeFormat : ' hms'
203+ fontSize : ' auto'
204+ font : ' Arial'
205+ showMilliseconds : true
206+ paused : false
207+
208+ module .exports = ReactCountdownClock
0 commit comments