欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS實(shí)現(xiàn)羊了個(gè)羊小游戲?qū)嵗?/h1>
 更新時(shí)間:2022年09月17日 11:46:32   作者:夕水  
這篇文章主要為大家介紹了JS實(shí)現(xiàn)羊了個(gè)羊小游戲示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

這兩天火爆全場的《羊了個(gè)羊》游戲,相信大家都玩過了,那么在玩這個(gè)游戲的同時(shí),我想大家都會(huì)好奇這個(gè)游戲的實(shí)現(xiàn),本文就帶大家使用css,html,js來實(shí)現(xiàn)一個(gè)動(dòng)物版的游戲。

首先我用到了2個(gè)插件,第一個(gè)插件就是flexible.js,這個(gè)插件就是對(duì)不同設(shè)備設(shè)置根元素字體大小,也就是一個(gè)移動(dòng)端的適配方案。

因?yàn)檫@里使用了rem布局,針對(duì)移動(dòng)端做了自適應(yīng),所以這里選擇采用rem布局方案。

rem布局方案

還有一個(gè)彈框插件,我很早自行實(shí)現(xiàn)的,就是popbox.js,關(guān)于這個(gè)插件,本文不打算講解實(shí)現(xiàn)原理,只講解一下使用原理:

popbox.js使用原理

ewConfirm({
    title: "溫馨提示", //彈框標(biāo)題
    content: "游戲結(jié)束,別灰心,你能行的!", //彈框內(nèi)容
    sureText: "重新開始", //確認(rèn)按鈕文本
    isClickModal:false, //點(diǎn)擊遮罩層是否關(guān)閉彈框
    sure(context) {
        context.close();
        //點(diǎn)擊確認(rèn)按鈕執(zhí)行的邏輯
    },//點(diǎn)擊確認(rèn)的事件回調(diào)
})

引入了這個(gè)js之后,會(huì)在window對(duì)象上綁定一個(gè)ewConfirm方法,這個(gè)方法傳入一個(gè)自定義對(duì)象,對(duì)象的屬性有title,content,sureText,cancelText,cancel,sure,isClickModal這幾個(gè)屬性,當(dāng)然這里沒有用到cancel按鈕,所以不細(xì)講。

正如注釋所說,每個(gè)屬性代表的意思,這里不做贅述。

html代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>羊了個(gè)羊《動(dòng)物版》</title>
    <link rel="stylesheet" href="./style.css" rel="external nofollow" >
</head>
<body>
</body>
<script src="https://www.eveningwater.com/static/plugin/popbox.min.js"></script>
<script src="https://www.eveningwater.com/test/demo/flexible.js"></script>
<script src="./script.js"></script>
</html>

可以看到html代碼是什么都沒有的,因?yàn)槔锩娴腄OM元素,我們都放在js代碼里面動(dòng)態(tài)生成了,所以script.js這里的代碼是核心,這個(gè)后續(xù)會(huì)講到,接下來看樣式代碼,也比較簡單。

