七、JS项目实战

郁子大约 21 分钟约 6357 字笔记渡一教育语言基础袁进韩刚丁永志谢杰JavaScript

(一)文字滚动效果

1.编写 JS 前需考虑

  • 初始化:一开始要做什么
  • 交互:用户操作之后要做什么

(二)手风琴效果

规范

DRY:don't repeat yourself

能封装成模块的功能函数尽量抽离出来

1.JS 动画函数

  • 动画的本质:从一个值变化到另一个值
function createAnimation(options) {
  var from = options.from; // 起始值
  var to = options.to; // 结束值
  var totalMS = options.totalMS || 1000; // 变化总时间
  var duration = options.duration || 15; // 动画间隔时间
  var times = Math.floor(totalMS / duration); // 变化的次数
  var dis = (to - from) / times; // 每一次变化改变的值
  var curTimes = 0; // 当前变化的次数
  var timerId = setInterval(function () {
    from += dis;
    curTimes++; // 当前变化增加一次
    if (curTimes >= times) {
      // 变化的次数达到了
      from = to; // 变化完成了
      clearInterval(timerId); // 不再变化了
      options.onend && options.onend();
    }
    // 无数的可能性 —— 回调模式
    options.onmove && options.onmove(from);
  }, duration);
}

2.回调模式

  • 满足以下两点即可使用回调模式
    • 事件函数知道什么时候处理,但不知道怎么处理
    • 绑定事件的对象知道怎么处理,但不知道什么时候处理
  • 通过回调函数参数交互

(三)动态排序表格效果

1.localeCompare

  • localeCompare 是一种基于国际化字体的地区字符比较
    • 例如中国用中文,美国用英文,法国用法文,德国用德文......
    • 将这些国家的文字按照国家/地区等进行编号,然后每个编号都对应了该国/地区的文字
  • 传入两个参数:
    • 参数 1:待比较的字符串
    • 参数 2:字符串文字对应的国家/地区的编号
  • 返回值:
    • 正数:参数 1 顺序排在调用的变量之前
    • 负数:参数 1 顺序排在调用的变量之后
    • 零:参数 1 和调用的变量相等,顺序不分先后
var val1 = "张三",
  val2 = "李四他爸爸";
val1.localeCompare(val2, "zh");

2.appendChild

  • parentNode.appendChild(chileNode) 方法将一个节点附加到指定父节点的子节点列表的末尾处
  • 如果将被插入的节点已经存在于当前文档的文档树中【即原本就是该父节点的一个子节点】
    • 那么 appendChild() 只会将它从原先的位置移动到新的位置
    • 不需要事先移除要移动的节点

(四)三级联动效果

1.中国各省市大学名称【2017 年整理】

渡一教育 - JS 项目实战 - AllSchool.jsopen in new window

  • 省会字典
    • 标号:省市名称
  • 城市字典
    • 省标号:{ 城市标号:城市名称 }
  • 学校字典
    • 城市标号:[大学 1, 大学 2]

(五)腾讯视频重磅推荐模块

1.使用自定义属性

  • 在初始化标题列表的同时绑定 id 值
  • 便于后续绑定事件
// 绑定自定义属性
var el = document.querySelector(".menu-item[data-index='" + id + "']");

// 获取自定义属性值
changeVideoContent(this.getAttribute("data-index"));

(六)图片放大镜

1.大图移动距离

  • 其实就是放大镜的 top、left 的距离
  • 需要取负值
// 放大镜偏移
mirror.style.left = newX + "px";
mirror.style.top = newY + "px";

// 大图移动
bigImg.style.backgroundPosition = `${-newX}px ${-newY}px`;

(七)积分抽奖效果

1.奖品顺时针高亮的效果

  • 按奖品数组顺序遍历
  • 每次去除上一个奖品的高亮样式,再为当前奖品添加高亮样式
  • 因此奖品需要使用固定定位,排列成一周
    • 不能使用正常的文档流定位
prizes[currentActive].classList.remove("active");
var nextActive = (currentActive + 1) % prizes.length;
prizes[nextActive].classList.add("active");
currentActive = nextActive;

