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 相关文章推荐
js 实现css风格选择器(压缩后2KB)
Jan 12 Javascript
JSF中confirm弹出框的用法示例介绍
Jan 07 Javascript
基于JQuery实现的Select级联
Jan 27 Javascript
JavaScript中逗号运算符介绍及使用示例
Mar 13 Javascript
js实现网页收藏功能
Dec 17 Javascript
学习JavaScript设计模式之装饰者模式
Jan 19 Javascript
javascript实现PC网页里的拖拽效果
Mar 14 Javascript
JavaScript的ExtJS框架中数面板TreePanel的使用实例解析
May 21 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
May 30 Javascript
bootstrap vue.js实现tab效果
Feb 07 Javascript
利用vue-i18n实现多语言切换效果的方法
Jun 19 Javascript
Vue实现渲染数据后控制滚动条位置(推荐)
Dec 09 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
欧美媒体选出10年前最流行的17部动画
2017/01/18 日漫
PHP实现删除字符串中任何字符的函数
2015/08/11 PHP
php关联数组与索引数组及其显示方法
2018/03/12 PHP
PHP论坛实现积分系统的思路代码详解
2020/06/01 PHP
Jquery获得控件值的三种方法总结
2014/02/13 Javascript
Javascript单元测试框架QUnitjs详细介绍
2014/05/08 Javascript
JavaScript中判断页面关闭、页面刷新的实现代码
2014/08/27 Javascript
js使用cookie记录用户名的方法
2015/11/26 Javascript
javascript编程异常处理实例小结
2015/11/30 Javascript
基于jQuery和CSS3制作响应式水平时间轴附源码下载
2015/12/20 Javascript
封装的dialog插件 基于bootstrap模态对话框的简单扩展
2016/08/10 Javascript
AngularJs bootstrap搭载前台框架——基础页面
2016/09/01 Javascript
Vue.js第四天学习笔记
2016/12/02 Javascript
jQuery实现倒计时(倒计时年月日可自己输入)
2016/12/02 Javascript
React组件refs的使用详解
2018/02/09 Javascript
Node.js中的cluster模块深入解读
2018/06/11 Javascript
使用iView Upload 组件实现手动上传图片的示例代码
2018/10/01 Javascript
[02:31]《DAC最前线》之选手酒店现场花絮
2015/01/30 DOTA
python学生管理系统代码实现
2020/04/05 Python
keras 多gpu并行运行案例
2020/06/10 Python
真正了解CSS3背景下的@font face规则
2017/05/04 HTML / CSS
html5 Canvas画图教程(3)—canvas出现1像素线条模糊不清的原因
2013/01/09 HTML / CSS
获取邓白氏信用报告:Dun & Bradstreet
2019/01/22 全球购物
举例说明类变量和实例变量的区别
2016/06/30 面试题
给幼儿园老师的表扬信
2014/01/19 职场文书
乡镇干部党的群众路线教育实践活动个人对照检查材料
2014/09/24 职场文书
小区门卫的岗位职责
2014/09/26 职场文书
法院干警四风问题个人对照检查材料思想汇报
2014/10/07 职场文书
领导干部考核评语
2015/01/04 职场文书
新郎婚礼答谢词
2015/01/04 职场文书
大学生就业意向书
2015/05/11 职场文书
“5.12”护士节主持词
2015/07/04 职场文书
趣味运动会通讯稿
2015/07/18 职场文书
2016优秀青年志愿者事迹材料
2016/02/25 职场文书
2019最新版火锅店的创业计划书 !
2019/07/12 职场文书
分析MySQL抛出异常的几种常见解决方式
2021/05/18 MySQL