樣式代碼

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body,
html {
    height: 100%;
    width: 100%;
    overflow: hidden;
}
body {
    background: url('https://www.eveningwater.com/my-web-projects/js/21/img/2.gif') no-repeat center / cover;
    display: flex;
    justify-content: center;
    align-items: center;
}
.ew-box {
    position: absolute;
    width: 8rem;
    height: 8rem;
}
.ew-box-item {
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 4px;
    border: 1px solid #535455;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
    cursor: pointer;
    transition: all .4s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.ew-collection {
    width: 8rem;
    height: 2.4rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 1rem;
    background: url('https://www.eveningwater.com/static/dist/20d6c430c2496590f224.jpg') no-repeat center/cover;
    position: fixed;
    margin: auto;
    overflow: auto;
    bottom: 10px;
}
.ew-collection > .ew-box-item {
    margin-right: 0.3rem;
}
.ew-left-source,
.ew-right-source {
    width: 2.6rem;
    height: 1.2rem;
    position: absolute;
    top: 0;
}
.ew-left-source {
    left: 0;
}
.ew-right-source {
    right: 0;
}
.ew-shadow {
    box-shadow: 0 0 50px 10px #535455 inset;
}

首先是通配選擇器'*'代表匹配所有的元素,并且設(shè)置樣式初始化,然后是html和body元素設(shè)置寬高為100%,并且隱藏溢出的內(nèi)容,然后給body元素設(shè)置了一個(gè)背景圖,并且body元素采用彈性盒子布局,水平垂直居中。

接下來是中間消除的盒子元素box,也很簡單就是設(shè)置定位,和固定寬高為8rem。

接下來是box-item,代表每一個(gè)塊元素,也就是消消樂的每一塊元素,接著羊了個(gè)羊底部有一個(gè)存儲(chǔ)選中塊元素的收集盒子元素,也就是ew-collection,然后是左右的看不到層級(jí)的卡牌容器元素。

最后就是為了讓塊元素看起來有層疊效果而添加的陰影效果。

javascript代碼

css核心代碼也就比較簡單,接下來我們來看javascript代碼。

導(dǎo)入圖片素材列表

在開始之前,我們需要先導(dǎo)入圖片素材列表,這里如下:

const globalImageList = [
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/1.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/2.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/3.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/4.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/5.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/6.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/7.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/8.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/9.jpg',
    'https://www.eveningwater.com/my-web-projects/jQuery/7/img/10.jpg'
]

然后在onload也就是頁面加載時(shí)調(diào)用我們封裝好的Game類,將這個(gè)素材列表傳入其中。如下:

window.onload = () => {
    const game = new Game(globalImageList);
}

接下來,我們來看Game類的核心代碼吧,首先定義這個(gè)類:

class Game {
    constructor(originSource, bindElement){
        //核心代碼
    }
}

這個(gè)類名有2個(gè)參數(shù),第一個(gè)參數(shù)就是素材列表,第二個(gè)參數(shù)則是綁定的DOM元素,默認(rèn)如果不傳入的話,就綁定到document.body上。也因此,我們?cè)跇?gòu)造函數(shù)里面初始化一些后續(xù)需要用到的變量。如下:

//constructor內(nèi)部
this.doc = document;
this.originSource = originSource;
this.bindElement = bindElement || this.doc.body;
// 存儲(chǔ)隨機(jī)打亂的元素
this.source = [];
// 存儲(chǔ)點(diǎn)擊的元素
this.temp = {};
// dom元素
this.box = null; //存儲(chǔ)消消樂塊元素的容器盒子元素
this.leftSource = null; //左邊素材容器元素
this.rightSource = null; //右邊素材容器元素
this.collection = null; //收集素材的容器元素
// 需要調(diào)用bind方法修改this指向
this.init().then(this.startHandler.bind(this)); //startHandler為游戲開始的核心邏輯函數(shù),init初始化方法

這里存儲(chǔ)了document對(duì)象,存儲(chǔ)了原始素材列表,以及綁定的dom元素,然后還定義了source用來存儲(chǔ)被打亂后的素材列表,以及temp用來存儲(chǔ)點(diǎn)擊的元素,方便做消除,添加陰影這些操作。

還有四個(gè)變量,其實(shí)也就是存儲(chǔ)dom元素的,如注釋所述。

接下來init方法就是做初始化的一些操作,這個(gè)方法返回一個(gè)Promise所以才能調(diào)用then方法,然后startHandler是游戲開始的核心邏輯函數(shù),這個(gè)后面會(huì)講到,注意這里有一個(gè)有意思的點(diǎn),那就是bind(this),因?yàn)樵趖hen方法內(nèi)部的this并不是指Game這個(gè)實(shí)例,所以需要調(diào)用bind方法修改this綁定,接下來我們來看init方法做了什么。

init() {
    return new Promise(resolve => {
        const template = `<div class="ew-box" id="ew-box"></div>
        <div class="ew-left-source" id="ew-left-source"></div>
        <div class="ew-right-source" id="ew-right-source"></div>
        <div class="ew-collection" id="ew-collection"></div>`;
        const div = this.create('div');
        this.bindElement.insertBefore(div, document.body.firstChild);
        this.createElement(div, template);
        div.remove();
        resolve();
    })
}

很顯然這個(gè)方法如前所述返回了一個(gè)Promise,內(nèi)部定義了template模板代碼,也就是頁面的結(jié)構(gòu),然后調(diào)用create方法創(chuàng)建一個(gè)容器元素,并且向body元素的首個(gè)子元素之前插入這個(gè)元素,然后在這個(gè)容器元素之前插入創(chuàng)建好的頁面結(jié)構(gòu),刪除這個(gè)容器元素,并且resolve出去,從而達(dá)到將頁面元素添加到body元素內(nèi)部。這里涉及到了兩個(gè)工具函數(shù),我們分別來看看它們,如下:

create(name) {
    return this.doc.createElement(name);
}

