canvas實(shí)現(xiàn)轉(zhuǎn)盤抽獎(jiǎng)

用canvas寫了一個(gè)簡單的轉(zhuǎn)盤抽獎(jiǎng)插件溅潜,

給大家參考下下肋演。抑诸。。


做的時(shí)候的想法是爹殊,通過傳進(jìn)來的標(biāo)簽以及屬性蜕乡,直接可以new出一個(gè)轉(zhuǎn)盤

如:var a = new createRound(obj,{...}) ;

因?yàn)槭怯胏anvas來寫梗夸,所以肯定會(huì)用到角度层玲,弧度了什么的,所以做好準(zhǔn)備工作:

1反症,角度轉(zhuǎn)弧度?

說明:因?yàn)?π弧度等于360度辛块,所以通過這個(gè)封裝成以下函數(shù)

function d2a(n){

? ? ? ?return n * Math.PI / 180;

};


2,n - m 區(qū)間獲取隨機(jī)數(shù)铅碍,一會(huì)后面會(huì)用到

function rnd(n,m){

? ? ? return parseInt(Math.random()*(m-n))+n;

};


3润绵,因?yàn)橐貜?fù)使用,所以想著用面向?qū)ο蟀福F(xiàn)在編輯構(gòu)造函數(shù)尘盼。根據(jù)我們開始定義的使用方法來傳值:

說明:

傳進(jìn)obj后士嚎,我們在obj里面添加創(chuàng)建一個(gè)canvas,并且給他賦值寬高悔叽,(canvas寬度以及高度莱衩,必須用屬性來寫,寫在樣式里會(huì)進(jìn)行拉伸哦)娇澎,所以我直接寫的是 this.oC.width = this.config.width ; 來定義屬性值笨蚁;

this.init() 里面放的時(shí)直接調(diào)用的一些函數(shù),之所以都放到this.config 的 json 里趟庄,是因?yàn)檫@樣更靈活括细,不用擔(dān)心順序而出現(xiàn)錯(cuò)誤,里面有一些在繪制時(shí)需要用到的值 和一些默認(rèn)值 戚啥;


4奋单,this.init() 里的內(nèi)容

說明:因?yàn)槿绻麤]有抽獎(jiǎng)信息的話,轉(zhuǎn)盤是不成立的猫十,所以做了初始判斷览濒,this.config.data ,如果沒有數(shù)據(jù)就 return 出去拖云;


5贷笛,畫弧,也可以說是畫圓

說明:

this.gd.save() : 保存畫布坐標(biāo)系統(tǒng)的狀態(tài)

this.gd.beginPath() : 重新畫(清除之前的路徑)

this.gd.closePath() : 閉合路徑(自動(dòng)連接到起始點(diǎn))

this.gd.restore() : 恢復(fù)save之后設(shè)置的狀態(tài)

可以簡單理解為調(diào)用restore之后宙项,restore方法前調(diào)用的rotate/translate/scale方法全部就還原了乏苦,畫布的坐標(biāo)系統(tǒng)恢復(fù)到save方法之前,但是這里要注意的是尤筐,restore方法的調(diào)用只影響restore之后繪制的內(nèi)容汇荐,對restore之前已經(jīng)繪制到屏幕上的圖形不會(huì)產(chǎn)生任何影響。(這段話是從網(wǎng)上找的盆繁,我自己總結(jié)不了這么清楚掀淘。。改基。) 繁疤;

接下來要開始繪制圓了

this.gd.moveTo( 起點(diǎn)x , 起點(diǎn)y ) ; 通過這連接其他地方

this.gd.arc(圓心x,圓心y秕狰,半徑稠腊,起始角度,結(jié)束角度) ?鸣哀,因?yàn)槔锩嫘枰?的是弧度架忌,所以我們剛才封裝的d2a(n) 用到了。

this.gd.fillStyle = 填充顏色我衬;

如上圖所示叹放,我們將它封裝好饰恕,因?yàn)橐粫?huì)轉(zhuǎn)盤內(nèi)部分塊的時(shí)候還需要用到;


我們要根據(jù)傳進(jìn)來的 data 來確定分成多少塊井仰,所以在上面 第 4 步的時(shí)候埋嵌,我們把數(shù)據(jù)傳進(jìn)去調(diào)用,

c 是數(shù)據(jù) 傳進(jìn)來的顏色 俱恶。

a 是起始角度雹嗦,從 0度 開始 減去偏移量,因?yàn)楫嫽《仁悄J(rèn)開始角度 是90度(如圖1所示)合是,所以需要減90(得到圖2) 想讓第一塊內(nèi)容在中心位置(如圖3)了罪,所以需要減去當(dāng)前塊的一半角度 360 / arr.length / 2,找了個(gè)變量將要減的值存儲(chǔ)下來 this.config.pyl 聪全。

b 是結(jié)束角度泊藕,值是(i + 1),也同樣需要減去偏移量难礼。