2.定时器 Bug

  • 多次点击抽奖按钮会开启多个定时器,导致抽奖函数多次执行
  • 需要做防抖
var timer = null;
function playLotteryOnce() {
  if (currentCount < totalCount) {
    if (timer) clearInterval(timer);
    timer = setInterval(() => {
      // ...
    }, 50);
  }
}
lotteryBtn.addEventListener("click", playLotteryOnce);

(八)JS 倒计时效果

1.transition 属性

1)作用

  • 从一种状态过渡到另一种状态
  • 用于在一定的时间内进行元素平滑的过渡
  • 这种效果可以在元素被单击,鼠标滑过,或者是其他的事件中触发,实现圆滑的以动画效果改变 CSS 属性的效果

2)子属性

  • transition 属性是个复合属性
属性名含义
transition-property规定设置过渡效果的 css 属性名称,常用值
all:全部 css 属性进行动画效果添加
transition-duration规定完成过渡效果需要多少秒或毫秒
transition-timing-function指定过渡函数,规定速度效果的速度曲线
常用值(关键字描述):linear ease-in ease-in-out
transition-delay指定开始出现的延迟时间

3)使用方法

  • hover 效果实现
div {
  width: 200px;
  height: 200px;
  background-color: red;
  transition: all 0.2s linear; // all => 全部执行 200毫秒内执行完成 以线性方式执行
}
div:hover {
  background-color: yellow;
}
  • 以事件的形式进行 trainstion 属性添加
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box {
        width: 200px;
        height: 200px;
        background-color: red;
        position: absolute;
        left: 200px;
        top: 0px;
      }
    </style>
  </head>

  <body>
    <div class="box"></div>
    <button id="btn">点击进行transtion属性添加</button>

    <script>
      document.getElementById("btn").addEventListener("click", function () {
        var box = document.getElementsByClassName("box")[0];
        box.style.transition = "all .5s linear";
        box.style.backgroundColor = "yellow";
        box.style.top = "200px";
      });
    </script>
  </body>
</html>

2.动画结束事件 transitionend

  • 当动画执行完成之后,dom 元素会触发 transitionend 事件
var firstChild = el.querySelectorAll("li")[0];
el.style.marginTop = "-120px";
el.style.transition = "all 0.1s linear";
el.addEventListener("transitionend", function () {
  el.style.marginTop = "0px";
  el.style.transition = "none";
  el.appendChild(firstChild);
});

3.倒计时效果

  • 为时、分、秒的十位和个位分别开启定时器
  • 通过定时器的时间间隔模拟倒计时
handleChangeTime(document.querySelector("#hour_ten"), 1000 * 60 * 60 * 3);
handleChangeTime(document.querySelector("#hour_one"), 1000 * 60 * 60);
handleChangeTime(document.querySelector("#minute_ten"), 1000 * 60 * 10);
handleChangeTime(document.querySelector("#minute_one"), 1000 * 60);
handleChangeTime(document.querySelector("#second_ten"), 1000 * 10);
handleChangeTime(document.querySelector("#second_one"), 1000);

(九)无缝轮播图

1.动画函数(ver 2.0)

  • 如果有 onend 函数
    • 先执行 onmove 函数
    • 再执行 onend 函数
    • 最后结束本次函数调用
function createAnimation(options) {
  var from = options.from;
  var to = options.to;
  var totalMS = options.totalMS || 1000;
  var duration = options.duration || 15;

  // 计算动画变化的次数
  var times = Math.floor(totalMS / duration);
  // 计算数字每次动画变化多少
  var dis = (to - from) / times;

  // 当前变化次数
  var curTime = 0;
  var timer = setInterval(() => {
    from += dis;
    curTime++;
    if (curTime >= times) {
      from = to;
      clearInterval(timer);
      options.onmove && options.onmove(from);
      options.onend && options.onend();
      return;
    }
    options.onmove && options.onmove(from);
  }, duration);
}



















 
 
 




(十)图片瀑布流

1.什么是瀑布流

  • 瀑布流,又称瀑布流式布局
  • 是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局
  • 随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部

2.制作思路