create方法其實(shí)也就是調(diào)用createElement方法來創(chuàng)建一個(gè)DOM元素,this.doc指的就是document文件對(duì)象,也就是說,create方法只是document.createElement的一個(gè)封裝而已。來看createElement方法。

createElement(el, str) {
    return el.insertAdjacentHTML('beforebegin', str);
}

createElement方法傳入2個(gè)參數(shù),第一個(gè)參數(shù)是一個(gè)DOM元素,第二個(gè)參數(shù)是一個(gè)DOM元素字符串,表示在第一個(gè)DOM元素之前插入傳入的模板元素。這個(gè)方法可以參考code-segment

startHandler函數(shù)實(shí)現(xiàn)

init方法說白了就是動(dòng)態(tài)創(chuàng)建元素的一個(gè)實(shí)現(xiàn),接下來就是startHandler函數(shù)的實(shí)現(xiàn)。

startHandler() {
    this.box = this.$('#ew-box');
    this.leftSource = this.$('#ew-left-source');
    this.rightSource = this.$('#ew-right-source');
    this.collection = this.$('#ew-collection');
    this.resetHandler();
    //后續(xù)還有邏輯
}

startHandler是核心實(shí)現(xiàn),所以不可能只有上面那么點(diǎn)代碼,但是我們要寫一步步的拆分,以上的代碼就做了2個(gè)邏輯,獲取DOM元素和重置。這里涉及到了一個(gè)$方法,如下:

$(selector, el = this.doc) {
    return el.querySelector(selector);
}

$方法傳入2個(gè)參數(shù),第一個(gè)參數(shù)為選擇器,是一個(gè)字符串,第二個(gè)參數(shù)為DOM元素,實(shí)際上就是document.querySelector的一個(gè)封裝。當(dāng)然還有一個(gè)$$方法,類似,如下:

$$(selector, el = this.doc) {
    return el.querySelectorAll(selector);
}

接下來是resetHandler方法,如下:

resetHandler() {
    this.box.innerHTML = '';
    this.leftSource.innerHTML = '';
    this.rightSource.innerHTML = '';
    this.collection.innerHTML = '';
    this.temp = {};
    this.source = [];
}

可以看到resetHandler方法確實(shí)是如其定義的那樣,就是做重置的,我們要重置用到的數(shù)據(jù)以及DOM元素的子節(jié)點(diǎn)。

讓我們繼續(xù),在startHandler也就是resetHandler方法的后面,添加這樣的代碼:

startHandler() {
    this.box = this.$('#ew-box');
    this.leftSource = this.$('#ew-left-source');
    this.rightSource = this.$('#ew-right-source');
    this.collection = this.$('#ew-collection');
    this.resetHandler();
    for (let i = 0; i < 12; i++) {
        this.originSource.forEach((src, index) => {
            this.source.push({
                src,
                index
            })
        })
    }
    this.source = this.randomList(this.source);
    //后續(xù)還有邏輯
}

可以看到這里實(shí)際上就是對(duì)素材數(shù)據(jù)做了一個(gè)添加和轉(zhuǎn)換操作,randomList方法顧名思義,就是打亂素材列表的順序。

randomList 工具方法

讓我們來看這個(gè)工具方法的源碼:

/**
* 打亂順序
* @param {*} arr 
* @returns 
*/
randomList(arr) {
    const newArr = [...arr];
    for (let i = newArr.length - 1; i >= 0; i--) {
        const index = Math.floor(Math.random() * i + 1);
        const next = newArr[index];
        newArr[index] = newArr[i];
        newArr[i] = next;
    }
    return newArr;
}

這個(gè)函數(shù)的作用就是將素材列表隨機(jī)打亂以達(dá)到隨機(jī)的目的,接下來,讓我們繼續(xù)。