數(shù)據(jù)下新增 start 和 end 將起始角度和結(jié)束角度存儲(chǔ)下來 , ?因?yàn)檫@個(gè)需要填寫的是正確的角度 娃圆,所以需要將剛才減去的 90度 加上,后面的 90/arr.length 是在隨機(jī)區(qū)域內(nèi)的角度的時(shí)候 鹤竭,不到于太靠邊上踊餐。

調(diào)用剛才封裝好的 drow 函數(shù),并將值 傳進(jìn)去 循環(huán)創(chuàng)建多塊內(nèi)容


圖1
圖2?
圖3


6臀稚,繪制指針

說明:畫箭頭,用數(shù)組存儲(chǔ)位置三痰,這個(gè)箭頭稍微有點(diǎn)長吧寺,不過如果圓盤小的時(shí)候可以根據(jù)需要進(jìn)行適當(dāng)調(diào)整

this.gd.moveTo() : 起始位置定義為中心靠左 5 像素 ;

循環(huán)數(shù)組 連接 里點(diǎn)的點(diǎn) 散劫,接著做了一個(gè)陰影的處理稚机,設(shè)置了箭頭的顏色 ;

找了半天沒有找到怎么移動(dòng)自己劃出來的圖形的方法获搏,因?yàn)閳D形是由點(diǎn)連成線繪制赖条,所以也沒法使用 translate 或者 rotate ,所以將它轉(zhuǎn)換成圖片常熙,然后對圖片進(jìn)行操作纬乍,當(dāng)圖片加載完成后,調(diào)用 _this.clearOther(0) 函數(shù)裸卫,下面會(huì)對該函數(shù)說明仿贬。


7,為指針轉(zhuǎn)動(dòng)做準(zhǔn)備工作

說明:當(dāng)指針旋轉(zhuǎn)的時(shí)候必須清空畫布墓贿,要不然會(huì)連續(xù)繪制茧泪,達(dá)不到我們想要的效果蜓氨,所以里面的好多內(nèi)容需要重新繪制润文,上面對代碼有備注潦俺,大家可以看一下

旋轉(zhuǎn)箭頭時(shí)攻冷,rotate并鸵,默認(rèn)以畫布左上角為支點(diǎn)笑陈,箭頭生成的圖片與畫布大小一樣跌帐,我們要以畫布的中心對箭頭進(jìn)行旋轉(zhuǎn)明肮,所以我們需要先將箭頭 移到 中心位置窄陡,translate 后棘钞,與剛才不同的是 支點(diǎn) 移動(dòng)到中心位置缠借,但是整體位置已經(jīng)偏移,所以在 rotate 后 我們需要將 圖片自身 的位置 定義為 負(fù)值宜猜,讓圖片回到自己最初的位置


8泼返,指針轉(zhuǎn)動(dòng)到指定位置

說明:因?yàn)橐粡垐D無法截取完整代碼,所以分兩張圖姨拥。

因?yàn)槭钱?dāng)用戶觸發(fā)時(shí)開啟定時(shí)器绅喉,所以為了防止用戶在連續(xù)開啟定時(shí)器,所以叫乌,首先定義一個(gè)開關(guān)柴罐,當(dāng)用戶點(diǎn)擊時(shí) 判斷 是否在進(jìn)行,如果在 進(jìn)行憨奸,就 return 出來革屠,如果沒有進(jìn)行,定義值排宰,現(xiàn)在開始進(jìn)行似芝,當(dāng)運(yùn)動(dòng)結(jié)束后,改變值板甘,記錄運(yùn)動(dòng)已經(jīng)結(jié)束党瓮。

因?yàn)楫?dāng)將方法是在用戶觸發(fā)時(shí)調(diào)用,所以當(dāng)用戶調(diào)用時(shí)需要將中獎(jiǎng)id傳參進(jìn)去盐类,循環(huán)數(shù)據(jù)寞奸,將每個(gè)數(shù)據(jù)索引存儲(chǔ)起來,進(jìn)行判斷在跳,如果當(dāng)前索引下數(shù)據(jù)的 id 等于 傳參進(jìn)來的 id 則將該中獎(jiǎng)索引記錄下來枪萄,然后獲取到數(shù)據(jù)該索引下的內(nèi)容,將之前存儲(chǔ)的 起始角度(start)和 結(jié)束角度 (end ) 取出來硬毕,通過隨機(jī)數(shù)呻引,找到其區(qū)域內(nèi)的角度 為 目標(biāo)角度(t)。