1)瀑布流图片都是定宽不定高的

  • 定宽,就能计算出一共显示几列

  • 得到列数后,用一个数组保存每一行的高度
  • 按照 4 列来算,一开始一张图片都没有放,每一列的高度都为 0,所以数组里面是 4 个 0

2)铺满第一行

  • 放入第一张图片,找数组里面最小的,目前都是 0,就放在第一列
  • 放完之后需要更新数组里面的最小值

  • 依此类推,找数组最小的,会找到第二个 0,往第二列放入图片
  • 更新数组,找到第三个 0,往第三列放入图片
  • 更新数组...

3)铺满下一行

  • 第一行满了,该放在第二行了,但是放在第二行的第几列呢?
    • 实际上和上面的算法是一样的,找数组的最小值即可
    • 哪个最小就放在哪一列,放完之后更新数组

新的高度的计算公式

这一列新的高度 = 这一列高度(数组里面存储的) + 间隙 + 新的图片高度

4)计算第几列

  • 这只是计算了 top 值,还有 left 值需要计算
  • 每张图片的 left 值只和 该图片所在的列 有关

3.函数防抖

  • 图片已经按照瀑布流的形式布局出来了
  • 当我们改变窗体大小的时候,图片需要重新进行布局
  • 要监听 widnow 的 resize 事件
    • 每当此事件触发时,就需要重新排列

警告

布局函数是一个耗时长且复杂的函数,频繁触发 reflow 会极大影响用户体验

并且 resize 过程中无需触发重新布局,resize 结束后再根据最后窗口大小重新布局

需要使用函数防抖

var timeId = null; // 一个计时器的 id
// 主要就是绑定窗口尺寸改变的监听事件
window.onresize = function () {
  if (timeId) {
    clearTimeout(timeId);
  }
  timeId = setTimeout(function () {
    setPositions(); // 重新排列
  }, 500);
};

(十一)分页插件

1.什么是分页

2.如何制作分页

3.createPager 的实现

1)【首页】、【上一页】、【下一页】、【尾页】

  • 这四个按钮分为能够点击和不能点击两种情况

2)中间数字页码

  • 中间的数字会有一个边界,要先把这个边界找出来

  • min 最小数字的计算方式:

  • max 最大数字的计算方式:

  • 在从最小数字到最大数字的循环中,如果 i 等于 page,那么说明是当前页,挂上 active 样式类

4.分页跳转

  • 跳转的本质,其实就是重新调用 createPager
  • 传递新的页码,其他参数不变
  • 跳转完成后,后续还需要发送请求从服务器上面获取对应页码的数据

(十二)五子棋游戏

1.HTML5 新增查询 API

  • querySelector
    • 只会选择匹配的第一个元素
  • querySelectorAll
    • 会选择所有匹配的元素
// 模拟 jquery 封装两个查询方法:
function $(selector) {
  return document.querySelector(selector);
}

function $$(selector) {
  return document.querySelectorAll(selector);
}

2.模板字符串

  • 模板字符串使用反引号 (``) 来代替普通字符串中的双引号和单引号
  • 模板字符串可以包含特定语法(${expression})的占位符
var name = "xiejie";
console.log(`Hello,${name}`);
  • 以前使用字符串拼接
var chessPoint = {
  c: "white",
  x: 2,
  y: 3,
};
var newChess = "<div style='' class='chess " + chessPoint.c + "' data-row='" + chessPoint.y + "' data-line='" + chessPoint.x + "'></div>";

// <div class='chess white' data-row='3' data-line='2'></div>
  • 现在使用字符串模板
var chessPoint = {
  c: "white",
  x: 2,
  y: 3,
};
var newChess = `<div class='chess ${chessPoint.c}' data-row='${chessPoint.y}' data-line='${chessPoint.x}'></div>`;

3.clientWidth

  • Element.clientWidth 属性表示元素的内部宽度,单位是像素
  • 该属性包括内边距 padding
  • 但不包括边框 border 、外边距 margin 和垂直滚动条(如果有的话)

