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调用WebService的示例
Apr 07 Javascript
类似CSDN图片切换效果脚本
Sep 17 Javascript
JS实现定时页面弹出类似QQ新闻的提示框
Nov 07 Javascript
Jquery 实现图片轮换
Jan 28 Javascript
JavaScript学习小结(一)——JavaScript入门基础
Sep 02 Javascript
JS基于面向对象实现的拖拽库实例
Sep 24 Javascript
Javascript循环删除数组中元素的几种方法示例
May 18 Javascript
zTree树形菜单交互选项卡效果的实现方法
Dec 25 Javascript
javascript中undefined的本质解析
Jul 31 Javascript
关于ckeditor在bootstrap中modal中弹框无法输入的解决方法
Sep 11 Javascript
使用JS监听键盘按下事件(keydown event)
Nov 07 Javascript
vue实现数字滚动效果
Jun 29 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获取远程图片的两种 CURL方式和sockets方式获取远程图片
2011/11/07 PHP
php使用Imagick生成图片的方法
2015/07/31 PHP
PHP中的switch语句的用法实例详解
2015/10/21 PHP
php支持断点续传、分块下载的类
2016/05/02 PHP
PHP时间处理类操作示例
2018/09/05 PHP
实例解析php的数据类型
2018/10/24 PHP
yii框架结合charjs实现统计30天数据的方法
2020/04/04 PHP
如何在Laravel之外使用illuminate组件详解
2020/09/20 PHP
阻止JavaScript事件冒泡传递(cancelBubble 、stopPropagation)
2007/05/08 Javascript
javascript网页关闭时提醒效果脚本
2008/10/22 Javascript
关于全局变量和局部变量的那些事
2013/01/11 Javascript
用jquery方法操作radio使其默认选项是否
2013/09/10 Javascript
js获取视频时长代码
2014/04/10 Javascript
Node.js重新刷新session过期时间的方法
2016/02/04 Javascript
JS实现复制内容到剪贴板功能兼容所有浏览器(推荐)
2016/06/17 Javascript
Javascript中常用类型的格式化方法小结
2016/12/26 Javascript
vue2.0父子组件及非父子组件之间的通信方法
2017/01/21 Javascript
详解Angular CLI + Electron 开发环境搭建
2017/07/20 Javascript
vue发送ajax请求详解
2018/10/09 Javascript
微信小程序实现跑马灯效果
2020/10/21 Javascript
vue.js实现的幻灯片功能示例
2019/01/18 Javascript
微信小程序上传图片并等比列压缩到指定大小的实例代码
2019/10/24 Javascript
vue中的mescroll搜索运用及各种填坑处理
2019/10/30 Javascript
json_decode 索引为数字时自动排序问题解决方法
2020/03/28 Javascript
vue-iview动态新增和删除的方法
2020/06/17 Javascript
python微信跳一跳游戏辅助代码解析
2018/01/29 Python
python生成密码字典的方法
2018/07/06 Python
python 基于TCP协议的套接字编程详解
2019/06/29 Python
python3+django2开发一个简单的人员管理系统过程详解
2019/07/23 Python
纯CSS3实现移动端展开和收起效果的示例代码
2020/04/26 HTML / CSS
英国领先的杂志订阅网站:Magazine.co.uk
2018/01/25 全球购物
自荐书范文
2013/12/08 职场文书
汽车专业大学生职业生涯规划范文
2014/01/07 职场文书
文明村创建实施方案
2014/03/27 职场文书
护林防火标语
2014/06/27 职场文书
python自动获取微信公众号最新文章的实现代码
2022/07/15 Python