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 相关文章推荐
实现复选框全选/全不选切换
Dec 23 Javascript
增强的 JavaScript 的 trim 函数的代码
Aug 13 Javascript
Javascript 面向对象编程(一) 封装
Aug 28 Javascript
JS onmousemove鼠标移动坐标接龙DIV效果实例
Dec 16 Javascript
巧用局部变量提升javascript性能
Feb 24 Javascript
javascript绘制漂亮的心型线效果完整实例
Feb 02 Javascript
JavaScript数据结构中栈的应用之表达式求值问题详解
Apr 11 Javascript
JS实现自定义状态栏动画文字效果示例
Oct 12 Javascript
JS实现图片居中悬浮效果
Dec 25 Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 Javascript
微信小程序后台持续定位功能使用详解
Aug 23 Javascript
Vue项目页面跳转时浏览器窗口上方显示进度条功能
Mar 26 Javascript
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
PHP中英混合字符串截取函数代码
2011/07/17 PHP
使用Zttp简化Guzzle 调用
2017/07/02 PHP
CodeIgniter框架数据库基本操作示例
2018/05/24 PHP
PHPstorm启用自动换行的方法详解(IDE)
2020/09/17 PHP
JavaScript EasyPager 分页函数
2011/05/25 Javascript
jquery 如何动态添加、删除class样式方法介绍
2012/11/07 Javascript
js屏蔽鼠标键盘(右键/Ctrl+N/Shift+F10/F11/F5刷新/退格键)
2013/01/24 Javascript
javascript中onclick(this)用法介绍
2013/04/19 Javascript
jQuery.holdReady()方法用法实例
2014/12/27 Javascript
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
2015/01/01 NodeJs
Nodejs为什么选择javascript为载体语言
2015/01/13 NodeJs
如何使用jquery easyui创建标签组件
2015/11/18 Javascript
jQuery 1.9.1源码分析系列(十五)之动画处理
2015/12/03 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
AngularJS通过$http和服务器通信详解
2016/09/21 Javascript
懒加载实现的分页&amp;&amp;网站footer自适应
2016/12/21 Javascript
JavaScript动态绑定详解
2017/09/14 Javascript
详解vue-cli脚手架build目录中的dev-server.js配置文件
2017/11/24 Javascript
解决layer弹层遮罩挡住窗体的问题
2018/08/17 Javascript
Vue在 Nuxt.js 中重定向 404 页面的方法
2019/04/23 Javascript
深入了解JavaScript代码覆盖
2019/06/13 Javascript
vue使用Sass时报错问题的解决方法
2020/10/14 Javascript
python继承和抽象类的实现方法
2015/01/14 Python
介绍Python中的一些高级编程技巧
2015/04/02 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
西部世纪面试题
2014/12/05 面试题
Jdbc数据访问技术面试题
2012/03/30 面试题
旅游管理毕业生自荐信
2013/11/05 职场文书
艺术应用与设计个人的自我评价
2013/11/23 职场文书
人力资源专业推荐信
2013/11/29 职场文书
国际贸易专业个人鉴定
2014/02/22 职场文书
欢迎词怎么写
2015/01/23 职场文书
检讨书大全
2015/01/27 职场文书
体育委员竞选稿
2015/11/21 职场文书
Python爬虫数据的分类及json数据使用小结
2021/03/29 Python
电脑关机速度很慢怎么办 提升电脑关机速度设置教程
2022/04/08 数码科技