4.棋盘的绘制

  • 绘制棋盘,其实就是一个 14 行 x 14 列 的 table 表格
  • 每个 td 会记录当前的格子是第几行第几列【通过 自定义属性 来进行记录】
    • data-row 记录行
    • data-line 记录列

1)第一行第一列

2)第一行最后一列

3)最后一行第一列

4)最后一行最后一列

5.确定落子的坐标

  • 当用户在棋盘上点击鼠标时,需要落下一颗棋子

1)获取点击的 td

  • e.target.dataset 能够获取到用户点击的是哪一个 td
{ "row": "0", "line": "0" }

2)判断落子位置

  • 落子是落在两条线的交叉处的,而不是格子中央

  • 这意味着同样一个 td 格子,用户点击的位置不同,则棋子的位置也不同

  • e.offsetXe.offsetY 可以获取到事件发生时鼠标相对于 事件源元素 的坐标
  • 所谓事件源元素就是绑定事件的那个元素

  • 首先计算出一个格子的宽高
  • 然后用户点击的 e.offsetX 小于格子宽度的一半,e.offsetY 小于格子高度的一半,则是左上区域
  • e.offsetX 小于格子宽度的一半,但是 e.offsetY 大于格子高度的一半,则是左下
  • 依此类推
//定位落子的位置是在四个角的哪一个
var positionX = e.offsetX > tdw / 2;
var positionY = e.offsetY > tdw / 2;
// 生成点击的坐标点,包含 3 个属性
// x 坐标、y 坐标和 c 落子方
var chessPoint = {
  x: positionX ? parseInt(temp.line) + 1 : parseInt(temp.line),
  y: positionY ? parseInt(temp.row) + 1 : parseInt(temp.row),
  c: whichOne,
};
  • 重新组装格子信息,得到类似于下面的对象
{x: 0, y: 0, c: "white"} // 第一个格子左上
{x: 1, y: 0, c: "black"} // 第一个格子右上
{x: 0, y: 1, c: "white"} // 第一个格子左下
{x: 1, y: 1, c: "white"} // 第一个格子右下

6.绘制棋子

  • 绘制棋子其实就是在 td 单元格里面添加一个 div
  • 例如第一行第一个棋子
<td data-row="0" data-line="0">
  <div data-row="0" data-line="0" style="" class="white"></div>
</td>
  • 需要注意的是每一行和每一列的最后两个棋子共用一个单元格
  • 例如第一行最后两个棋子
<td data-row="0" data-line="13">
  <!-- 最后一个棋子 -->
  <div data-row="0" data-line="14" style="left: 50%;" class="black"></div>
  <!-- 倒数第二个棋子 -->
  <div data-row="0" data-line="13" style="" class="white"></div>
</td>
  • 所以最右下角的格子,会放 4 个 div

<td data-row="13" data-line="13">
  <div data-row="13" data-line="13" style="" class="white"></div>
  <div data-row="13" data-line="14" style="left: 50%;" class="black"></div>
  <div data-row="14" data-line="13" style="top: 50%;" class="white"></div>
  <div data-row="14" data-line="14" style="top: 50%; left: 50%;" class="black"></div>
</td>

7.胜负判定

  • 每一次落子都需要判断
  • 每一次落子都将这个棋子的坐标对象存储入数组
  • 每次落子遍历数组进行判断即可
  • 核心代码块
// 检查横着有没有连着的 5 个
chess2 = chessArr.find(function (item) {
  return curChess.x === item.x + 1 && item.y === curChess.y && item.c === curChess.c;
});
chess3 = chessArr.find(function (item) {
  return curChess.x === item.x + 2 && item.y === curChess.y && item.c === curChess.c;
});
chess4 = chessArr.find(function (item) {
  return curChess.x === item.x + 3 && item.y === curChess.y && item.c === curChess.c;
});
chess5 = chessArr.find(function (item) {
  return curChess.x === item.x + 4 && item.y === curChess.y && item.c === curChess.c;
});
if (chess2 && chess3 && chess4 && chess5) {
  end(curChess, chess2, chess3, chess4, chess5);
}

