javascript结合Flexbox简单实现滑动拼图游戏


Posted in Javascript onFebruary 18, 2016

滑动拼图就是把一张图片分成几等份,打乱顺序(下图),然后通过滑动拼凑成一张完整的图片。

javascript结合Flexbox简单实现滑动拼图游戏

要实现一个拼图游戏,需要考虑怎样随机的打乱顺序,怎样交换两张图片的位置,等等。但是,使用了Flexbox布局以后,这都不需要你去考虑,浏览器会帮你做,Flexbox就是这么的强大。关于Flexbox的介绍可以点击这里。
这个游戏中要用的是Flexbox布局的order属性,order属性可以用来控制Flex项目的顺序。
这里我用九个canvas元素来把图片分成九等分,也可以用其他方法,比如背景图片定位:

<div class="wrap">
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
  <canvas></canvas>
</div>

如果不仅限于九宫格,还要十六宫格等,上面的元素完全可以动态生成。
下面是生成打乱顺序的九张图代码:

var drawImage = function (url) {
  return new Promise(function (resolve, reject) {
    var img = new Image();
    img.onload = function () {
      resolve(img);
    };
    img.src = url;
  })
};

drawImage("2.jpg").then(function (img) {
  var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
  var random = arr.sort(function() {return Math.random() > 0.5});
  [].forEach.call(document.querySelectorAll("canvas"), function (item, i) {
    item.width = $(".wrap").clientWidth / 3;
    item.height = $(".wrap").clientHeight / 3;
    item.style.order = random[i];
    var ctx = item.getContext("2d");
    ctx.drawImage(img, img.width * (i % 3) / 3, img.height * Math.floor(i / 3) / 3, img.width / 3, img.height / 3, 0, 0, item.width, item.height);
  });
});

上面的关键代码是:

item.style.order = random[i];

通过将数字打乱顺序,随机赋值给每个canvas元素的order属性,这样浏览器就自动帮你排序了。
关于代码的其他细节就不讲了,这里说一下怎样交换两张图片的位置,真是出乎意料的简单:

var order1 = item.style.order;
var order2 = target.style.order;

只需要交换双方的order属性值就可以了。

