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去掉字符串里的所有空格
Feb 08 Javascript
利用javascript实现一些常用软件的下载导航
Aug 03 Javascript
JQuery EasyUI 对话框的使用方法
Oct 24 Javascript
JS编程小常识很有用
Nov 26 Javascript
jQuery中index()的用法分析
Sep 05 Javascript
JavaScript获取鼠标移动时的坐标(兼容IE8、chome谷歌、Firefox)
Sep 13 Javascript
jfinal与bootstrap的登录跳转实战演习
Sep 22 Javascript
Labelauty?jQuery单选框/复选框美化插件分享
Sep 26 Javascript
微信小程序 图片等比例缩放(图片自适应屏幕)
Nov 16 Javascript
Vue表单验证插件的制作过程
Apr 01 Javascript
BootStrap Table 后台数据绑定、特殊列处理、排序功能
May 27 Javascript
vue的列表交错过渡实现代码示例
May 05 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中取得image按钮传递的name值
2006/10/09 PHP
php下将图片以二进制存入mysql数据库中并显示的实现代码
2010/05/27 PHP
PHP的mysqli_stmt_init()函数讲解
2019/01/24 PHP
使用Modello编写JavaScript类
2006/12/22 Javascript
JavaScript编程开发中的五个实用小技巧
2010/07/22 Javascript
JQuery 自定义CircleAnimation,Animate方法学习笔记
2011/07/10 Javascript
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
Jquery attr(&quot;checked&quot;) 返回checked或undefined 获取选中失效
2013/10/10 Javascript
javascript中with()方法的语法格式及使用
2014/08/04 Javascript
浅析jquery数组删除指定元素的方法:grep()
2016/05/19 Javascript
Vue.js实战之利用vue-router实现跳转页面
2017/04/01 Javascript
Angularjs根据json文件动态生成路由状态的实现方法
2017/04/17 Javascript
全面解析vue中的数据双向绑定
2017/05/10 Javascript
总结js中的一些兼容性易错的问题
2017/12/18 Javascript
jquery的 filter()方法使用教程
2018/03/22 jQuery
详解Vue2.0配置mint-ui踩过的那些坑
2018/04/23 Javascript
自己编程中遇到的Python错误和解决方法汇总整理
2015/06/03 Python
基于python绘制科赫雪花
2018/06/22 Python
简单了解python反射机制的一些知识
2019/07/13 Python
Python TCP通信客户端服务端代码实例
2019/11/21 Python
HTML5中的拖放实现详解
2017/08/23 HTML / CSS
记一次高分屏下canvas模糊问题
2020/02/17 HTML / CSS
阿联酋电子产品购物网站:Menakart
2017/09/15 全球购物
如何写出高性能的JSP和Servlet
2013/01/22 面试题
运动会广播稿500字
2014/01/28 职场文书
2014年预备党员学习两会心得体会
2014/03/17 职场文书
2014年大学生四年规划书范文
2014/04/03 职场文书
住宅质量保证书
2014/04/29 职场文书
老干部工作先进集体事迹材料
2014/05/21 职场文书
甜品店创业计划书
2014/08/14 职场文书
党性教育心得体会
2014/09/03 职场文书
教师个人学习总结
2015/02/11 职场文书
九九重阳节致辞
2015/07/31 职场文书
浅谈移动端中的视口(viewport)的具体使用
2021/04/13 HTML / CSS
Flask搭建一个API服务器的步骤
2021/05/28 Python
CSS实现切角+边框+投影+内容背景色渐变效果
2021/11/01 HTML / CSS