// 检查竖着有没有连着的 5 个
chess2 = chessArr.find(function (item) {
  return curChess.x === item.x && item.y + 1 === curChess.y && item.c === curChess.c;
});
chess3 = chessArr.find(function (item) {
  return curChess.x === item.x && item.y + 2 === curChess.y && item.c === curChess.c;
});
chess4 = chessArr.find(function (item) {
  return curChess.x === item.x && item.y + 3 === curChess.y && item.c === curChess.c;
});
chess5 = chessArr.find(function (item) {
  return curChess.x === item.x && item.y + 4 === curChess.y && item.c === curChess.c;
});
if (chess2 && chess3 && chess4 && chess5) {
  end(curChess, chess2, chess3, chess4, chess5);
}

// 检查斜线 1 有没有连着的 5 个
chess2 = chessArr.find(function (item) {
  return curChess.x === item.x + 1 && item.y + 1 === curChess.y && item.c === curChess.c;
});
chess3 = chessArr.find(function (item) {
  return curChess.x === item.x + 2 && item.y + 2 === curChess.y && item.c === curChess.c;
});
chess4 = chessArr.find(function (item) {
  return curChess.x === item.x + 3 && item.y + 3 === curChess.y && item.c === curChess.c;
});
chess5 = chessArr.find(function (item) {
  return curChess.x === item.x + 4 && item.y + 4 === curChess.y && item.c === curChess.c;
});
if (chess2 && chess3 && chess4 && chess5) {
  end(curChess, chess2, chess3, chess4, chess5);
}

// 检查斜线 2 有没有连着的 5 个
chess2 = chessArr.find(function (item) {
  return curChess.x === item.x - 1 && item.y + 1 === curChess.y && item.c === curChess.c;
});
chess3 = chessArr.find(function (item) {
  return curChess.x === item.x - 2 && item.y + 2 === curChess.y && item.c === curChess.c;
});
chess4 = chessArr.find(function (item) {
  return curChess.x === item.x - 3 && item.y + 3 === curChess.y && item.c === curChess.c;
});
chess5 = chessArr.find(function (item) {
  return curChess.x === item.x - 4 && item.y + 4 === curChess.y && item.c === curChess.c;
});
if (chess2 && chess3 && chess4 && chess5) {
  end(curChess, chess2, chess3, chess4, chess5);
}

(十三)读心术小游戏

1.弹性盒子

  • 2009 年,W3C 提出了一种新的方案 —— flex 布局
  • 可以简便、完整、响应式地实现各种页面布局
  • 目前已经得到了所有浏览器的支持
  • flex 布局已经成为当前布局的首选方案

1)生成弹性容器和弹性项目

2)更改方向

  • 通过 flex-direction 可更改主轴方向

3)主轴排列

  • 通过 justify-content 可以影响主轴的排列方式

4)侧轴排列

  • 通过 align-items 可以影响侧轴的排列方式

2.网格布局

  • grid 布局与 flex 布局有一定的相似性,都可以指定容器内部多个项目的位置
  • flex 布局是轴线布局,只能指定“项目”针对轴线的位置,可以看作是一维布局
  • grid 布局则是将容器划分成“行”和“列”,产生单元格,然后指定“项目所在”的单元格,可以看作是二维布局
  • grid 布局远比 flex 布局强大

1)display 属性

  • display: grid 可以指定一个容器采用网格布局
  • 默认情况下,所指定的容器元素为块级元素
  • 也可以通过 display: inline-grid 将其设成行内元素
<body>
  <span>foo</span>
  <div class="wrapper">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
  </div>
  <span>bar</span>
</body>
.wrapper {
  width: 450px;
  height: 450px;
  background: #f3f3f3;
  text-align: center;
  display: grid;
  grid-template-columns: 150px 150px 150px;
  grid-template-rows: 150px 150px 150px;
}
.item {
  text-align: center;
  border: 1px solid #fff;
  color: #fff;
  font-weight: bold;
  line-height: 150px;
}
.item:first-of-type {
  background: #ef342a;
}
.item:nth-of-type(2) {
  background: #00a0a0;
}
.item:nth-of-type(3) {
  background: #a0a0ff;
}
.item:nth-of-type(4) {
  background-color: skyblue;
}
.item:nth-of-type(5) {
  background-color: greenyellow;
}
.item:last-of-type {
  background-color: pink;
}

