拼图小游戏之计算后样式与CSS动画的冲突

先说结论:

前几天写了几个非常简单的移动端小游戏,其中一个拼图游戏让我郁闷了一段时间。因为要获取每张图片的位置,用`<style>`标签写的样式,直接获取计算后样式再用来交换位置,结果就悲剧了,出现了一些不理解的情况。这个错误比较低级,不过还是被我遇到了,就拿来记录一下。

注意:

在交换每张图片位置的时候,我对它们设置了CSS中transition属性,有了缓冲动画效果,这样一来,每次打乱图片的时候,用getComputedStyle获取计算后样式,但是,动画有时长,而获取样式在触发时就完成了,所以会造成:图片还没有达目标位置,就已经获取到了它的中途位置坐标,得到了一组错误的数字,所有的拼图就会错乱。

所以,在遇到需要获取一个移动中的元素的left、top这类属性值的时候,如果要获取的值是个具体的值,那么就不要用计算后样式,而是去获取行内样式或者一个固定的值,就不会出现麻烦了。

代码地址:https://github.com/zhangxiongcn/demo

正确效果:

错误效果:

HTML部分:

    <div class="box">
    <h2>拼图游戏</h2>
    <button id="btn">play</button>
        <div class="puzzle" id="puzzle">
            <div class="item item0" data-num="0" style="left: 2px;top: 2px;background-position: 0px 0px;"></div>
            <div class="item item1" data-num="1" style="left: 104px;top: 2px;background-position: -100px 0px;"></div>
            <div class="item item2" data-num="2" style="left: 206px;top: 2px;background-position: -200px 0px;"></div>
            <div class="item item3" data-num="3" style="left: 2px;top: 104px;background-position: 0px -100px;"></div>
            <div class="item item4" data-num="4" style="left: 104px;top: 104px;background-position: -100px -100px;"></div>
            <div class="item item5" data-num="5" style="left: 206px;top: 104px;background-position: -200px -100px;"></div>
            <div class="item item6" data-num="6" style="left: 2px;top: 206px;background-position: 0px -200px;"></div>
            <div class="item item7" data-num="7" style="left: 104px;top: 206px;background-position: -100px -200px;"></div>
            <div class="item item8" data-num="8" style="left: 206px;top: 206px;background-position: -200px -200px;"></div>
        </div>
    </div>
    <div class="mask" id="mask">
        <div class="sucbox">
            <div class="animated tada">完成</div>
            <button class="again">继续</button>
        </div>
    </div>

CSS部分:

    <style>
        *{margin:0;padding:0;}
        body{
            background-color: #FDF5E6;
        }
        .box{
            width: 100%;
            text-align: center;
        }
        .box h2{
            margin:20px;
        }
        .box button{
            width: 50px;
            height: 30px;
            background-color: #1E90FF;
            border: none;
            outline: none;
            font-size: 20px;
            color: #fff;
            border-radius: 5px;
            margin-bottom: 10px;
        }
        .puzzle{
            position: relative;
            width: 308px;
            height: 308px;
            margin: 0 auto;
            border: 3px solid #ccc;
            box-shadow: 0 0 10px #ddd;
        }
        .item{
            position: absolute;
            width: 100px;
            height: 100px;
            background-image: url(images/puzzle.jpg);
            background-repeat: no-repeat;
            background-size: 300% 300%;
            transition: all .5s;
        }
        .mask{
            display: none;
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(0,0,0,.3);
        }
        .mask .sucbox{
            position: absolute;
            top: 20%;
            left: 50%;
        }
        .tada{
            margin-left: -50px;
            width: 100px;
            height: 50px;
            background-color: pink;
            border-radius: 10px;
            font-size: 24px;
            line-height: 50px;
            text-align: center;
        }
        .again{
            width: 100px;
            height: 30px;
            margin-top: 50px;
            margin-left: -50px;
            font-size: 20px;
        }
    </style>