n 為當(dāng)前進(jìn)行的角度 吐咳,默認(rèn)快速旋轉(zhuǎn)3圈后逻悠,開始慢慢減速元践,所以當(dāng) n > 360*3 ( 3 圈分界線 ) 的角度后,開始慢慢減速童谒,(可能大家有疑問单旁,為什么要給 t 加上 360 ,是因?yàn)槿绻?t 等于 10度 或者特別小的度數(shù)的時(shí)候饥伊,由慢變慢的過程不明顯象浑,所以又加了360,讓它有個(gè)慢慢減速的過程)琅豆。當(dāng)進(jìn)行的角度 減去 分割線后 大于 等于 目標(biāo)角度(t)后愉豺,證明已經(jīng)到達(dá)角度終點(diǎn),停止定時(shí)器茫因,將進(jìn)行角度 歸 0蚪拦。


用戶點(diǎn)擊時(shí)調(diào)用該方法


9,繪制獎(jiǎng)品信息冻押,展示數(shù)據(jù)提供的文字信息驰贷,進(jìn)行封裝

this.gd.textBaseline = ' top ' ; ?字體位置,如下圖所示:

this.gd.textAlign = ' center ' ; ? 如下圖所示:

this.gd.translate(this.config.cx,this.config.cy); 將字體默認(rèn)定義在畫布中心洛巢,本來的算用 rotate 來處理文字的角度括袒,但是用了之后,文字位置角度是正確了稿茉,可是文字本身角度也進(jìn)行了調(diào)整锹锰,所以沒辦法,只好通過文字自身的 x , y 來調(diào)整所處的正確位置狈邑。

var x = Math.sin(d2a(i*360/l)) * (this.config.r - 50); ? 因?yàn)榻嵌群托本€的位置我們是已知的(因?yàn)槲覀兌x所有文字據(jù)中心的位置都是相等的 相當(dāng)于半徑 城须,所以我們知道斜線位置,角度就是 360 除以 份數(shù)后 乘以 i 得出來的值)米苹,然后通過下圖公式去求出 x 值,y 值也是同樣方法砰琢。(學(xué)好數(shù)理化蘸嘶,走遍天下都不怕,驕傲臉 ^_^ )

this.gd.fillText(str,x,-y)陪汽; 將設(shè)置好的值傳進(jìn)去训唱,就可以定義好文字的位置了,因?yàn)?y 值 的 0 位置在畫布中心挚冤,所以當(dāng)位置在上面時(shí)自然就成了負(fù)值 (大家不要用 x軸y軸的想法去想哦)况增。


10,循環(huán)數(shù)據(jù)训挡,給數(shù)據(jù)中的不同文字定義不同位置

說明:循環(huán)數(shù)據(jù)澳骤,使用之前封裝好的方法將數(shù)據(jù)下的每一份的文字定義位置歧强。


11,封裝成功为肮,開始調(diào)用

說明:這個(gè)是自己弄的假數(shù)據(jù) 摊册,大家可根據(jù)后臺(tái)提供的不同數(shù)據(jù)來對代碼進(jìn)行,適當(dāng)?shù)恼{(diào)整


寫到這颊艳,轉(zhuǎn)盤抽獎(jiǎng)就差不多完了茅特,第一次總結(jié)自己寫的小demo,有不對的地方歡迎大家多多指教棋枕,在寫的時(shí)候 是按照 自己封裝好后的代碼順序 一塊一塊進(jìn)行的白修,大家看著可能有些亂,可以去 github 上下載代碼進(jìn)行參考重斑,看起來會(huì)更直觀一點(diǎn)兵睛。

地址:https://github.com/juanjuanGit/rotary-draw.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绸狐,隨后出現(xiàn)的幾起案子卤恳,更是在濱河造成了極大的恐慌,老刑警劉巖寒矿,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件突琳,死亡現(xiàn)場離奇詭異,居然都是意外死亡符相,警方通過查閱死者的電腦和手機(jī)拆融,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啊终,“玉大人镜豹,你說我怎么就攤上這事±渡” “怎么了趟脂?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長例衍。 經(jīng)常有香客問我昔期,道長,這世上最難降的妖魔是什么佛玄? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任硼一,我火速辦了婚禮,結(jié)果婚禮上梦抢,老公的妹妹穿的比我還像新娘般贼。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布哼蛆。 她就那樣靜靜地躺著蕊梧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪人芽。 梳的紋絲不亂的頭發(fā)上望几,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天,我揣著相機(jī)與錄音萤厅,去河邊找鬼橄抹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛惕味,可吹牛的內(nèi)容都是我干的楼誓。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼名挥,長吁一口氣:“原來是場噩夢啊……” “哼疟羹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起禀倔,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤榄融,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后救湖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愧杯,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年鞋既,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了力九。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邑闺,死狀恐怖跌前,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陡舅,我是刑警寧澤抵乓,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站靶衍,受9級特大地震影響臂寝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摊灭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望败徊。 院中可真熱鬧帚呼,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沈自,卻和暖如春酌儒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枯途。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工忌怎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酪夷。 一個(gè)月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓榴啸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晚岭。 傳聞我的和親對象是個(gè)殘疾皇子鸥印,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容