2)grid-template-rows 和 grid-template-columns 属性

  • 容器指定了网格布局以后,接着就要划分行和列
    • grid-template-columns 属性定义每一列的列宽
    • grid-template-rows 属性定义每一行的行高
  • 指定了一个 3 行 3 列的网格,列宽和行高都是 150px
.wrapper {
  width: 450px;
  height: 450px;
  background: #f3f3f3;
  text-align: center;
  display: grid;
  grid-template-columns: 150px 150px 150px;
  grid-template-rows: 150px 150px 150px;
}
  • 除了使用绝对单位,也可以使用百分比
.wrapper {
  width: 450px;
  height: 450px;
  background: #f3f3f3;
  text-align: center;
  display: grid;
  grid-template-columns: 33.33% 33.33% 33.33%;
  grid-template-rows: 33.33% 33.33% 33.33%;
}
  • 通过 grid-template-columns 属性和百分比值的配合可以很轻松的写出两栏式布局
.wrapper {
  width: 450px;
  height: 450px;
  background: #f3f3f3;
  text-align: center;
  display: grid;
  grid-template-columns: 70% 30%;
}

3)repeat 方法

  • 可以使用 repeat 函数,简化重复的值
.wrapper {
  width: 450px;
  height: 450px;
  background: #f3f3f3;
  text-align: center;
  display: grid;
  grid-template-columns: repeat(3, 150px);
  grid-template-rows: repeat(3, 150px);
}
  • repeat 方法接受两个参数
    • 第一个参数是重复的次数
    • 第二个参数是所要重复的值
  • 也可以重复某种模式
/* 定义了 6 列,第一列和第四列的宽度为 100px,第二列和第五列为 20px,第三列和第六列为 80px */
grid-template-columns: repeat(2, 100px 20px 80px);

4)示例

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    .container {
      width: 500px;
      height: 500px;
      border: 1px solid;
      display: grid;
      grid-template-columns: repeat(2, 250px);
      grid-template-rows: 200px 200px;
    }
    .container div {
      border: 1px solid;
      text-align: center;
      font-size: 18px;
      line-height: 100px;
    }
  </style>
</head>
<body>
  <div class="container">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
  </div>
</body>

3.CSS 过渡效果

  • 在 CSS3 中,新增了过渡效果,可以在样式切换时更加的丝滑,不至于两个样式之间切换很生硬

1)transition

transition: property duration timing-function delay;
  • 是复合属性,包括以下几个子属性:
    • transition-property :规定设置过渡效果的 css 属性名称
    • transition-duration :规定完成过渡效果需要多少秒或毫秒
    • transition-timing-function :指定过渡函数,规定速度效果的速度曲线
    • transition-delay :指定开始出现的延迟时间

2)示例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      div {
        width: 100px;
        height: 100px;
        background-color: red;
        transition: all 1s;
      }
      div:hover {
        height: 300px;
      }
    </style>
  </head>
  <body>
    <div></div>
  </body>
</html>

4.CSS 变形

  • CSS 变形 transform 是一些效果的集合
  • 主要是移动、旋转、缩放和倾斜这四种基本操作
  • 还可以通过设置 matrix 矩阵来实现更复杂的效果
  • 变形 transform 可以实现 2D 和 3D 两种效果

1)旋转 ratate 函数

  • 通过指定的角度参数使元素相对原点进行旋转
  • 主要在二维空间内进行操作,设置一个角度值,用来指定旋转的幅度
    • 如果这个值为 正值 ,元素相对原点中心 顺时针 旋转
    • 如果这个值为 负值 ,元素相对原点中心 逆时针 旋转
  • transform:rotate(-20deg)

2)扭曲 skew 函数

  • 能够让元素 倾斜显示
  • 可以将一个对象以其中心位置围绕着 X 轴Y 轴 按照一定的角度倾斜
  • 这与 rotate()函数的旋转不同,rotate()函数只是旋转,而不会改变元素的形状
    • skew()函数不会旋转,而只会改变元素的形状
  • 一个参数:表示水平方向的倾斜角度
  • 两个参数:第一个参数表示水平方向的倾斜角度,第二个参数表示垂直方向的倾斜角度
  • 分 3 种情况
  • transform:skewX(30deg)

  • transform:skewY(10deg)

  • transform:skew(-45deg)