startHandler() {
    this.box = this.$('#ew-box');
    this.leftSource = this.$('#ew-left-source');
    this.rightSource = this.$('#ew-right-source');
    this.collection = this.$('#ew-collection');
    this.resetHandler();
    for (let i = 0; i < 12; i++) {
        this.originSource.forEach((src, index) => {
            this.source.push({
                src,
                index
            })
        })
    }
    this.source = this.randomList(this.source);
    //后續(xù)還有邏輯
    for (let k = 5; k > 0; k--) {
        for (let i = 0; i < 5; i++) {
            for (let j = 0; j < k; j++) {
                const item = this.create('div');
                item.setAttribute('x', i);
                item.setAttribute('y', j);
                item.setAttribute('z', k);
                item.className = `ew-box-item ew-box-${i}-${j}-${k}`;
                item.style.position = 'absolute';
                const image = this.source.splice(0, 1);
                // 1.44為item設(shè)置的寬度與高度
                item.style.left = 1.44 * j + Math.random() * .1 * k + 'rem';
                item.style.top = 1.44 * i + Math.random() * .1 * k + 'rem';
                item.setAttribute('index', image[0].index);
                item.style.backgroundImage = `url(${image[0].src})`;
                const clickHandler = () => {
                    // 如果是在收集框里是不能夠點(diǎn)擊的
                    if(item.parentElement.className === 'ew-collection'){
                        return;
                    }
                    // 沒有陰影效果的元素才能夠點(diǎn)擊
                    if (!item.classList.contains('ew-shadow')) {
                        const currentIndex = item.getAttribute('index');
                        if (this.temp[currentIndex]) {
                            this.temp[currentIndex] += 1;
                        } else {
                            this.temp[currentIndex] = 1;
                        }
                        item.style.position = 'static';
                        this.collection.appendChild(item);
                        // 重置陰影效果
                        this.$$('.ew-box-item',this.box).forEach(item => item.classList.remove('ew-shadow'));
                        this.createShadow();
                        // 等于3個(gè)就消除掉
                        if (this.temp[currentIndex] === 3) {
                            this.$$(`div[index="${currentIndex}"]`, this.collection).forEach(item => item.remove());
                            this.temp[currentIndex] = 0;
                        }
                        let num = 0;
                        for (let i in this.temp) {
                            num += this.temp[i];
                        }
                        if (num > 7) {
                            item.removeEventListener('click', clickHandler);
                            this.gameOver();
                        }
                    }
                }
                item.addEventListener('click', clickHandler)
                this.box.append(item);
            }
        }
    }
}

這里的代碼很長,但是總結(jié)下來就二點(diǎn),添加塊元素,并為每個(gè)塊元素綁定點(diǎn)擊事件。我們知道羊了個(gè)羊每一個(gè)消除的塊元素都會(huì)有層疊的效果,那么我們這里也要實(shí)現(xiàn)同樣的效果,如何實(shí)現(xiàn)呢?

答案就是定位,我們應(yīng)該知道定位會(huì)分為層級(jí)關(guān)系,層級(jí)越高就會(huì)占上面,這里也是采用同樣的道理,這里之所以用3個(gè)循環(huán),就是盒子元素是分成5行5列的,所以也就是為什么循環(huán)是5的原因。

然后在循環(huán)內(nèi)部,我們就是創(chuàng)建每一個(gè)塊元素,每個(gè)元素都設(shè)置了x,y,z三個(gè)屬性,并且還添加了ew-box-${i}-${j}-${k}類名,很顯然這里的x,y,z屬性和這個(gè)類名關(guān)聯(lián)上了,這方便我們后續(xù)對(duì)元素進(jìn)行操作。

同樣的每個(gè)塊元素我們也設(shè)置了樣式,類名是'ew-box-item',同樣的每個(gè)塊元素也設(shè)置為絕對(duì)定位。

PS: 大家可能有些好奇為什么每個(gè)元素我都加一個(gè)'ew-'的前綴,其實(shí)也就是我個(gè)人喜歡給自己寫的代碼加的一個(gè)前綴,代表這是我自己寫的代碼的一個(gè)標(biāo)志。

接下來從素材列表中取出單個(gè)素材,取出的數(shù)據(jù)結(jié)構(gòu)應(yīng)該是{ src:'圖片路徑',index:'索引值' }這樣。然后將該元素設(shè)置背景圖,就是素材列表的圖片路徑,以及index屬性,還有l(wèi)eft和top偏移值,這里的left和top偏移值之所以是隨機(jī)的,也就是因?yàn)槊恳粋€(gè)塊元素都是隨機(jī)的。

接下來是clickHandler也就是點(diǎn)擊塊元素執(zhí)行的回調(diào),這個(gè)我們先不詳細(xì)敘述,我們繼續(xù)往后看,就是為該元素添加事件,利用addEventListener方法,并且將塊元素添加到box盒子元素中。

clickHandler函數(shù)內(nèi)部

讓我們繼續(xù)來看clickHandler函數(shù)內(nèi)部。

首先這里有這樣一個(gè)判斷:

if(item.parentElement.className === 'ew-collection'){
    return;
}