JS部分:

    var puzzle = document.getElementById(‘puzzle‘);
    var items  = puzzle.querySelectorAll(‘.item‘);
    var btn    = document.getElementById(‘btn‘);
    var mask   = document.getElementById(‘mask‘);
    var again  = mask.querySelector(‘.again‘);
    var info = {
        left:0,
        top:0,
        x:0,
        y:0
    }
    again.addEventListener(‘touchend‘,function(){
        mask.style.display = "none";
    });
    // 点击play按钮,打乱图片顺序
    btn.addEventListener(‘touchstart‘,function(){
        for (var i = 1; i < 20; i++) {
            // 随机获取20组0-9的数字
            // 让它们互相更换位置
            var a = Math.floor(Math.random()*1000)%9;
            var b = Math.floor(Math.random()*1000)%9;
            if( a != b){
                var _left = items[a].style.left;
                items[a].style.left = items[b].style.left;
                items[b].style.left = _left;

                var _top = items[a].style.top;
                items[a].style.top = items[b].style.top;
                items[b].style.top = _top;

                // 更换编号
                var _num= items[a].getAttribute("data-num");
                items[a].setAttribute("data-num",items[b].getAttribute("data-num"));
                items[b].setAttribute("data-num",_num);
            }
        }
    });
    for (var i = 0; i < items.length; i++) {
        // 手指按下时,获取初始值
        items[i].addEventListener(‘touchstart‘,function(e){
            info.left = parseInt(this.style.left);
            info.top  = parseInt(this.style.top);
            info.x    = e.targetTouches[0].pageX;
            info.y    = e.targetTouches[0].pageY;
            // 保存每张图片原来的left和top
            // 用于交换图片时用
            this.iniLeft = info.left;
            this.iniTop  = info.top;
            this.style.transition = "none";
        });
        // 滑动时,改变图片的left和top
        items[i].addEventListener(‘touchmove‘,function(e){
            this.style["z-index"] = 99;
            this.style.left = info.left - info.x + e.targetTouches[0].pageX + "px";
            this.style.top  = info.top - info.y + e.targetTouches[0].pageY + "px";
        });
        // 手指抬起时,更换两张图片位置
        items[i].addEventListener(‘touchend‘,function(e){
            this.style["z-index"] = 0;
            var x = e.changedTouches[0].pageX - puzzle.offsetLeft;
            var y = e.changedTouches[0].pageY - puzzle.offsetTop;
            var target = find(this,x,y);
            if( target === this){
                target.style.top = target.iniTop +"px";
                target.style.left = target.iniLeft +"px";
            }else{
                exchange(this,target);
                if(isOk()){
                    setTimeout(function(){
                        mask.style.display = "block";
                    },1000);
                }
            }
            this.style.transition = "all .5s";
        });
    }
    // 两个图片互相交换,即交换它们的left和top
    function exchange(a,b){

        var _top = a.iniTop;
        a.style.top = b.style.top;
        b.style.top = _top + "px";

        var _left = a.iniLeft;
        a.style.left = b.style.left;
        b.style.left = _left + "px";
        var _num= a.getAttribute("data-num");
        a.setAttribute("data-num",b.getAttribute("data-num"));
        b.setAttribute("data-num",_num);
    }
    // 移动一张图片,找到要更换的目标图片
    // 根据鼠标的x,y值所在的范围去确定目标图片
    function find(obj,x,y){
        for (var i = 0; i < items.length; i++) {
            if(obj != items[i]){
                var _left = parseInt(items[i].style.left);
                var _top = parseInt(items[i].style.top);
                var c1 = x >= _left && x < _left+100;
                var c2 = y >= _top && y < _top+100;
                if(c1 && c2){
                    return items[i];
                }
            }
        }
        return obj;
    }
    function isOk(){
        var str = ‘‘;
        for (var i = 0; i < items.length; i++) {
            str += items[i].getAttribute(‘data-num‘);
        }
        return str == "012345678";
    }
    document.addEventListener(‘touchstart‘,function(e){
        e.stopPropagation();
        e.preventDefault();
    });
时间: 2024-08-04 00:53:35

拼图小游戏之计算后样式与CSS动画的冲突的相关文章

绅士向纯原生250行拼图小游戏

