基于JavaScript實現(xiàn)年份數(shù)字拼圖效果
背景
時光荏苒,2022年又要收尾了,公司的年會是不是都安排上了?(順便問一嘴,您陽了嗎?)
前幾天看到一個年會抽獎系統(tǒng),功能十分的強大,其中有一個年份數(shù)字的拼圖效果深深的吸引了哥,決定深入探索一番。先看下具體的效果,圖中有個2022的年份數(shù)字。

實現(xiàn)原理
從效果能看出,實際就是將相應(yīng)卡片設(shè)置為高亮顏色拼成數(shù)字,實現(xiàn)原理大致是:
- 設(shè)計好數(shù)字(0-9)在橫向和縱向占據(jù)的卡片列數(shù)和行數(shù),比如上圖中的橫向為3列,縱向為5行;
- 針對每個數(shù)字(0-9)的形狀,獲取亮色卡片位置的坐標(biāo),從而得到每個數(shù)字的形狀坐標(biāo)數(shù)組;
- 根據(jù)每個數(shù)字的形狀坐標(biāo)、要展示數(shù)字的順序計算出具體的位置,將對應(yīng)坐標(biāo)卡片設(shè)置為亮色就可以了;
具體實現(xiàn)
1. 創(chuàng)建背景卡片
拼圖展示的數(shù)字是當(dāng)前的年份(2022),也就是4位數(shù)字。根據(jù)數(shù)字在橫行占3列,縱向占5行,數(shù)字前后間隔1列,為了美觀數(shù)字區(qū)域上下左右邊界要空出一行或者一列。所以整個背景卡片的列數(shù)和行數(shù)就有了:
行數(shù) = 5 + 1 + 1 = 7;
列數(shù) = 3 * 4 + 3(間隔) + 1 + 1 = 17;
const rowCount = 7;
const colCount = 17;
// 創(chuàng)建卡片
const createCard = () => {
const frag = document.createDocumentFragment();
for (let i = 0; i < rowCount; i++) {
for (let j = 0; j < colCount; j++) {
const item = document.createElement('div');
item.className = "item";
frag.appendChild(item);
}
}
document.querySelector('.container').appendChild(frag);
}2. 設(shè)置數(shù)字形狀坐標(biāo)
這個其實就是根據(jù)每個數(shù)字的形狀,記錄下形狀路徑上的每個點的坐標(biāo)。規(guī)則是從上到下,從左到右,找到所有路徑上的點。0-9的形狀坐標(biāo)數(shù)組如代碼所示,可以比照著上文中的圖片,確認下數(shù)字的形狀坐標(biāo)。
注意:如果想設(shè)計其他的數(shù)字字體展示形式,可以根據(jù)具體形狀收集路徑點坐標(biāo)。
// 0-9數(shù)字的坐標(biāo)形狀
const NUMBER_MATRIX = [
[
// 0
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[2, 2],
[0, 3],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 1
[1, 0],
[0, 1],
[1, 1],
[1, 2],
[1, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 2
[0, 0],
[1, 0],
[2, 0],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[0, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 3
[0, 0],
[1, 0],
[2, 0],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 4
[0, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[2, 4]
],
[
// 5
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 6
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2],
[0, 3],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 7
[0, 0],
[1, 0],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[2, 4]
],
[
// 8
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[0, 3],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 9
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
]
];3. 數(shù)字拼圖
第二步中,給出的數(shù)字形狀坐標(biāo)實際是單個數(shù)字展示時的坐標(biāo),如果多個數(shù)字并排展示,需要對每個數(shù)字的坐標(biāo)進行換算,換算規(guī)則主要有2條
- 因為數(shù)字是橫向排列的,所以每增加一個數(shù)字,x坐標(biāo)都要增加4列(包含一列數(shù)字間隔)
- 由于數(shù)字展示區(qū)域周邊上下左右都空了一行或者一列,所以x坐標(biāo)和y坐標(biāo)的開始位置,都是從(1,1)開始的。
// 根據(jù)數(shù)字形狀、當(dāng)前年份等信息,篩選出需要設(shè)置為亮色的卡片位置
const getHighlight = () => {
// 獲取當(dāng)前年份
let year = new Date().getFullYear() + "";
let step = 4,
xoffset = 1,
yoffset = 1,
highlight = [];
year.split('').forEach(n => {
highlight = highlight.concat(
NUMBER_MATRIX[n].map(item => {
return `${item[0] + xoffset}-${item[1] + yoffset}`;
})
);
xoffset += step;
});
return highlight;
}最后highlight返回的其實就是點坐標(biāo)字符串的數(shù)組,類似['1-1', '2-1']這種。
然后就可以根據(jù)返回的點坐標(biāo)數(shù)組進行繪制拼圖,其實就是將對應(yīng)坐標(biāo)的卡片添加高亮的樣式類名
const createHighLight = async (cards, hightLight) => {
for (let i = 0; i < hightLight.length; i++) {
const [col, row] = hightLight[i].split('-');
const index = Math.floor(row) * colCount + Math.floor(col);
cards[index].className = 'item highlight'
}
}最終實現(xiàn)效果如下圖所示:

延伸
上文中只是實現(xiàn)了靜態(tài)數(shù)字的拼圖展示效果,如果能夠讓數(shù)字動起來呢?比如實現(xiàn)一個寫字效果、或者倒計時變動數(shù)字效果,這些會讓拼圖更加的酷炫。我們下面實現(xiàn)一個寫字效果
其實,原理很簡單,只需要在繪制數(shù)字拼圖卡片時,將每個坐標(biāo)點的繪制,改成異步串行繪制就行了
const createHighLight = async (cards, hightLight) => {
for (let i = 0; i < hightLight.length; i++) {
await new Promise((resolve, reject) => setTimeout(resolve, 100));
const [col, row] = hightLight[i].split('-');
const index = Math.floor(row) * colCount + Math.floor(col);
cards[index].className = 'item highlight'
}
// 繪制結(jié)束后,循環(huán)繪制
await new Promise((resolve, reject) => setTimeout(resolve, 100));
drawData();
}具體實現(xiàn)效果如下所示:

注意:數(shù)字的繪制效果可能和我們正常的書寫筆畫順序不一致,這是因為坐標(biāo)點是按照從上到下,從左到右的順序收集的,其實可以調(diào)整坐標(biāo)點順序,讓它符合書寫筆畫的順序,就可以看到正常的書寫效果了,自己嘗試吧哈
總結(jié)
本文主要分析了數(shù)字拼圖效果的實現(xiàn)原理,實現(xiàn)核心就是要先確定每個數(shù)字的形狀坐標(biāo),然后根據(jù)形狀坐標(biāo)去繪制高亮卡片。最后在靜態(tài)數(shù)字拼圖效果的基礎(chǔ)之上,借助異步串行,實現(xiàn)了手寫字的效果,其他效果可以自己在此基礎(chǔ)上自己嘗試。
以上就是基于JavaScript實現(xiàn)年份數(shù)字拼圖效果的詳細內(nèi)容,更多關(guān)于JavaScript年份數(shù)字拼圖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
BootStrap fileinput.js文件上傳組件實例代碼
這篇文章主要介紹了BootStrap fileinput.js文件上傳組件實例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-02-02
學(xué)習(xí)JavaScript一定要知道的3個小技巧
這篇文章主要給大家分享的是學(xué)習(xí)JavaScript一定要知道的3個小技巧,通常在 Angular 或 React 項目中,code review 時看到一些老式的 JavaScript 代碼,就會將開發(fā)人員歸類為初學(xué)者,下面我們就來一起看看初學(xué)者需要知道的三個小技巧,需要的朋友可以參考一下2021-12-12
基于JavaScript實現(xiàn)年份數(shù)字拼圖效果
時光荏苒,2022年又要收尾了,公司的年會是不是都安排上了?前幾天看到一個年會抽獎系統(tǒng),功能十分的強大,其中有一個年份數(shù)字的拼圖效果深深的吸引了哥,決定用JS實現(xiàn)一下該效果,需要的可以參考一下2022-12-12
JavaScript中concat復(fù)制數(shù)組方法淺析
在本篇文章里小編給大家總結(jié)了關(guān)于JavaScript中concat復(fù)制數(shù)組方法知識點,有需要的朋友們可以學(xué)習(xí)下。2019-01-01