完整代码

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
  <meta content="yes" name="apple-mobile-web-app-capable" />
  <meta content="black" name="apple-mobile-web-app-status-bar-style" />
  <meta content="telephone=no" name="format-detection" />
  <title></title>
  <style>
    html, body {
      height: 100%;
    }
    body {
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    .wrap {
      display: flex;
      flex-wrap: wrap;
      width: 100%;
      height: 100%;
      overflow: hidden;
    }
    .wrap canvas {
      width: 33.3333%;
      height: 33.3333%;
      border: 1px solid red;
      box-sizing: border-box;
    }
  </style>
</head>
<body>
<div class="wrap">
  <canvas data-value="1"></canvas>
  <canvas data-value="2"></canvas>
  <canvas data-value="3"></canvas>
  <canvas data-value="4"></canvas>
  <canvas data-value="5"></canvas>
  <canvas data-value="6"></canvas>
  <canvas data-value="7"></canvas>
  <canvas data-value="8"></canvas>
  <canvas data-value="9"></canvas>
</div>
<script>
  var $ = function (el) {
    return document.querySelector(el);
  };
  var touchMove, touchEnd;
  var drawImage = function (url) {
    return new Promise(function (resolve, reject) {
      var img = new Image();
      img.onload = function () {
        resolve(img);
      };
      img.src = url;
    })
  };
  drawImage("2.jpg").then(function (img) {
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    var random = arr.sort(function() {return Math.random() > 0.5});
    [].forEach.call(document.querySelectorAll("canvas"), function (item, i) {
      item.width = $(".wrap").clientWidth / 3;
      item.height = $(".wrap").clientHeight / 3;
      item.style.order = random[i];
      var ctx = item.getContext("2d");
      ctx.drawImage(img, img.width * (i % 3) / 3, img.height * Math.floor(i / 3) / 3, img.width / 3, img.height / 3, 0, 0, item.width, item.height);
    });
  });
  document.addEventListener("touchstart", function (e) {
    var target = e.target;
    if (e.target.tagName.toLowerCase() !== "canvas") {
      return;
    }
    var ctx = target.getContext("2d");
    var image = ctx.getImageData(0, 0, target.width, target.height);
    var obj = target.cloneNode(true);
    obj.getContext("2d").putImageData(image, 0, 0);
    var top = target.getBoundingClientRect().top, left = target.getBoundingClientRect().left;
    obj.style.cssText = "position: absolute; top: " + top + "px; left: " + left + "px";
    document.body.appendChild(obj);
    var point = {"x": e.touches[0].pageX, "y": e.touches[0].pageY};
    document.addEventListener("touchmove", touchMove = function (e) {
      obj.style.cssText = "position: absolute; top:" + (e.touches[0].pageY - point.y + top) + "px; left: " + (e.touches[0].pageX - point.x + left) + "px";
    });
    document.addEventListener("touchend", touchEnd = function (e) {
      var pos = {"x": e.changedTouches[0].pageX, "y": e.changedTouches[0].pageY};
      [].forEach.call(document.querySelectorAll(".wrap canvas"), function (item, i) {
        var offset = item.getBoundingClientRect();
        if (pos.x > offset.left && pos.x < (offset.left + item.width) && pos.y > offset.top && pos.y < (offset.top + item.height)) {
          var order1 = item.style.order;
          var order2 = target.style.order;
          if (obj.parentNode) {
            document.body.removeChild(obj);
          }
          item.style.order = order2;
          target.style.order = order1;
        }
      });
      document.removeEventListener("touchmove", touchMove);
      document.removeEventListener("touchend", touchEnd);
    })
  })
</script>
</body>
</html>

大家做测试的时候,最好用谷歌模拟器或者手机打开,因为只支持移动端触摸事件。

代码中只实现了基本功能,并没有实现完整功能。

Javascript 相关文章推荐
javascript Split方法,indexOf方法、lastIndexOf 方法和substring 方法
Mar 21 Javascript
让图片旋转任意角度及JQuery插件使用介绍
Mar 20 Javascript
jquery实现的缩略图预览滑块实例
Jun 25 Javascript
使用jQuery在移动页面上添加按钮和给按钮添加图标
Dec 04 Javascript
浅析Javascript中bind()方法的使用与实现
Apr 29 Javascript
JS模拟实现方法重载示例
Aug 03 Javascript
jQuery Validate让普通按钮触发表单验证的方法
Dec 15 Javascript
前端把html表格生成为excel表格的实例
Sep 19 Javascript
详解创建自定义的Angular Schematics
Jun 06 Javascript
通过javascript实现扫雷游戏代码实例
Feb 09 Javascript
JS写滑稽笑脸运动效果
May 28 Javascript
jquery实现图片放大镜效果
Dec 23 jQuery
Angular发布1.5正式版,专注于向Angular 2的过渡
Feb 18 #Javascript
iscroll.js的上拉下拉刷新时无法回弹的解决方法
Feb 18 #Javascript
javascript每日必学之条件分支
Feb 17 #Javascript
JavaScipt中栈的实现方法
Feb 17 #Javascript
Bootstrap入门书籍之(五)导航条、分页导航
Feb 17 #Javascript
Bootstrap入门书籍之(四)菜单、按钮及导航
Feb 17 #Javascript
Bootstrap入门书籍之(三)栅格系统
Feb 17 #Javascript
You might like
1亿条数据如何分表100张到Mysql数据库中(PHP)
2015/07/29 PHP
CI框架中数据库操作函数$this-&gt;db-&gt;where()相关用法总结
2016/05/17 PHP
PHP实现微信提现(企业付款到零钱)
2019/08/01 PHP
使用jQuery的ajax功能实现的RSS Reader 代码
2009/09/03 Javascript
js下用gb2312编码解码实现方法
2009/12/31 Javascript
EXT窗口Window及对话框MessageBox
2011/01/27 Javascript
JS上传图片前实现图片预览效果的方法
2015/03/02 Javascript
jquery.mousewheel实现整屏翻屏效果
2015/08/30 Javascript
jQuery实现的鼠标滑过弹出放大图片特效
2016/01/08 Javascript
详解js中常规日期格式处理、月历渲染和倒计时函数
2016/12/28 Javascript
使用AngularJS对表单提交内容进行验证的操作方法
2017/07/12 Javascript
webpack项目使用eslint建立代码规范实现
2019/05/16 Javascript
js实现淘宝浏览商品放大镜功能
2020/10/28 Javascript
[47:46]完美世界DOTA2联赛 Magma vs GXR 第三场 11.07
2020/11/10 DOTA
使用Nginx+uWsgi实现Python的Django框架站点动静分离
2016/03/21 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
2017/12/20 Python
django.db.utils.ProgrammingError: (1146, u“Table‘’ doesn’t exist”)问题的解决
2018/07/13 Python
django框架使用orm实现批量更新数据的方法
2019/06/21 Python
在Python中构建增广矩阵的实现方法
2019/07/01 Python
Python响应对象text属性乱码解决方案
2020/03/31 Python
html5 application cache遇到的严重问题
2012/12/26 HTML / CSS
澳大利亚领先的内衣店:Bendon Lingerie澳大利亚
2020/05/15 全球购物
自我评价中英文语句
2013/11/30 职场文书
大学生实习证明范本
2014/01/15 职场文书
老师对学生的寄语
2014/04/09 职场文书
人事经理岗位职责范本
2014/08/04 职场文书
安全生产年活动总结
2014/08/29 职场文书
2014年教师党员自我评价范文
2014/09/22 职场文书
ktv服务员岗位职责
2015/02/09 职场文书
2015年端午节活动策划书
2015/05/05 职场文书
2015小学教师德育工作总结
2015/05/12 职场文书
2015年圣诞节寄语
2015/08/17 职场文书
创业计划书之溜冰场
2019/10/25 职场文书
解决mysql模糊查询索引失效问题的几种方法
2021/06/18 MySQL
python实现简单聊天功能
2021/07/07 Python
JavaScript实现一键复制内容剪贴板
2022/07/23 Javascript