GitHub上的2048 源码分析

做为一个JS白痴,学习一门新新技术最快最好的方式就是抄,说出来有点危言耸听。不过确实如此。

这是一个基于html 由android包裹而成的WebApp

GitHub https://github.com/goodluckforme/2048-android

为了掌握web开发 我将逐一分析每一行代码

HTML基础

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
</body>
<html>

Head部分

标题

<title>2048</title>

标准的Css引用

<link href="style/main.css" rel="stylesheet" type="text/css">

标签上显示的小图片 验证:更换图片刷新就知道哪里了 请查看

<link rel="shortcut icon" href="favicon.ico">

Apple手机中网页logo和上面的一致 验证:请查看

 <link rel="apple-touch-icon" href="meta/apple-touch-icon.png">

IOS设备的启动页 验证 请查看

 <link rel="apple-touch-startup-image" href="meta/apple-touch-startup-image-640x1096.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)"> <!-- iPhone 5+ -->
<link rel="apple-touch-startup-image" href="meta/apple-touch-startup-image-640x920.png"  media="(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)"> <!-- iPhone, retina -->

WebApp 里Meta标签大全,webappmeta标签大全
全屏

<meta name="apple-mobile-web-app-capable" content="yes">

状态栏颜色黑色

<meta name="apple-mobile-web-app-status-bar-style" content="black">

针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓请查看

    <meta name="HandheldFriendly" content="True">

微软的老式浏览器

<meta name="MobileOptimized" content="320">
  • width - viewport的宽度
  • height - viewport的高度
  • initial-scale - 初始的缩放比例
  • minimum-scale - 允许用户缩放到的最小比例
  • maximum-scale - 允许用户缩放到的最大比例
  • user-scalable - 用户是否可以手动缩放

验证 请查看

<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0, maximum-scale=1, user-scalable=no, minimal-ui">

Body部分

引入js代码

<script src="js/i18n.js"></script>

引用样式 container heading

<div class="container"> </div>
<div class="heading"></div>

布局中的标题哦

 <h1 class="title">2048</h1>

最佳得分 和 当前得分

<div class="scores-container">
        <div class="score-container">0</div>
        <div class="best-container">0</div>
</div>

这个是清除浮动的意思 即浏览器窗口变小 模块会直接换行 不跟随移动

<div class="above-game"></div>

.above-game:after {
  content: "";
  display: block;
  clear: both; }

一个A链接

  <a id="nightbtn"><img src="style/night.png"></a>

**写入一段话:Join the numbers and get to the 2048 tile!
加入代码必须用 script 模块**

<p class="game-intro"><script>document.write(i18n.get('intro'))</script></p>

又是两个A链接

<a class="restart-button"><script>document.write(i18n.get('new_game'))</script></a>
<a class="undo-button"><script>document.write(i18n.get('undo'))</script></a>   

九宫格背景

 <div class="grid-container">
        <div class="grid-row">
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
        </div>
        <div class="grid-row">
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
        </div>
        <div class="grid-row">
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
        </div>
        <div class="grid-row">
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
          <div class="grid-cell"></div>
        </div>
      </div>

z-index 这越大 就越在最上层

  • position:fixed 相对于 窗口
  • position:relative 相当于Android的RelativeLayout
  • position:absolute 相对于父布局 的相对定位
<div class="tile-container"></div>
.tile-container {
  position: absolute;
  z-index: 2; }

Css部分

从index.html入手

有意思 和 android 类似

@import url(fonts/clear-sans.css);

这里主要是字体的定义 可参考:这里

html, body {
  margin: 0;
  padding: 0;
  background: #faf8ef;
  color: #776e65;
  font-family: "Clear Sans", "Helvetica Neue", Arial, sans-serif;
  font-size: 18px; }

@font-face {
    font-family: "Clear Sans";
    src: url("ClearSans-Light-webfont.eot");
    src: url("ClearSans-Light-webfont.eot?#iefix") format("embedded-opentype"),
         url("ClearSans-Light-webfont.svg#clear_sans_lightregular") format("svg"),
         url("ClearSans-Light-webfont.woff") format("woff");
    font-weight: 200;
    font-style: normal;
}

屏幕适配 验证 请查看

@media screen and (max-width: 520px)

属性动画:Css3中属性

@-webkit-keyframes move-up { 
0% {
    top: 25px;
    opacity: 1; }

100% {
    top: -50px;
    opacity: 0; } }

最后一个元素 Css3 属性 验证 请查看

grid-cell:last-child

这个是清除浮动的语法 dispaly 块元素表示(此元素将显示为块级元素,此元素前后会带有换行符。)验证:请查看

.heading:after {
  content: "";
  display: block;
  clear: both; }

最外层布局 居中对齐

  .container {
    width: 280px;
    margin: 0 auto; }

标题2048需要这么多样式?

position: absolute; 相对于父布局定位

transition:<过渡属性名称> <过渡时间> <过渡模式>
transition-timing-function 的五种取值:
1.ease 逐渐变慢
2.linear 匀速
3.ease-in 缓慢开始(加速)
4.ease-out 缓慢结束(减速)
5.ease-in-out 缓慢开始,缓慢结束(先加速后减速)
6.cubic-bezier 贝塞尔曲线(matthewlein.com/ceaser)
  过渡模式比如宽过渡,高过渡和all过渡

验证 请查看

-webkit-transition: 100ms ease-in-out; Css3属性动画 /* Safari 和 Chrome */
验证请查看

