From 3ad6e6c760a81f687852928e4d3096da81a8f5ed Mon Sep 17 00:00:00 2001 From: qianguyihao Date: Fri, 2 Feb 2018 21:19:12 +0800 Subject: [PATCH] update readme --- 03-JavaScript基础/09-事件.md | 144 ++++ .../07-DOM操作练习:innerHTML的方式创建元素.md | 15 +- .../01-offset家族和匀速动画(含轮播图的实现).md | 682 ++++++++++++++++++ 06-JavaScript进阶/02-缓动动画.md | 55 ++ README.md | 19 + 5 files changed, 911 insertions(+), 4 deletions(-) create mode 100644 03-JavaScript基础/09-事件.md create mode 100644 06-JavaScript进阶/01-offset家族和匀速动画(含轮播图的实现).md create mode 100644 06-JavaScript进阶/02-缓动动画.md diff --git a/03-JavaScript基础/09-事件.md b/03-JavaScript基础/09-事件.md new file mode 100644 index 0000000..5731e1c --- /dev/null +++ b/03-JavaScript基础/09-事件.md @@ -0,0 +1,144 @@ + + +## 绑定事件的两种方式 + +我们在上一篇文章中已经讲过事件的概念。这里讲一下注册事件的两种方式,我们以onclick事件为例。 + + +### 方式一:onclick + +举例: + +```html + + + + + +``` + +点击按钮后,上方代码的打印结果: + + +```html +事件2 +``` + +我们可以看到,这种绑定事件的方式,会层叠掉之前的事件。 + + +### 方式二:addEventListener + +addEventListener()里的参数: + +- 参数1:事件名(不带on) + +- 参数2:事件名(执行函数) + +- 参数3:事件名(捕获或者冒泡) + + +举例: + +```html + + + + +``` + + +点击按钮后,上方代码的打印结果: + + +```html +事件1 +事件2 +``` + +我们可以看到,这种绑定事件的方式,不会层叠掉之前的事件。 + + + + + +```html + +``` + + + + + +```html + +``` + + + + + +```html + +``` + + + + + +```html + +``` + + + + + +```html + +``` + + + + + +```html + +``` + + + + + +```html + +``` + diff --git a/04-前端基础练习/07-DOM操作练习:innerHTML的方式创建元素.md b/04-前端基础练习/07-DOM操作练习:innerHTML的方式创建元素.md index 891f302..2dd366f 100644 --- a/04-前端基础练习/07-DOM操作练习:innerHTML的方式创建元素.md +++ b/04-前端基础练习/07-DOM操作练习:innerHTML的方式创建元素.md @@ -42,7 +42,7 @@ document.write(); 效果如下: -20180129_1908.png +![](http://img.smyhvae.com/20180129_1908.png) **方式二:**innerHTML @@ -77,7 +77,7 @@ document.write(); 效果如下: -20180129_2017.png +![](http://img.smyhvae.com/20180129_2017.png) @@ -109,7 +109,9 @@ document.write(); 现在要做下面这样一个页面: -20180129_2151.png + +![](http://img.smyhvae.com/20180129_2151.png) + 上图的意思是,每次刷新页面,都从服务器获取最新的在线人数的名单(我们先用本地的数组来模拟服务器上的数据)。 @@ -334,12 +336,17 @@ document.write(); ``` +工程文件: + +- [2018-02-01-获取在线用户列表demo.rar](http://download.csdn.net/download/smyhvae/10237611) + + ## innerHTML举例2:模拟百度搜索的下方提示 要求实现的效果如下: -20180201_2030.gif +![](http://img.smyhvae.com/20180201_2030.gif) 在这之前,我们先实现这样一个例子:**判断字符串以某个字符串为开头**。 diff --git a/06-JavaScript进阶/01-offset家族和匀速动画(含轮播图的实现).md b/06-JavaScript进阶/01-offset家族和匀速动画(含轮播图的实现).md new file mode 100644 index 0000000..1316e2f --- /dev/null +++ b/06-JavaScript进阶/01-offset家族和匀速动画(含轮播图的实现).md @@ -0,0 +1,682 @@ + + +> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8407109.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + +> 以下是正文。 + + +## 前言 + +JS动画的主要内容如下: + +1、三大家族和一个事件对象: + +- 三大家族:offset/scroll/client。也叫三大系列。 + +- 事件对象/event(事件被触动时,鼠标和键盘的状态)(通过属性控制)。 + +2、动画(闪现/匀速/缓动) + +3、冒泡/兼容/封装 + +4、正则 + +## offset家族简介 + +我们知道,三大家族包括:offset/scroll/client。今天来讲一下offset,以及与其相关的匀速动画。 + +> offset的中文是:偏移,补偿,位移。 + +js中有一套方便的**获取元素尺寸**的办法就是offset家族。offset家族包括: + +- offsetWidth + +- offsetHight + +- offsetLeft + +- offsetTop + +- offsetParent + +下面分别介绍。 + +### 1、offsetWidth 和 offsetHight + +用于检测盒子自身的**宽高+padding+border**,不包括margin。如下: + +- offsetWidth = width + padding + border; + +- offsetHeight = Height + padding + border; + +这两个属性,他们绑定在了所有的节点元素上。获取之后,只要调用这两个属性,我们就能够获取元素节点的宽和高。 + +举例如下: + +```html + + + + + + + + + +
+ + + +``` + +### 2、offsetLeft 和 offsetTop + +返回距离上级盒子(带有定位)左边的位置;如果父级都没有定位,则以body为准。 + +offsetLeft: 从父亲的 padding 开始算,父亲的 border 不算。 + +举例: + +```html + + + + + + + + +
+
+
+ + + + + +``` + +在父盒子有定位的情况下,offsetLeft == style.left(去掉px之后)。注意,后者只识别行内样式。但区别不仅仅于此,后面会讲。 + +### 3、offsetParent + +检测父系盒子中带有定位的**父盒子节点**。返回结果是该对象的父级(带有定位)。 + +- 如果当前元素的父级元素,**没有CSS定位**(position为absolute、relative、fixed),那么offsetParent的返回结果为**body**。 + +- 如果当前元素的父级元素,**有CSS定位**(position为absolute、relative、fixed),那么offsetParent的返回结果为**最近的**那个父级元素。 + +举例: + +```html + + + + + + + +
+
+
+
+
+ + + +``` + +打印结果: + +![](http://img.smyhvae.com/20180202_1725.png) + +### offsetLeft和style.left区别 + +(1)最大区别在于: + +offsetLeft 可以返回没有定位盒子的距离左侧的位置。如果父系盒子中都没有定位,以body为准。 + +style.left 只能获取行内式,如果没有,则返回""(意思是,返回空); + +(2)offsetTop 返回的是数字,而 style.top 返回的是字符串,而且还带有单位:px。 + +比如: + +```javascript + +div.offsetLeft = 100; +div.style.left = "100px"; + +``` + +(3)offsetLeft 和 offsetTop **只读**,而 style.left 和 style.top 可读写(只读是获取值,可写是赋值) + + +(4)如果没有给 HTML 元素指定过 top 样式,则style.top 返回的是空字符串。 + +总结:我们一般的做法是:**用offsetLeft 和 offsetTop 获取值,用style.left 和 style.top 赋值**(比较方便)。理由如下: + +- style.left:只能获取行内式,获取的值可能为空,容易出现NaN。 + +- offsetLeft:获取值特别方便,而且是现成的number,方便计算。它是只读的,不能赋值。 + + +## 动画的种类 + +- 闪现(基本不用) + +- 匀速(本文重点) + +- 缓动(后续重点) + +简单举例如下:(每间隔500ms,向右移动盒子100px) + +```html + + + + + + + + + +
+ + + + +``` + +效果如下: + +![](http://img.smyhvae.com/20180202_1840.gif) + +## 匀速动画的封装:每间隔30ms,移动盒子10px【重要】 + + +代码如下: + +```html + + + + + + + + +
+ + +
+
+
+ + + + +``` + +实现的效果: + +![](http://img.smyhvae.com/20180202_1910.gif) + +上方代码中的方法封装,可以作为一个模板步骤,要记住。其实,这个封装的方法,写成下面这样,会更严谨,更容易理解:(将if语句进行了改进) + +```javascript + //【重要】方法的封装:每间隔30ms,将盒子向右移动10px + function animate(ele, target) { + //要用定时器,先清除定时器 + //一个盒子只能有一个定时器,这样的话,不会和其他盒子出现定时器冲突 + //我们可以把定时器本身,当成为盒子的一个属性 + clearInterval(ele.timer); + //我们要求盒子既能向前又能向后,那么我们的步长就得有正有负 + //目标值如果大于当前值取正,目标值如果小于当前值取负 + var speed = target > ele.offsetLeft ? 10 : -10; //speed指的是步长 + ele.timer = setInterval(function () { + //在执行之前就获取当前值和目标值之差 + var val = target - ele.offsetLeft; + + //移动的过程中,如果目标值和当前值之差如果小于步长,那么就不能在前进了 + //因为步长有正有负,所有转换成绝对值来比较 + if (Math.abs(val) < Math.abs(speed)) { //如果val小于步长,则直接到达目的地;否则,每次移动一个步长 + ele.style.left = target + "px"; + clearInterval(ele.timer); + } else { + ele.style.left = ele.offsetLeft + speed + "px"; + } + }, 30) + } +``` + +## 代码举例:轮播图的实现 + +完整版代码如下:(注释已经比较详细) + +```html + + + + + 无标题文档 + + + + + + +
+
+
    +
  • +
  • +
  • +
  • +
  • +
