zoukankan      html  css  js  c++  java
  • 拼图小游戏之计算后样式与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();
        });
  • 相关阅读:
    一个比喻理解进程和线程的区别
    python蛋疼的编码decode、encode、unicode、str、byte的问题都在这了
    python类中__unicode__和__str__方法的妙用
    python re 正则提取中文
    一个python爬虫协程的写法(gevent模块)
    python 中range和xrange的区别
    python 监控oracle 数据库
    Spring security 知识笔记【自定义登录页面】
    Spring security 知识笔记【内存角色授权】
    Spring security 知识笔记【入门】
  • 原文地址:https://www.cnblogs.com/zhangxiongcn/p/6132464.html
Copyright © 2011-2022 走看看