這一節簡單的模仿一下人氣眼中的無重疊彈幕效果,也不賣關子了,下一節模仿頭部的標籤切換效果一談到彈幕相信大家多不陌生,平時看直播,那彈幕可是看的很歡啊。
人氣眼中的彈幕可能數量比較少的原因,是一種不重疊的彈幕。先看一下實現的效果:
無重疊彈幕效果
當你決定看下文之前,你需要注意幾點:
在canvas的api中並沒有圓角矩形的繪製方法,所以我們得自己寫乙個繪製圓角矩形的方法,一說到圓角矩形,對於我們前端可以說是小菜一碟了,border-radius早就用爛了:
矩形的圓角
由上面這幅圖,想必繪製圓角矩形的思路已經有了。這裡我們可以通過canvas中的弧線和直線組合成圓角矩形(這裡我就不過多的設定各個角的半徑了):
// ********************=
// canvas 圓角矩形的繪製
// ********************=
// @param x 左上角的x座標
// @param y 左上角的y座標
// @param w 寬度
// @param h 高度
// @param r 圓角半徑
// @param bg 背景顏色
barrage.prototype.drawroundrect = function(options) = options;
const context = this.context;
context.beginpath();
context.fillstyle = bg;
//左上角
context.arc(x + r, y + r, r, math.pi, math.pi * 3 / 2);
context.lineto(x + w - r, y);
//右上角
context.arc(x + w - r, y + r, r, math.pi * 3 / 2, 0);
context.lineto(x + w, y + h - r);
//右下角
context.arc(x + w - r, y + h - r, r, 0, math.pi / 2);
context.lineto(x + r, y + h);
//左下角
context.arc(x + r, y + h - r, r, math.pi / 2, math.pi);
context.lineto(x, y + r);
context.fill();
}複製**
這裡需要注意的是beginpath方法,這通常是新手的乙個坑:
這裡你可以實驗一下下面的例子:
context.strokestyle = "#fff";
context.rect(10,10,100,100);
context.stroke();
context.beginpath(); //去掉這段** 會導致重複繪製上面生成的四個子路徑
context.strokestyle = "#000";
context.rect(200, 200, 100, 100);
context.stroke();複製**
很巧的是,在canvas中提供計算文字寬度的方法,需要注意的是:
// ***************====
// 計算文字寬度
// ***************====
barrage.prototype.gettextwidth = function(font, text) 複製**
很遺憾的是,這裡並沒有獲取高度的屬性。。。。
上面我們已經知道了繪製圓角矩形和測量文字的寬度了,這裡我們只需要繪製文字即可,而你需要注意的是合理的利用textalign和textbaseline將文字調整到合適的位置,這裡我將文字居中於圓角矩形內部:
context.textbaseline = "middle";
context.textalign = "center";
context.filltext(text, x + width / 2, y + h / 2);複製**
對於這一條,我們一步步來:
1、初始化資料的基本資訊
初始化每個資料的字型、位置、速度等基本資訊,接下來繪製多需要這些引數,這些資料存放在data陣列中。
2、劃分車道
無重疊彈幕和道路上行駛的車輛類似,我們需要劃分車道,讓它們有序的運作在各自的車道中:
const pathheight = 10 + vp * 2 + size,
pathnumber = math.floor(h / pathheight);複製**
3、彈幕的狀態區分
彈幕我們可以區分為待顯示的彈幕、即將顯示的彈幕、未完全顯示的彈幕、完全顯示的彈幕和顯示完成的彈幕。這裡我們還需要宣告activearray儲存未完全顯示的彈幕和完全實現的彈幕,nextbarrage儲存即將顯示的彈幕。
4、待顯示彈幕
我們的彈幕是從左邊發射的,所以當乙個彈幕完全顯示出來,這個「車道」應該就要新增新的彈幕了:
// 部分**
if (item.x + item.w < width && item.status === 0) 複製**
5、新增待顯示彈幕
動畫執行的每一幀我們需要將待顯示彈幕加入到activearray陣列當中:
if (next.length > 0 && data.length > 0) 複製**
這裡的200並不是乙個隨意的數,因為我們在設定速度時,是設定1~1.25的隨機數,所以你建立乙個方程也就解出兩個彈幕之間的最小安全距離了。
6、動畫的暫停和恢復
暫停和恢復的根本就是要儲存暫停的繪製狀態,這裡可以通過canvas的getimagedata和putimagedata實現:
// **********====
// 動畫暫停與恢復
// **********====
barrage.prototype.pause = function () else
}複製**
到這裡,簡單的彈幕功能就完成了。
參考書籍: 《html5 canvas核心技術》源**
重構構建的平凡之路
剛開始做前端的時候,一直以為切好頁面是重構的全部職責,在切好頁面的前提,增加頁面互動,這樣已經能到重構的頂峰。直到進入公司後發現參與的專案都有兩個特點,專案複雜和參與人數的多,發現傳統的方法已經不適用。主要介紹自己重構構建經歷,如有問題歡迎指教!乀 乀 這裡介紹自己以往傳統重構的方法容易暴露的缺點。...
重構構建的平凡之路
剛開始做前端的時候,一直以為切好頁面是重構的全部職責,在切好頁面的前提,增加頁面互動,這樣已經能到重構的頂峰。直到進入公司後發現參與的專案都有兩個特點,專案複雜和參與人數的多,發現傳統的方法已經不適用。主要介紹自己重構構建經歷,如有問題歡迎指教!乀 乀 這裡介紹自己以往傳統重構的方法容易暴露的缺點。...
十年牧碼,我的平凡之路
我是乙個有著十年碼齡的無證程式設計師,如果算上996那就更長了。我有讀故事的喜好,別人的艱辛 遭遇 苦難,往往能化為我生活的勇氣和前進的動力。今天我想講講自己的故事,它雖不夠精彩和離奇,但卻如同那一行行 平淡 樸素而真實。平凡人的奮鬥 掙扎 彷徨,往往最能打動人心,因為有自己生活的影子。本人80後,...