国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

HTML 簡單拼圖游戲

eechen / 2267人閱讀

摘要:基本需求有一個固定區域,被拆分成個同等大小的碎片,拿走其中一塊,靠近缺口的塊可以向缺口方向移動當拼出原來的圖樣視為完成。左右移動很簡單,序號大的序號小的即可。

先不廢話,請看演示。


公司要搞這么個微信活動,可現在沒有前端開發,沒辦法,身為打雜總監只好臨時頂下這個空缺了。先找了一些 JS 代碼,試用了下都不太理想,好一點的寫的又太復雜,改起來有難度,干脆擼起袖子自己干。

基本需求

有一個固定區域,被拆分成 c*r 個同等大小的碎片,拿走其中一塊,靠近缺口的塊可以向缺口方向移動;當拼出原來的圖樣視為完成。

依照此需求,需要經歷 加載圖片-》拆分圖片-》隨機打散-》移動碎片-》判定完成 這些步驟。為了更有可玩性,能自行選擇自己的圖片就更妙了。

下面就重點說明下各個步驟,為編寫方便,引入 jQuery 作為輔助庫。

加載圖片

首先當然是載入圖片,計算寬高,對比拼圖區域的尺寸進行縮放,如果比例不同,還得“裁剪”掉多余的部分。

/**
 * 加載圖片
 * cal 的回調參數為:
 *  ox 橫向偏移
 *  oy 縱向偏移
 *  this 指向載入的圖片的 jQuery 對象
 * @param {String} src 圖片路徑
 * @param {int} w 額定寬
 * @param {int} h 額定高
 * @param {Fucntion} cal 加載完成后的回調方法
 */
function loadr(src, w, h, cal) {
    var img  =  new Image();
    img.onload = function() {
        var xw = img.width ;
        var xh = img.height;
        var zw = xh * w / h;
        if (zw > xw) {
            // 寬度優先
            img.width   = w;
            img.height  = xh * w / xw;
            xh = (h - img.height) / 2;
            xw = 0;
        } else {
            // 高度優先
            img.height  = h;
            img.width   = xw * h / xh;
            xw = (w - img.width ) / 2;
            xh = 0;
        }

        cal.call(img, xw, xh);
    };
    img.src = src ;
}

以上的“裁剪”僅僅是計算出偏移,然后將其傳遞給加載就緒的回調函數。

拆分圖片

圖有了,已縮放,現在需要“拆分”成碎片。這里自然不是真的切割了,而是將圖片 clone 出 c*r 片,然后利用負的坐標定位,其實質是用一個塊遮蓋了“切除”的部分,僅顯示需要的碎片部分。

/**
 * 拆分圖片
 * @param {jQuery} that 容器對象
 * @param {int} cols 行
 * @param {int} rows 列
 * @param {int} ew 板塊寬度
 * @param {int} eh 板塊高度
 * @param {int} ox 圖片橫向偏移
 * @param {int} oy 圖片縱向偏移
 * @param {Image} im 圖片對象
 */