transition-property(指定适用时间过渡效果的css属性) 验证请查看

.tile {
  position: absolute;
  -webkit-transition: 100ms ease-in-out;
  -moz-transition: 100ms ease-in-out;
  transition: 100ms ease-in-out;
  -webkit-transition-property: -webkit-transform;
  -moz-transition-property: -moz-transform;
  transition-property: transform; }

右浮动 文本右对齐
.scores-container {
float: right;
text-align: right; }

.score-container, .best-container {
  position: relative;       相对布局 
  display: inline-block;    内联板块 
  background: #bbada0;      背景颜色
  padding: 12px 20px;       内边距 
  font-size: 25px;          字体大小    
  height: 25px;             字体高度
  line-height: 47px;        //行高度 验证:请查看 http://www.jb51.net/css/199174.html
  font-weight: bold;        字体
  border-radius: 3px;       圆角
  color: white;             字颜色
  margin-top: 8px;          上边距
  text-align: center; }     对齐方式

这部分在 html 和 css 中都没有,应该在某 js(nightmode) 当中.

 <div id="night" style="padding:10px;">
            <a id="nightbtn"><img src="style/night.png"></a>
 </div>

window.onload:防止加载完成前调用 造成找不到对象BUG 验证:请查看

‘===’验证:请查看

window.onload = function() {
  var a = document.getElementById("night");
  a.onclick = function() {
    if (document.getElementsByTagName("html")[0].style.backgroundColor === "rgb(45, 48, 44)") {
        document.getElementsByTagName("html")[0].style.backgroundColor = "#faf8ef";
        document.getElementsByTagName("body")[0].style.backgroundColor = "#faf8ef";
        return false;
    } else {
        document.getElementsByTagName("html")[0].style.backgroundColor = "#2D302C";
        document.getElementsByTagName("body")[0].style.backgroundColor = "#2D302C";
        return false;
    }
  }
}

游戏介绍 i18n.get(‘intro’)

a=b||0 b不等于undefined和null,也就是说b有东西那a就等于b的值

typeof 类型比对 和instanceof的区别 验证请查看

 <p class="game-intro"><script>document.write(i18n.get('intro'))</script></p>

 this.get = function(key) {
        if (typeof this.messages[key] === 'string') {
            return this.messages[key];
        }
        return '';
    };

A链接 restart-button 这个在哪个JS(keyboard_input_manager.js)中有调用呢?

<a class="restart-button"><script>document.write(i18n.get('new_game'))</script></a>

.restart-button {
  display: inline-block;    不换行
  background: #8f7a66;
  border-radius: 3px;
  padding: 0 20px;
  text-decoration: none;  无下划线
  color: #f9f6f2;       
  height: 40px;
  line-height: 42px;
  display: block;
  text-align: center;
  float: right;
  margin-left: 5px;
  font-size: 16px; }

application.js 中获取到 GameManager实例
game_manager.js 中设置点击事件 bindButtonPress 并初始化
- this.inputManager = new InputManager; 键盘
- this.storageManager = new StorageManager; 缓存
- this.actuator = new Actuator; 触摸事件
keyboard_input_manager.js 重写触摸事件
学习点这里

window.requestAnimationFrame(function () {
  new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
});

this.bindButtonPress(".restart-button", this.restartWithConfirmation);

KeyboardInputManager.prototype.restartWithConfirmation = function (event) {
  event.preventDefault();
  this.emit("restartWithConfirmation");
}; 

KeyboardInputManager.prototype.bindButtonPress = function (selector, fn) {
  var button = document.querySelector(selector);
  button.addEventListener("click", fn.bind(this));
  button.addEventListener(this.eventTouchend, fn.bind(this));
};

JavaScript部分

  <script src="js/bind_polyfill.js"></script>
  <script src="js/classlist_polyfill.js"></script>
  <script src="js/animframe_polyfill.js"></script>
  <script src="js/keyboard_input_manager.js"></script>
  <script src="js/html_actuator.js"></script>
  <script src="js/grid.js"></script>
  <script src="js/tile.js"></script>
  <script src="js/local_storage_manager.js"></script>
  <script src="js/game_manager.js"></script>
  <script src="js/application.js"></script>
  <script src="js/nightmode.js"></script>

classlist_polyfill.js 中 数组操作符 验证 请查看

  var prototype = Array.prototype,
      push = prototype.push,
      splice = prototype.splice,
      join = prototype.join;

DOMTokenList window成员方法重写 请查看


  DOMTokenList.prototype = {
    add: function (token) {
      if (this.contains(token)) return;
      push.call(this, token);
      this.el.className = this.toString();
    },
    contains: function (token) {
      return this.el.className.indexOf(token) != -1;
    },
    item: function (index) {
      return this[index] || null;
    },
    remove: function (token) {
      if (!this.contains(token)) return;
      for (var i = 0; i < this.length; i++) {
        if (this[i] == token) break;
      }
      splice.call(this, i, 1);
      this.el.className = this.toString();
    },
    toString: function () {
      return join.call(this, ' ');
    },
    toggle: function (token) {
      if (!this.contains(token)) {
        this.add(token);
      } else {
        this.remove(token);
      }

      return this.contains(token);
    }
  };

animframe_polyfill.js 中执行刷新动画
验证 请查看

类方法 .prototype 修饰符

Tile.prototype.savePosition = function () {
  this.previousPosition = { x: this.x, y: this.y };
};

我们需要着重看 game_manager.js 这是个核心类

待续哦···

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值