拼图小游戏 先来预览,咳咳,这个比上次那个地鼠会好看点-- 代码是可以设置难度的,3就是9,9就是81-- 相比来说,此程序难度可是远远高过打地鼠的,希望小伙伴能跟上~ html <header> <button ='Game.restart()'>重新开始</button> <button id="download" ='Game.openImage()'>新标签打开图片</button> </header> &

JavaScript版拼图小游戏

慕课网上准备开个新的jQuery教程,花了3天空闲时间写了一个Javascript版的拼图小游戏,作为新教程配套的分析案例 拼图游戏网上有不少的实现案例了,但是此源码是我自己的实现,所以不做太多的比较 在线预览(Chrome):http://sandbox.runjs.cn/show/pcwfu7i5 拼图游戏其实挺简单,主要是涉及到一些细节的处理,以下是我的自己在实现中涉及到的问题: 图片的切割与拼接 如何随机布局 如何切换图片 拖动图片溢出处理 怎么知道图片是否还原成功 实现思路: 为了简单

仿苹果电脑任务栏菜单&amp;&amp;拼图小游戏&amp;&amp;模拟表单控件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

《C++ Qt 设计模式》8|15拼图 小游戏的简单实现。拜托,别乱点!

第零章:介绍 看到这个游戏了,感觉蛮好玩的,实现了一下. 界面如下: 游戏玩法:在3×*3的矩阵中,每个按钮都可以点击,如果按钮四周有一个是空白,则点击此按钮则会移动到这个空白.按钮字母顺序变成“ABCD……”这样有序就赢了,最后空格可以出现在任何地方. 第一章:构思 设计模式基本上没接触过,所以就没有按书上的方式,自己想了大概要怎么实现,可能自己像的没有它给出的方式好吧,但是毕竟是菜鸟嘛,一步一步来! 1.用什么装这些按钮 学习了QGridLayOut,“The QGridLayout cla

jQuery拼图小游戏

jQuery拼图小游戏 最后样式 核心代码部分 <script type="text/javascript" > $(function () { $("td").click(function () { //获取点击的图片的id id = parseInt($(this).prop("id")); //向下 if (id + 3 < 10 && $("td[id=" + (id + 3) + &

js事件,操作页面文档,计算后样式,数据类型

js:运行在浏览器的脚本语言 js引入 1.行间式:存在于行间事件中 <div id="div" onclick="this.style.color="red"">文本内容</div> <style> div{ width: 100px; height: 100px; background-color: red; } </style> </head> <body> <d

探索javascript----获得节点计算后样式

节点计算后样式是一个属性与属性值的值对对象: IE:    node.currentStyle; 非IE: window.getComputedStyle(node,null); 兼容方式: function getCurrentStyle(node){ var style=[]; node.currentStyle?style=node.currentStyle:window.getComputedStyle(node,null); return style; }

swift 拼图小游戏

根据这位朋友的拼图小游戏改编 http://tangchaolizi.blog.51cto.com/3126463/1571616 改编主要地方是: 原本着我仁兄的代码时支持拖动小图块来移动的,我参照之前自己java当初写的,其实不需要拖动,因为只有一个空出来地方,那么通过点击事件,接受到点击事件的小图只能向一个方向移动或者不能移动. 通过对这个游戏的学习,我也算是第一次用swift写一个有用的代码,大家互相学习. 代码下载位置 版权声明:本文为博主原创文章,未经博主允许不得转载.

速度挑战 - 2小时完成HTML5拼图小游戏

初学lufylegend.js之日,我用lufylegend.js开发了第一个HTML5小游戏--拼图游戏,还写了篇博文来炫耀一下:HTML5小游戏<智力大拼图>发布,挑战你的思维风暴.不过当时初学游戏开发,经验浅薄,所以没有好好专研游戏里的算法和代码的缺陷,导致游戏出现了很多bug,甚至拼图打乱后很可能无法复原.最近经常有朋友问起这个游戏,希望我能把代码里的bug改一下方便初学者学习,顺便我也打算测试一下自己写这种小游戏的速度,所以就抽出了一些时间将这个游戏从头到尾重新写了一遍,计算了一下用