很簡單,當(dāng)我們的收集框里面點(diǎn)擊該元素,是不能觸發(fā)點(diǎn)擊事件的,所以這里要做判斷。

然后又是一個(gè)判斷,有陰影效果的都是多了一個(gè)類名'ew-shadow',有陰影效果代表它的層級(jí)最小,被疊加遮蓋住了,所以無法被點(diǎn)擊。

接下來獲取當(dāng)前點(diǎn)擊塊元素的index索引值,這也是為什么在添加塊元素之前會(huì)設(shè)置一個(gè)index屬性的原因。

然后判斷點(diǎn)擊的次數(shù),如果點(diǎn)擊的是同一個(gè),則在temp對(duì)象里面存儲(chǔ)點(diǎn)擊的索引值,否則點(diǎn)擊的是不同的塊元素,索引值就是1。

然后將該元素的定位設(shè)置為靜態(tài)定位,也就是默認(rèn)值,并且添加到收集框容器元素當(dāng)中去。

createShadow方法

接下來就是重置陰影效果,并且重新添加陰影效果。這里有一個(gè)createShadow方法,讓我們來揭開它的神秘面紗。如下:

createShadow(){
    this.$$('.ew-box-item',this.box).forEach((item,index) =&gt; {
        let x = item.getAttribute('x'),
            y = item.getAttribute('y'),
            z = item.getAttribute('z'),
            ele = this.$$(`.ew-box-${x}-${y}-${z - 1}`),
            eleOther = this.$$(`.ew-box-${x + 1}-${y + 1}-${z - 1}`);
        if (ele.length || eleOther.length) {
            item.classList.add('ew-shadow');
        }
    })
}

這里很顯然通過獲取x,y,z屬性設(shè)置的類名來確定是否需要添加陰影,因?yàn)橥ㄟ^這三個(gè)屬性值可以確定元素的層級(jí),如果不是在最上方,就能夠獲取到該元素,所以就添加陰影。注意$$方法返回的是一個(gè)NodeList集合,所以可以拿到length屬性。

接下來就是通過存儲(chǔ)的索引值等于3個(gè),代表選中了3個(gè)相同的塊,那就要從收集框里面移除掉該三個(gè)塊元素,并且重置對(duì)應(yīng)的index索引值為0。

接下來的for...in循環(huán)所做的操作當(dāng)然是統(tǒng)計(jì)收集框里面的塊元素,如果達(dá)到了7個(gè)代表槽位滿了,然后游戲結(jié)束,并且移除塊元素的點(diǎn)擊事件。我們來看游戲結(jié)束這個(gè)方法的實(shí)現(xiàn):

gameOver() {
    const self = this;
    ewConfirm({
        title: "溫馨提示",
        content: "游戲結(jié)束,別灰心,你能行的!",
        sureText: "重新開始",
        isClickModal:false,
        sure(context) {
            context.close();
            self.startHandler();
        }
    })
}

這也是最開始提到的彈框插件的用法,在點(diǎn)擊確認(rèn)的回調(diào)里面調(diào)用startHandler方法表示重新開始游戲,這沒什么好說的。

到這里,我們實(shí)現(xiàn)了中間盒子元素的每一個(gè)塊元素與槽位容器元素的對(duì)應(yīng)邏輯,接下來還有2點(diǎn),那就是被遮蓋看不到層級(jí)的兩邊塊元素集合。所以繼續(xù)看startHandler后續(xù)的邏輯。

startHandler后續(xù)的邏輯

