周末無事, 看到WEB QQ上的小時鍾挺可愛的, 於是尋思着用WPF模仿着做一個.
先看下WEB QQ的圖:
打開VS, 開始動工. 建立好項目后, 面對一個空盪盪的頁面, 首先想下時鍾是怎么構成的. 從圖中看到, 時鍾被一個黑色的圓環包圍, 里面有12個代表小時的刻度線, 等比例的分布在圓環內側. 中間有個小圓環, 是指針的中心. 3個小指針以圓的中心轉動.
第一步, 畫出外部的圓環:WPF里面只有橢圓, 怎么畫出一個圓環形狀呢, 其實很簡單. 里面放個小圓, 外面放個大圓. 小圓和大圓采用不同的背景, 看起來就是個圓環了.
第二步: 畫中間的中心圓, 這個沒什么好說的, 代碼省略.
第三步: 畫刻度: 12個刻度應該是每隔30度角度就放置一個, 而且應該和圓環內測對齊. 這里肯定需要用到WPF變換(RenderTransform)的知識. 如果我們只是以一個小矩形來做刻度, 通過一系列計算強行得到所在位置, 那么是很耗時耗力的. 這里可以想點簡單的法子. 比如, 我放一個剛好是內環寬度的Grid, 讓它以中心點做旋轉, 只讓他的最右側一點點顯示背景色, 這樣看起來是不是像刻度線呢.
第四步:開始復制粘貼, 把12個刻度線都擺好位置. 這里只需要改RotateTransform的Angle屬性, 從30加到360即可.
是不是有一點時鍾的輪廓了? 但是少了中間的指針, 那么現在需要來添加指針.
第五步: 添加3種指針: 指針是以時鍾的中心, 也就是上圖黑色的小圓的中心點來轉動的. 有了上面做刻度的經驗, 我們可以繼續在中間放幾個長長的Grid, 讓它以中心來旋轉, 同時把一半的部分顯示背景色, 這樣看起來就像指針了. 我以時針來做個例子:
第六步: 有了時針的例子在前面, 我們繼續添加分針和秒針. 我們可以把他們對應的Grid的寬度和高度做調整, 使時針變得胖一些, 秒針變得瘦一些.
現在,UI部分的設計已經完成了, 但是該怎么把這些UI元素和真實時間關聯起來呢? 我們在控制指針角度的時候, 有一個很重要的屬性, 就是RotateTransform.Angle. 這個屬性是個依賴屬性, 那么我們可以做一個綁定. 把當前時間綁定到每個指針的RotateTransform.Angle上, 並通過一個Converter來確定當前時間下, 每個指針應該轉動的角度. 我只列出Converter的部分代碼:

public class HandAngleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var dt = System.Convert.ToDateTime(value); var handType = parameter.ToString(); //簡單的算法 //時針轉動360度代表的是12個小時, 所以只需要取當前時間總秒數除以12個小時的秒數 //分針轉動360度代表的是60分鍾 //秒針轉動360度代表的是60秒 switch (handType) { case "hour": return System.Convert.ToDouble((dt.Hour * 3600 + dt.Minute * 60 + dt.Second) * 360) / (12 * 60 * 60); case "minute": return System.Convert.ToDouble((dt.Minute * 60 + dt.Second) * 360) / (60 * 60); case "second": return (dt.Second * 360) / 60; } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
同時, 我們前面復制粘貼了太多的Grid, 如果在真實項目中, 是會被同事和領導罵的. 所以我再做了一些優化, 把部分UI提到了資源里面. 真實的時鍾, 12點6點都會重點提示, 所以我把對應的刻度加了粗. 真正的指針間斷都是圓圓的, 所以我也做了些處理.
最后放一張實際運行的圖片吧, 它顯示了我敲下這段文字的時間: 11點09分.
最后, 還是附上源碼: 源碼下載 此源碼在VS2012下開發, VS2010 SP1可以正常打開.