function split(that, cols, rows, ew, eh, ox, oy, im) {
    that.empty();

    for(var j = 0 ; j < rows; j ++) {
        for(var i = 0 ; i < cols; i ++) {
            var k = i + j * rows;

            var pic = $("
"); pic.attr("id", "pt-pic-"+k); pic.data("idx", k); pic.appendTo(that); pic.css ({ "position": "relative", "overflow": "hidden", "border" : "0", "width" : ew + "px", "height" : eh + "px" }); var img = $(im.cloneNode()); img.appendTo(pic); img.css ({ "position": "absolute", "z-index" : "88", "border" : "0", "left" : (0 - i * ew + ox) + "px", "top" : (0 - j * eh + oy) + "px" }); // 因邊框可能影響寬高計算, 故邊框多帶帶用一個塊來放 var bor = $("
"); bor.appendTo(pic); bor.css ({ "position": "absolute", "z-index" : "99", "width" : "100%", "height" : "100%" }); // 由于樣式寬高并不含邊框, 故再次計算尺寸的偏移量 bor.css ({ "width" : (2 * bor.width () - bor.outerWidth ()) + "px", "height" : (2 * bor.height() - bor.outerHeight()) + "px" }); } } }

稍微注意,為方便人眼分辨碎片,最好給碎片加個邊框,但加邊框必然影響坐標的計算,故在圖片上再覆蓋一層,邊框設在他上面,就算加個撕裂效果的透明圖做邊框都沒問題了。這樣碎片內圖片的偏移坐標的計算就少了些麻煩了。

隨機打散

這游戲當然是跟電腦玩了,總不能自己打散自己玩吧?但這個打散不能給每個圖片一個隨機位置,那很可能你永遠也拼不回去了。小時拿那種拼圖游戲板整人就干過這種事,故意摳下來把頭和腳交換再打散,然后跟其他小朋友打賭。所以程序也得守規矩一塊一塊的移動。

/**
 * 打散圖片
 * @param {jQuery} that 容器對象
 * @param {int} cols 列
 * @param {int} rows 行
 * @param {int} rand 打散步數
 */
function upset(that, cols, rows, rand) {
    var v ;
    var r = Math.floor(Math.random()  *  cols  *  rows);
    var hole = that.children().eq(r).addClass("pt-pix");
    var part ;
    var step = [];
    var dbug = [];
    for(var  i = 0, j = rand; i < j; i ++) {
        var  x = cols - 1;
        var  y = rows - 1;
        var  z = cols;
        var rx = r % cols;
        var ry = Math.floor(r / cols);
        var rv = [];

        if (rx > 0 && rx < x) {
            rv.push(r - 1, r + 1); // 可左右移動
        } else
        if (rx > 0) {
            rv.push(r - 1); // 可向左移動
        } else
        {
            rv.push(r + 1); // 可向右移動
        }
        if (ry > 0 && ry < y) {
            rv.push(r - z, r + z); // 可上下移動
        } else
        if (ry > 0) {
            rv.push(r - z); // 可向上移動
        } else
        {
            rv.push(r + z); // 可向下移動
        }

        // 排除來源位置
        if (step.length > 0) {
            v = step[step.length - 1];
            v = $.inArray(v, rv);
            if (v > -1) {
                rv.splice(v, 1 );
            }
        }
        // 排除回旋位置
        if (step.length > 2 && rv.length > 1) {
            v = step[step.length - 3];
            v = $.inArray(v, rv);
            if (v > -1) {
                rv.splice(v, 1 );
            }
        }

        // 隨機方向
        r = rv[Math.floor(Math.random()* rv.length)];
        v = hole.index();
            step.push(v);

        // 交換位置
        part  = that.children().eq( r );
        if (r < v) {
            part.insertBefore(hole);
            hole.insertBefore(that.children().eq(r));
        } else {
            hole.insertBefore(part);
            part.insertBefore(that.children().eq(v));
        }

        // 調試步驟
        if (r == v + 1) {
            dbug.push("左");
        } else
        if (r == v - 1) {
            dbug.push("右");
        } else
        if (r > v) {
            dbug.push("上");
        } else
        if (r < v) {
            dbug.push("下");
        }
    }

    // 攻略
    dbug = dbug.reverse().join(" "); alert(dbug);
    console.log( "攻略: "+dbug+"
此非最優解, 僅為隨機打散時的逆向步驟, 上下左右為相對缺口的板塊, 祝您玩的開心!" );
}

把打散的步驟記錄下來,然后反轉數組,就是攻略啦。

不過隨機時需要避免往回走,否則出現 左->右->左 這類情況就不好玩了;還得避免其他循環,如 上->右->下->左 這樣的,這會回到原點,等于什么也沒干;但更大的循環沒想好怎么處理,暫時不去糾結了。

移動判定

移動碎片到缺口,也就是交換碎片與缺口的位置。左右移動很簡單,序號大的 insertBefore 序號小的即可。上下移動有個小坑,開始自己沒注意,我原本想不管橫向還是縱向,沒有兩次 insertBefore 搞不定的,但是如果 3 和 7 交換位置(3x3, 0~8),3 移動到 7 前,7 再移動到 3 前,此時原來的 3 變成了 6。的確,沒有什么是不能兩次 insertBefore 解決的,但還得考慮讓序號大的先動。

/**
 * 移動板塊
 * @param {jQuery} that 容器對象
 * @param {int} cols 列數
 * @param {int} rows 行數
 * @param {jQuery} hole 缺口對象
 * @param {jQuery} part 板塊對象
 */
function mover(that, cols, rows, hole, part) {
    var move = false ;
    var i  = part.index();
    var j  = hole.index();
    var ix = i % cols;
    var jx = j % cols;
    var iy = Math.floor(i / cols);
    var jy = Math.floor(j / cols);

    if (iy == jy) { // 在同一行
        move  = ix == jx + 1  // 可向左邊移動
             || ix == jx - 1; // 可向右邊移動
    } else
    if (ix == jx) { // 在同一列
        move  = iy == jy + 1  // 可向上移動
             || iy == jy - 1; // 可向下移動
    }

    // 互換位置
    if (move) {
        if (i  <  j ) {
            part.insertBefore(hole);
            hole.insertBefore(that.children().eq(i));
        } else {
            hole.insertBefore(part);
            part.insertBefore(that.children().eq(j));
        }
    }

    // 判斷是否拼圖完成
    move = true;
    for (i = 0, j = cols * rows; i < j; i ++) {
        if (that.children().eq(i).data("idx") != i) {
            move = false;
        }
    }

    return  move;
}

判斷是否完成就來個笨辦法吧,依次遍歷所有碎片,只要有一個沒對上序號就是還沒成功。

未處理滑動事件,以后閑了再加吧。

整合游戲程序

上面分散的幾個函數用起來還是不太方便,整合成一個 jQuery 插件。

/**
 * 拼圖游戲
 * @param {String} src 圖片路徑
 * @param {int} cols 列數
 * @param {int} rows 行數
 * @param {int} rand 打散步數
 */
$.fn.hsPintu = function(src, cols, rows, rand) {
    var that = $(this);
    var srz  = that.data("src");
    var img  = that.data("img");

    var aw = that.width ();
    var ah = that.height();
    var ew = aw / rows;
    var eh = ah / cols;

    // 狀態: 0 進行中, 1 成功, 2 結束
    that.data("hsPintuStatus", 2);
    that.data("cols", cols);
    that.data("rows", rows);

    /**
     * img 存在且 src 沒變化
     * 則不需要再次加載圖片
     * 直接取出存儲好的數據
     */
    if (img && srz === src) {
        var ox = that.data("pos_x");
        var oy = that.data("pos_y");
        console.log("Note: 圖片無變化");

        split(that, cols, rows, ew, eh, ox, oy, img );

        // 未給 rand 則僅拆分而不打散
        if (rand === undefined) return;

        upset(that, cols, rows, rand);
        that.data("hsPintuStatus", 0);
        that.trigger("hsPintuLaunch");
    } else
    loadr(src, aw, ah, function(ox, oy) {
        that.data("src", src );
        that.data("img", this);
        that.data("pos_x", ox);
        that.data("pos_y", oy);
        console.log("Note: 載入新圖片");

        split(that, cols, rows, ew, eh, ox, oy, this);

        // 未給 rand 則僅拆分而不打散
        if (rand === undefined) return;

        upset(that, cols, rows, rand);
        that.data("hsPintuStatus", 0);
        that.trigger("hsPintuLaunch");
    });

    // 已經初始化過就不要再綁定事件了
    if (! that.data("hsPintuInited")) {
        that.data("hsPintuInited", 1);

        that.on("click", ".pt-pic:not(.pt-pix)", function() {
            if (that.data("hsPintuStatus") === 0) {
                var cols =that.data("cols");
                var rows =that.data("rows");
                var hole =that.children(".pt-pix");
                if (mover(that, cols, rows, hole, $(this))) {
                    that.data("hsPintuStatus", 1);
                    that.trigger("hsPintuFinish");
                }
            }
        });
    }

    return  this;
};

$("#pt-box").hsPintu(圖片URL, 列數, 行數[, 隨機步數]); 即可初始化拼圖游戲了, 拼圖區域需要固定寬高;隨機步數參數不提供時,僅拆解不打散。

圖片沒變化時沒必要重新加載,避免下時間損耗。當然了,更好的辦法是再判斷行、列和區域尺寸,沒變化則直接排列好碎片。懶得寫了,先這樣吧。

選擇任意圖片

上面都是固定的圖片,參與感不好,讓用戶自行“上傳”圖片豈不更有意思。其實不必真的上傳到服務器,既然“縮放”、“裁剪”上面都有了,直接加載本地圖片不就好了嘛。

/**
 * 預載文件
 * @param {Function} cal 回調函數
 * @returns {jQuery} 當前文件節點
 */
$.fn.hsFileLoad = function(cal) {
    this.each(function() {
        var that = this;
        if (window.FileReader) {
            var fr = new FileReader( );
            fr.onloadend = function(e) {
                cal.call(that, e.target.result);
            };  cal.call(that);
            $.each( this.files, function(i, fo) {
                fr.readAsDataURL( fo );
            });
        } else
        if (this.getAsDataURL) {
            cal.call(that, that.getAsDataURL());
        } else {
            cal.call(that, that.value);
        }
    });
    return this;
};

這段代碼也能從我的開源項目內找到 預載文件 方法,此工具包還有些其他的文件上傳預覽類的方法,這是我對 bootstrap-fileinput 沒有圖片裁剪功能(與最終服務端處理后的結果一致)而“一氣之下”自己寫的一點零散代碼。

完整的代碼及演示可在 這里 看到,有朋友說看不到圖,但圖片我用的百度圖片搜索的縮略圖,不清楚怎么回事,看不到可以自己從本地選擇圖片。只是那個“加載”(Image.onload)和“切片”(Image.cloneNode)比較耗時,比較大的圖片請耐心等等。

當然了,也可以光顧我們的活動頁玩一把 拼圖抽獎。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/49865.html

相關文章

  • 打造專屬自己的html5拼圖游戲

    摘要:最近公司剛好有個活動是要做一版的拼圖小游戲,于是自己心血來潮,自己先實現了一把,也算是嘗嘗鮮了。下面就把大體的思路介紹一下,希望大家都可以做出一款屬于自己的拼圖小游戲,必須是更炫酷,更好玩來吧,大家一起加油。。。 最近公司剛好有個活動是要做一版 html5的拼圖小游戲,于是自己心血來潮,自己先實現了一把,也算是嘗嘗鮮了。下面就把大體的思路介紹一下,希望大家都可以做出一款屬于自己的拼圖小...

    codeKK 評論0 收藏0
  • 打造專屬自己的html5拼圖游戲

    摘要:最近公司剛好有個活動是要做一版的拼圖小游戲,于是自己心血來潮,自己先實現了一把,也算是嘗嘗鮮了。下面就把大體的思路介紹一下,希望大家都可以做出一款屬于自己的拼圖小游戲,必須是更炫酷,更好玩來吧,大家一起加油。。。 最近公司剛好有個活動是要做一版 html5的拼圖小游戲,于是自己心血來潮,自己先實現了一把,也算是嘗嘗鮮了。下面就把大體的思路介紹一下,希望大家都可以做出一款屬于自己的拼圖小...

    JowayYoung 評論0 收藏0
  • 打造專屬自己的html5拼圖游戲

    摘要:最近公司剛好有個活動是要做一版的拼圖小游戲,于是自己心血來潮,自己先實現了一把,也算是嘗嘗鮮了。下面就把大體的思路介紹一下,希望大家都可以做出一款屬于自己的拼圖小游戲,必須是更炫酷,更好玩來吧,大家一起加油。。。 最近公司剛好有個活動是要做一版 html5的拼圖小游戲,于是自己心血來潮,自己先實現了一把,也算是嘗嘗鮮了。下面就把大體的思路介紹一下,希望大家都可以做出一款屬于自己的拼圖小...

    趙春朋 評論0 收藏0
  • HTML 簡單拼圖游戲

    摘要:基本需求有一個固定區域,被拆分成個同等大小的碎片,拿走其中一塊,靠近缺口的塊可以向缺口方向移動當拼出原來的圖樣視為完成。左右移動很簡單,序號大的序號小的即可。 先不廢話,請看演示。 showImg(https://segmentfault.com/img/bVyoj2);showImg(https://segmentfault.com/img/bVyoj5); 公司要搞這么個微信活動...

    vslam 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<