先说结论:

前几天写了几个非常简单的移动端小游戏,其中一个拼图游戏让我郁闷了一段时间。因为要获取每张图片的位置,用`<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:;padding:;}
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:;
left:;
right:;
bottom:;
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();
});

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

  1. JavaScript版拼图小游戏

    慕课网上准备开个新的jQuery教程,花了3天空闲时间写了一个Javascript版的拼图小游戏,作为新教程配套的分析案例 拼图游戏网上有不少的实现案例了,但是此源码是我自己的实现,所以不做太多的比较 ...

  2. jQuery实现拼图小游戏

    小熊维尼拼图                                                                                    2017-07-23 ...

  3. jQuery拼图小游戏

    jQuery拼图小游戏 最后样式 核心代码部分 <script type="text/javascript" > $(function () { $("td& ...

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

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

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

    js:运行在浏览器的脚本语言 js引入 1.行间式:存在于行间事件中 <div id="div" onclick="this.style.color="r ...

  6. 教你用Python自制拼图小游戏,一起来制作吧

    摘要: 本文主要为大家详细介绍了python实现拼图小游戏,文中还有示例代码介绍,感兴趣的小伙伴们可以参考一下. 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Pyt ...

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

    节点计算后样式是一个属性与属性值的值对对象: IE:    node.currentStyle; 非IE: window.getComputedStyle(node,null); 兼容方式: func ...

  8. 使用NGUI实现拖拽功能(拼图小游戏)

    上一次用UGUI实现了拼图小游戏,这次,我们来用NGUI来实现 实现原理 NGUI中提供了拖拽的基类UIDragDropItem,所以我们要做的就是在要拖拽的图片上加一个继承于该类的脚本,并实现其中的 ...

  9. 在HTML页面中有jQuery实现实现拼图小游戏

    1.用jQuery实现拼图小游戏 2.首先获得td的点击事件.再进行交换位置 3.下面这种仅供参考 4.下面这些是HTMl标签 当这个世界变得越来越复杂的时候,内心最需保持一份简单一份纯真:

随机推荐

  1. XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个的解决办法

            在前几天的一个项目中,由于数据库字段的命名原因 其中有两项:一项叫做"市场价格"一项叫做"商店价格" 为了便于区分,遂分别将其命名为market ...

  2. .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]

    方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...

  3. 解决PHP-问题:Class 'SimpleXMLElement' not found in

    1.问题 在ubuntu 16.10中,学习PHP,学习到PHP如何生成XML文件时候,碰到了这个问题: PHP Fatal error: Class 'ClassName\SimpleXMLElem ...

  4. jQuery学习之路(2)-DOM操作

    ▓▓▓▓▓▓ 大致介绍 jQuery作为JavaScript库,继承并发扬了JavaScript对DOM对象操作的特性,使开发人员能方便的操作DOM对象. ▓▓▓▓▓▓ jQuery中的DOM操作 看 ...

  5. MySQL设置字段的默认值为当前系统时间

    问题产生: 当我们在对某个字段进行设置时间默认值,该默认值必须是的当前记录的插入时间,那么就将当前系统时间作为该记录创建的时间. 应用场景: 1.在数据表中,要记录每条数据是什么时候创建的,应该由数据 ...

  6. H5程序员如何利用cordova开发跨平台应用

    什么是Cordova? Cordova以前也叫PhoneGap,它提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头.麦克风等.Cordova还 ...

  7. C#各种同步方法 lock, Monitor,Mutex, Semaphore, Interlocked, ReaderWriterLock,AutoResetEvent, ManualResetEvent

    看下组织结构: System.Object System.MarshalByRefObject System.Threading.WaitHandle System.Threading.Mutex S ...

  8. Java—恶心的java.lang.NumberFormatException解决

    项目中要把十六进制字符串转化为十进制, 用到了到了Integer.parseInt(str1.trim(), 16):这个是不是后抛出java.lang.NumberFormatException异常 ...

  9. 编译器开发系列--Ocelot语言1.抽象语法树

    从今天开始研究开发自己的编程语言Ocelot,从<自制编译器>出发,然后再自己不断完善功能并优化. 编译器前端简单,就不深入研究了,直接用现成的一款工具叫JavaCC,它可以生成抽象语法树 ...

  10. Linux基础介绍【第九篇】

    服务器添加3块磁盘的体系结构 [root@oldboylinux test]# free -m              total used free shared buffers cached M ...