3)缩放 scale 函数

  • 让元素根据中心原点对对象进行缩放
  • scale() 的取值默认的值为 1
  • 当值设置为 0.010.99 之间时,作用使一个元素缩小
  • 而任何大于或等于 1.01 的值,作用是让元素放大
  • 分 3 种情况
  • transform:scale(x,y)
    • 使元素水平方向和垂直方向同时缩放

  • transform:scale(x)
    • X 轴缩放

  • transform:scale(y)
    • Y 轴缩放

4)位移 translate 函数

  • 可以将元素向指定的方向移动,类似于 position 中的 relative
  • 简单理解为,使用 translate()函数,可以把元素从原来的位置移动,而不影响在 X、Y 轴上的任何 Web 组件
  • 分为三种情况:
  • transform:translate(x,y)
    • 使元素水平方向和垂直方向同时移动

  • transform:translateX(x)
    • 使元素水平方向移动

  • transform:translateY(y)
    • 使元素垂直方向移动

5)原点 transform-origin

  • 任何一个元素都有一个中心点
  • 默认情况之下,其中心点是居于元素 X 轴和 Y 轴的 50%处

  • 在没有重置 transform-origin 改变元素原点位置的情况下,CSS 变形进行的旋转、位移、缩放,扭曲等操作都是 以元素自己中心位置进行变形
  • 可以通过 transform-origin 来对元素进行原点位置改变,使元素原点不在元素的中心位置,以达到需要的原点位置
  • transform-origin 取值和元素设置背景中的 background-position 取值类似(也可以是具体的像素值)

5.随机数

  • 游戏原理:任意一个两位数,分别减去其十位数和个位数,得到的都是 9 的倍数
  • 利用随机数,每次从图片列表中选一张图片,作为 9 的倍数对应的结果图片

1)产生随机数

Math.floor(Math.random() * 可能性数 + 第一个可能值);

// 例如,生成 1-10 的随机数
Math.floor(Math.random() * 10 + 1);

2)封装一个函数

// 返回从 min 到 max 的随机数
function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

6.transitionend

  • 该事件会在 transition 过渡效果结束后触发
  • 通常该事件绑定后要在适当时候移除
    • 否则下一次 transition 会直接触发
function handleTransitionEnd() {
  roundImage.style.opacity = 0;
  isGameOver = true;
}
roundContainer.addEventListener("transitionend", handleTransitionEnd);

(十四)图片拖动验证

1.CSS sprite 精灵图

  • CSS Sprite,雪碧图或精灵图,它是一种图像拼合技术
  • 该方法是将小图标和背景图像合并到一张图片上,然后利用 css 的背景定位来显示需要显示的图片部分
  • 雪碧图的使用有以下几个优点:
    • 减少图片的字节
    • 减少网页的 http 请求,从而大大的提高页面的性能
    • 解决了网页设计师在图片命名上的困扰,只需对一张集合的图片上命名就可以了,不需要对每一个小元素进行命名,从而提高了网页的制作效率
    • 更换风格方便,只需要在一张或少张图片上修改图片的颜色或样式,整个网页的风格就可以改变,维护起来更加方便
/* 语法 */
background-position: npx npx;
  • 第一个值是调左右的,当需要将背景图向右调的时候用正值,向左则为负值
  • 同理将背景图上下调动的时候上是用负值,下是正值

2.拖动按钮的距离计算

  • 原理:空缺图块必须出现在容器宽度的右半侧才能拖动
  • 如何计算拖动按钮的距离
    • 用户之所以可以按住按钮实时的进行滑动,实际上就是在不停的修改按钮的 left 值
    • 那么 实时的得到按钮最新的 left 值 就是一个非常重要的点

重要

按钮实时的 left 值 = 滑条的 clientX - 滑条的 offsetLeft - 按钮的 offsetX

上次编辑于: