创意时钟设计:带状时钟的实现

在浏览那些充斥着昂贵商品的杂志时,注意到了一种更实惠的选择,它没有防弹玻璃。

设计布局

使用Expression Blend设计了带状时钟。带子由包含TextBlock的Grid组成,这些Grid堆叠在一个Canvas类型的布局容器中。HourCanvas和其他一些元素构成了带子的视觉组件,它们被放置在另一个布局容器中,其ClipToBounds属性设置为True。

以下是当所有相关布局容器的ClipToBounds属性设置为False时的样子。

代码实现

确保正确显示时间的逻辑包含在一个名为TickTock的类中。当应用程序加载时,SetTimeOnLoad方法调用了几个方法来确保正确显示时间。

Public Sub SetTimeOnLoad() GetTime(currentHour, currentMinute_1, currentMinute_2) ' Highlight hour. DisplayTimeOnLoad(hourCanvas, currentHour, hourStartGrid, _ hourGridUpperLimit, hourGridLowerLimit) ' Highlight first part of minutes. DisplayTimeOnLoad(min1Canvas, currentMinute_1, min1StartGrid, _ min1GridUpperLimit, min1GridLowerLimit) ' Highlight second part of minutes. DisplayTimeOnLoad(min2Canvas, currentMinute_2, min2StartGrid, _ min2GridUpperLimit, min2GridLowerLimit) End Sub

GetTime方法设置了几个字段的当前时间值。

Private Sub GetTime(ByRef hour As Integer, ByRef min1 As Integer, ByRef min2 As Integer) hour = DateTime.Now.Hour If (hour > 12) Then hour -= 12 End If If (DateTime.Now.Minute.ToString.Length = 1) Then min1 = 0 min2 = CInt(DateTime.Now.Minute.ToString.Substring(0, 1)) Else min1 = CInt(DateTime.Now.Minute.ToString.Substring(0, 1)) min2 = CInt(DateTime.Now.Minute.ToString.Substring(1, 1)) End If End Sub

DisplayTimeOnLoad方法确保正确显示时间。

Private Sub DisplayTimeOnLoad(ByRef cnv As Canvas, ByVal currTime As Integer, _ ByVal startGrid As Integer, ByVal upperLimit As Integer, _ ByVal lowerLimit As Integer) If (currTime < startGrid) Then ' Move grids downwards. shift = (startGrid - currTime) * gridHeight While (shift > 0) For Each grd In cnv.Children initY = Canvas.GetTop(grd) newY = initY + 1 Canvas.SetTop(grd, newY) PlaceGridInLimitPosition(grd, upperLimit, lowerLimit) Next shift -= 1 Wend ElseIf (currTime > startGrid) Then ' Move grids upwards. shift = (currTime - startGrid) * gridHeight While (shift > 0) For Each grd In cnv.Children initY = Canvas.GetTop(grd) newY = initY - 1 Canvas.SetTop(grd, newY) PlaceGridInLimitPosition(grd, upperLimit, lowerLimit) Next shift -= 1 Wend End If End Sub

在上面的方法中,相关的Grid要么向上移动,要么向下移动,以便正确显示时间。PlaceGridInLimitPosition确保移动超出某个限制的Grid被相应地放置。

Private Sub PlaceGridInLimitPosition(ByRef grd As Grid, ByVal upperLimit As Integer, _ ByVal lowerLimit As Integer) If (upperLimit = hourGridUpperLimit) AndAlso (lowerLimit = hourGridLowerLimit) Then If (newY >= 280) Then Canvas.SetTop(grd, hourGridUpperLimit) ElseIf (newY <= -240) Then Canvas.SetTop(grd, hourGridLowerLimit) End If ElseIf (upperLimit = min1GridUpperLimit) AndAlso (lowerLimit = min1GridLowerLimit) Then If (newY >= 120) Then Canvas.SetTop(grd, min1GridUpperLimit) ElseIf (newY <= -160) Then Canvas.SetTop(grd, min1GridLowerLimit) End If ElseIf (upperLimit = min2GridUpperLimit) AndAlso (lowerLimit = min2GridLowerLimit) Then If (newY >= 200) Then Canvas.SetTop(grd, min2GridUpperLimit) ElseIf (newY <= -240) Then Canvas.SetTop(grd, min2GridLowerLimit) End If End If End Sub

TimeKeeper_Tick方法处理DispatcherTimer对象的Tick事件,其Interval属性设置为1秒,并确保时间变化时正确显示时间。

Private Sub TimeKeeper_Tick(ByVal sender As Object, ByVal e As EventArgs) GetTime(currHour, currMin1, currMin2) ' Set new hour. If (currentHour <> currHour) Then DisplayNewTime(hourCanvas, hourGridLowerLimit, hourGridUpperLimit) currentHour = currHour End If ' Set new first part of minutes. If (currentMinute_1 <> currMin1) Then DisplayNewTime(min1Canvas, min1GridLowerLimit, min1GridUpperLimit) currentMinute_1 = currMin1 End If ' Set new second part of minutes. If (currentMinute_2 <> currMin2) Then DisplayNewTime(min2Canvas, min2GridLowerLimit, min2GridUpperLimit) currentMinute_2 = currMin2 End If End Sub

DisplayNewTime方法导致执行动画,创建滚动效果。

Private Sub DisplayNewTime(ByRef cnv As Canvas, ByVal lowerLimit As Integer, _ ByVal upperLimit As Integer) For Each grd As Grid In cnv.Children initY = Canvas.GetTop(grd) If (initY <= upperLimit) Then dblGridAnim.Duration = TimeSpan.FromMilliseconds(1) dblGridAnim.To = lowerLimit dblGridAnim.FillBehavior = FillBehavior.HoldEnd grd.BeginAnimation(Canvas.TopProperty, dblGridAnim) Else newY = initY - gridHeight dblGridAnim.Duration = TimeSpan.FromMilliseconds(800) dblGridAnim.To = newY dblGridAnim.FillBehavior = FillBehavior.HoldEnd grd.BeginAnimation(Canvas.TopProperty, dblGridAnim) End If Next End Sub
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485