startHandler() {
    this.box = this.$('#ew-box');
    this.leftSource = this.$('#ew-left-source');
    this.rightSource = this.$('#ew-right-source');
    this.collection = this.$('#ew-collection');
    this.resetHandler();
    for (let i = 0; i < 12; i++) {
        this.originSource.forEach((src, index) => {
            this.source.push({
                src,
                index
            })
        })
    }
    this.source = this.randomList(this.source);
    for (let k = 5; k > 0; k--) {
        for (let i = 0; i < 5; i++) {
            for (let j = 0; j < k; j++) {
                const item = this.create('div');
                item.setAttribute('x', i);
                item.setAttribute('y', j);
                item.setAttribute('z', k);
                item.className = `ew-box-item ew-box-${i}-${j}-${k}`;
                item.style.position = 'absolute';
                const image = this.source.splice(0, 1);
                // 1.44為item設(shè)置的寬度與高度
                item.style.left = 1.44 * j + Math.random() * .1 * k + 'rem';
                item.style.top = 1.44 * i + Math.random() * .1 * k + 'rem';
                item.setAttribute('index', image[0].index);
                item.style.backgroundImage = `url(${image[0].src})`;
                const clickHandler = () => {
                    // 如果是在收集框里是不能夠點(diǎn)擊的
                    if(item.parentElement.className === 'ew-collection'){
                        return;
                    }
                    // 沒有陰影效果的元素才能夠點(diǎn)擊
                    if (!item.classList.contains('ew-shadow')) {
                        const currentIndex = item.getAttribute('index');
                        if (this.temp[currentIndex]) {
                            this.temp[currentIndex] += 1;
                        } else {
                            this.temp[currentIndex] = 1;
                        }
                        item.style.position = 'static';
                        this.collection.appendChild(item);
                        // 重置陰影效果
                        this.$$('.ew-box-item',this.box).forEach(item => item.classList.remove('ew-shadow'));
                        this.createShadow();
                        // 等于3個(gè)就消除掉
                        if (this.temp[currentIndex] === 3) {
                            this.$$(`div[index="${currentIndex}"]`, this.collection).forEach(item => item.remove());
                            this.temp[currentIndex] = 0;
                        }
                        let num = 0;
                        for (let i in this.temp) {
                            num += this.temp[i];
                        }
                        if (num >= 7) {
                            item.removeEventListener('click', clickHandler);
                            this.gameOver();
                        }
                    }
                }
                item.addEventListener('click', clickHandler)
                this.box.append(item);
            }
        }
    }
    //從這里開始分析
    let len = Math.ceil(this.source.length / 2);
    this.source.forEach((item, index) => {
        let div = this.create('div');
        div.classList.add('ew-box-item')
        div.setAttribute('index', item.index);
        div.style.backgroundImage = `url(${item.src})`;
        div.style.position = 'absolute';
        div.style.top = 0;
        if (index > len) {
            div.style.right = `${(5 * (index - len)) / 100}rem`;
            this.rightSource.appendChild(div);
        } else {
            div.style.left = `${(5 * index) / 100}rem`;
            this.leftSource.appendChild(div)
        }
        const clickHandler = () => {
            if(div.parentElement.className === 'ew-collection'){
                return;
            }
            const currentIndex = div.getAttribute('index');
            if (this.temp[currentIndex]) {
                this.temp[currentIndex] += 1;
            } else {
                this.temp[currentIndex] = 1;
            }
            div.style.position = 'static';
            this.collection.appendChild(div);
            if (this.temp[currentIndex] === 3) {
                this.$$(`div[index="${currentIndex}"]`, this.collection).forEach(item => item.remove());
                this.temp[currentIndex] = 0;
            }
            let num = 0;
            for (let i in this.temp) {
                num += this.temp[i];
            }
            if (num >= 7) {
                div.removeEventListener('click', clickHandler);
                this.gameOver();
            }
        }
        div.addEventListener('click', clickHandler);
    });
    this.createShadow();
}

這里很顯然取的是source素材列表的一般來分別生成對(duì)應(yīng)的左右素材列表,同理,這里面的塊元素點(diǎn)擊事件邏輯應(yīng)該是和塊容器元素里面的邏輯是很相似的,所以沒什么好說的。我們主要看以下這段代碼:

let div = this.create('div');
div.classList.add('ew-box-item');
div.setAttribute('index', item.index);
div.style.backgroundImage = `url(${item.src})`;
div.style.position = 'absolute';
div.style.top = 0;
if (index > len) {
    div.style.right = `${(5 * (index - len)) / 100}rem`;
    this.rightSource.appendChild(div);
} else {
    div.style.left = `${(5 * index) / 100}rem`;
    this.leftSource.appendChild(div)
}

其實(shí)這里也很好理解,也就是同樣的創(chuàng)建塊元素,這里根據(jù)index > len來確定是添加到右邊素材容器元素還是左邊素材元素,并且它們的top偏移量應(yīng)該是一致的,主要不同在left和right而已,計(jì)算方式也很簡單。

注意這里是不需要設(shè)置x,y,z屬性的,因?yàn)椴恍枰玫皆O(shè)置陰影的函數(shù)。

到此為止,我們一個(gè)《羊了個(gè)羊——動(dòng)物版》的小游戲就完成了。

如有興趣可以參考源碼。

更多關(guān)于jS 羊了個(gè)羊小游戲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論