+
    + +
+
+ < + > +
+
+
+ + + + +``` + +实现效果: + +![](http://img.smyhvae.com/20180202_2020.gif) + +温馨提示:动图太大,可以把单独在浏览器中打开。 + +工程文件: + +- [2018-02-02-JS动画实现轮播图.rar](http://download.csdn.net/download/smyhvae/10237662) + + +## 我的公众号 + +想学习**代码之外的软技能**?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](http://img.smyhvae.com/2016040102.jpg) + diff --git a/06-JavaScript进阶/02-缓动动画.md b/06-JavaScript进阶/02-缓动动画.md new file mode 100644 index 0000000..5ce7c79 --- /dev/null +++ b/06-JavaScript进阶/02-缓动动画.md @@ -0,0 +1,55 @@ + + +## 缓动动画 + +### 缓动动画的原理 + +缓动动画的原理就是:在移动的过程中,步长越来越小。 + +设置步长为**:目标位置和盒子当前位置的十分之一**。用公式表达,即: + +``` + 盒子位置 = 盒子本身位置 + (目标位置 - 盒子本身位置)/ 10; +``` + +代码举例: + +```html + + + + + + + + + +
+ + + + +``` + +效果: + +20180202_2046.gif diff --git a/README.md b/README.md index 1c75550..7f852e7 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ - [07-JavaScript基础:DOM操作](./03-JavaScript/07-JavaScript基础:DOM操作.md) +- [08-JavaScript基础:BOM的常见内置方法和内置对象](./03-JavaScript/08-JavaScript基础:BOM的常见内置方法和内置对象.md) + ## 前端基础练习 @@ -51,6 +53,23 @@ - [02-CSS基础练习:JD首页的制作(快捷导航部分)](./04-前端基础练习/02-CSS基础练习:JD首页的制作(快捷导航部分).md) +- [03-DOM操作练习:基础练习](./04-前端基础练习/03-DOM操作练习:基础练习.md) + +- [04-DOM操作练习:Tab栏切换(通过className设置样式)](./04-前端基础练习/04-DOM操作练习:Tab栏切换(通过className设置样式).md) + +- [05-DOM操作练习:访问关系的封装)](./04-前端基础练习/05-DOM操作练习:访问关系的封装.md) + +- [06-DOM操作练习:通过style对象设置样式](./04-前端基础练习/06-DOM操作练习:通过style对象设置样式.md) + +- [07-DOM操作练习:innerHTML的方式创建元素](./04-前端基础练习/07-DOM操作练习:innerHTML的方式创建元素.md) + +- [08-JavaScript基础:定时器](./04-前端基础练习/08-JavaScript基础:定时器.md) + + +## JavaScript进阶 + + +- [01-offset家族和匀速动画(含轮播图的实现)](./06-JavaScript进阶/01-offset家族和匀速动画(含轮播图的实现).md)