JavaScript第二講
一、事件響應
1.1 什麼是事件
JavaScript 創建動態頁面。事件是可以被 JavaScript 偵測到的行爲。 網頁中的每個元素都可以產生某些可以觸發 JavaScript 函數或程序的事件。比如說,當用戶單擊按鈕或者提交表單數據時,就發生一個鼠標單擊(onclick)事件,需要瀏覽器做出處理,返回給用戶一個結果。
1.2 鼠標單擊事件(onclick)
onclick是鼠標單擊事件,當在網頁上單擊鼠標時,就會發生該事件。同時onclick事件調用的程序塊就會被執行,通常與按鈕一起使用。
1.3 鼠標經過事件(onmouseover)
鼠標經過事件,當鼠標移到一個對象上時,該對象就觸發onmouseover事件,並執行onmouseover事件調用的程序。將上述代碼改爲鼠標經過觸發:
1.4 鼠標移開事件(onmouseout)
同理,鼠標移開事件,當鼠標移開當前對象時,執行onmouseout調用的程序。
1.5 光標聚焦事件(onfocus)
當網頁中的對象獲得聚點時,執行onfocus調用的程序就會被執行。
舉例:
1.6 失焦事件(onblur)
onblur事件與onfocus是相對事件,當光標離開當前獲得聚焦對象的時候,觸發onblur事件,同時執行被調用的程序。
假如網頁中有用戶和密碼兩個文本框。當前光標在用戶文本框內時(即焦點在文本框),在光標離開該文本框後(即失焦時),觸發onblur事件,並調用相關函數。
1.7 內容選中事件(onselect)
選中事件,當文本框或者文本域中的文字被選中時,觸發onselect事件,同時調用的程序就會被執行
1.8 文本框內容改變事件(onchange)
通過改變文本框的內容來觸發onchange事件,同時執行被調用的程序。當文本框的內容改變則觸發onchange事件,同時執行被調用的程序。
二、瀏覽器對象
2.1 JavaScript 計時器概念
在JavaScript中,我們可以在設定的時間間隔之後來執行代碼,而不是在函數被調用後立即執行。
計時器類型:
一次性計時器:僅在指定的延遲時間之後觸發一次。
間隔性觸發計時器:每隔一定的時間間隔就觸發一次。
2.2 計時器setInterval()
在執行時,從載入頁面後每隔指定的時間執行代碼。
語法:
setInterval(代碼,交互時間);
參數說明:
1.代碼:要調用的函數或要執行的代碼串。
2.交互時間:週期性執行或調用表達式之間的時間間隔,以毫秒計(1s=1000ms)。
返回值:
一個可以傳遞給 clearInterval() 從而取消對”代碼”的週期性執行的值。
舉例:
2.3 取消計時器clearInterval()
clearInterval() 方法可取消由 setInterval() 設置的交互時間。
語法:
clearInterval(id_of_setInterval)
參數說明:
id_of_setInterval:由 setInterval() 返回的 ID 值。
舉例:
2.4 計時器setTimeout()
setTimeout()計時器,在載入後延遲指定時間後,去執行一次表達式,僅執行一次。
語法:
setTimeout(代碼,延遲時間);
參數說明:
1. 要調用的函數或要執行的代碼串。
2. 延時時間:在執行代碼前需等待的時間,以毫秒爲單位(1s=1000ms)。
2.5 取消計時器clearTimeout()
同clearInterval();
語法:
clearTimeout(id_of_setTimeout)
參數說明:
id_of_setTimeout:由 setTimeout() 返回的 ID 值。該值標識要取消的延遲執行代碼塊。
三、DOM對象
3.1 認識DOM
文檔對象模型DOM(Document Object Model)定義訪問和處理HTML文檔的標準方法。DOM 將HTML文檔呈現爲帶有元素、屬性和文本的樹結構(節點樹)。
HTML DOM樹:
3.2 getElementByID()方法
返回帶有指定id的節點對象
語法:
document.getElementsById(id)
說明:
1. id是標籤的id
3.3 getElementsByName()方法
返回帶有指定名稱的節點對象的集合。
語法:
document.getElementsByName(name)
與getElementById() 方法不同的是,通過元素的 name 屬性查詢元素,而不是通過 id 屬性。
3.4 getElementsByTagName()方法
返回帶有指定標籤名的節點對象的集合。返回元素的順序是它們在文檔中的順序。
語法:
document.getElementsByTagName(Tagname)
說明:
1. Tagname是標籤的名稱,如p、a、img等標籤名。
2. 和數組類似也有length屬性,可以和訪問數組一樣的方法來訪問,所以從0開始。
3.5 區別getElementByID,getElementsByName,getElementsByTagName
以人來舉例說明,人有能標識身份的身份證,有姓名,有類別(大人、小孩、老人)等。
1. ID 是一個人的身份證號碼,是唯一的。所以通過getElementById獲取的是指定的一個人。
2. Name 是他的名字,可以重複。所以通過getElementsByName獲取名字相同的人集合。
3. TagName可看似某類,getElementsByTagName獲取相同類的人集合。如獲取小孩這類人,getElementsByTagName(“小孩”)。
舉例:
//用三種不同方式獲取節點並打印出它們的數量
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function getnum(){
/*第一種*/
alert(document.getElementById("hobby1").length);
alert(document.getElementById("hobby1").nodeName);
/*第二種*/
alert(document.getElementsByName("hobby").length);
/*第三種*/
alert(document.getElementsByTagName("input").length);
}
</script>
</head>
<body>
<input type="checkbox" name="hobby" id="hobby1"> 音樂
<input type="checkbox" name="hobby" id="hobby2"> 登山
<input type="checkbox" name="hobby" id="hobby3"> 游泳
<input type="checkbox" name="hobby" id="hobby4"> 閱讀
<input type="checkbox" name="hobby" id="hobby5"> 打球
<input type="checkbox" name="hobby" id="hobby6"> 跑步
<input type="button" value = "全選" id="button1">
<input type="button" value = "全不選" id="button1">
<br />
<input type="button" onclick="getnum()" value="看看有幾項?" />
</body>
</html>
3.6 getAttribute()方法
通過元素節點的屬性名稱獲取屬性的值。
語法:
elementNode.getAttribute(name)
說明:
1. elementNode:使用getElementById()、getElementsByTagName()等方法,獲取到的元素節點。
2. name:要想查詢的元素節點的屬性名字
舉例:
3.7 setAttribute()方法
setAttribute() 方法增加一個指定名稱和值的新屬性,或者把一個現有的屬性設定爲指定的值。
語法:
elementNode.setAttribute(name,value)
說明:
1.name: 要設置的屬性名。
2.value: 要設置的屬性值。
注意:
1.把指定的屬性設置爲指定的值。如果不存在具有指定名稱的屬性,該方法將創建一個新屬性。
2.類似於getAttribute()方法,setAttribute()方法只能通過元素節點對象調用的函數。
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function change(){
//改變input標籤裏面的value值
var temp = document.getElementById("hobby1");
temp.setAttribute("value","小花")
}
//實現全選與全不選功能
function change1(){
//改變input標籤裏面的value值
var temp = document.getElementsByName("hobby");
for(var i=1;i<temp.length;i++){
temp[i].checked = true;
}
}
function change2(){
//改變input標籤裏面的value值
var temp = document.getElementsByName("hobby");
for(var i=1;i<temp.length;i++){
temp[i].checked = false;
}
}
</script>
</head>
<body>
<input type="text" name="hobby" id="hobby1" value=”音樂”>
<input type="checkbox" name="hobby" id="hobby2" > 登山
<input type="checkbox" name="hobby" id="hobby3"> 游泳
<input type="checkbox" name="hobby" id="hobby4"> 閱讀
<input type="checkbox" name="hobby" id="hobby5"> 打球
<input type="checkbox" name="hobby" id="hobby6"> 跑步
<input type="button" value = "全選" id="button1" onclick="change1()">
<input type="button" value = "全不選" id="button1" onclick="change2()">
<br />
<input type="button" onclick="change()" value="看看有幾項?" />
</body>
</html>
3.8 訪問子節點childNodes
訪問選定元素節點下的所有子節點的列表,返回的值可以看作是一個數組,他具有length屬性。
語法:
elementNode.childNodes
注意:
如果選定的節點沒有子節點,則該屬性返回不包含節點的 NodeList。
3.9 節點屬性
在文檔對象模型 (DOM) 中,每個節點都是一個對象。DOM 節點有三個重要的屬性 :
1. nodeName : 節點的名稱
2. nodeValue :節點的值
3. nodeType :節點的類型
一、nodeName 屬性: 節點的名稱,是隻讀的。
1. 元素節點的 nodeName 與標籤名相同
2. 屬性節點的 nodeName 是屬性的名稱
3. 文本節點的 nodeName 永遠是 #text
4. 文檔節點的 nodeName 永遠是 #document
二、nodeValue 屬性:節點的值
1. 元素節點的 nodeValue 是 undefined 或 null,例如:<p> </p><br/><body></body>均爲元素節點。
2. 文本節點的 nodeValue 是文本自身,例如:<p> “Hello,World”</p> 中 “Hello,World”等屬於文本節點。
3. 屬性節點的 nodeValue 是屬性的值,例如:<p class=”lucy”></p>中class=”lucy”屬於屬性節點。
(第一步假設等等我們的html的結構是一本書,那麼元素節點就是每頁書,而文本節點則是每頁書中的文字,屬性節點就是這些文字的顏色,字體)
三、nodeType 屬性: 節點的類型,是隻讀的。以下常用的幾種結點類型:
元素 | 節點類型 |
---|---|
元素 | 1 |
屬性 | 2 |
文本 | 3 |
註釋 | 8 |
文檔 | 9 |
3.10 訪問子節點的第一和最後項
- firstChild 屬性返回‘childNodes’數組的第一個子節點。如果選定的節點沒有子節點,則該屬性返回 NULL。
語法:
node.firstChild
說明:與elementNode.childNodes[0]是同樣的效果。
- lastChild 屬性返回‘childNodes’數組的最後一個子節點。如果選定的節點沒有子節點,則該屬性返回 NULL。
語法:
node.lastChild
說明:
與elementNode.childNodes[elementNode.childNodes.length-1]是同樣的效果。
舉例:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function text(){
//獲取父節點
var container = document.getElementById("container");
//獲取子節點集合
var t1 = container.childNodes;
for(var i=0; i<t1.length; i++)
{
var node = t1[i];
if(node.nodeType == 3 && !/\S/.test(node.nodeValue))
{
//刪除空白子節點
node.parentNode.removeChild(node);
}
}
//獲取第一個子節點
var firstChild = container.firstChild;
alert(firstChild.value);
//獲取第二個子節點
var t2 = t1[1];
alert(t2.innerHTML);
}
</script>
</head>
<body>
<div id="container">
<input type="text" name="hobby" id="hobby1" value=”音樂”>
<span>lalala</span>
<input type="checkbox" name="hobby" id="hobby2"> 登山
<input type="checkbox" name="hobby" id="hobby3"> 游泳
<input type="checkbox" name="hobby" id="hobby4"> 閱讀
<input type="checkbox" name="hobby" id="hobby5"> 打球
<input type="checkbox" name="hobby" id="hobby6"> 跑步
<input type="button" value = "全選" id="button1">
<input type="button" value = "全不選" id="button1">
</div>
<input type="button" onclick="text()" value="看看有幾項?" />
<span id="content"></span>
</body>
</html>
3.11 訪問父節點parentNode
獲取指定節點的父節點
語法:
elementNode.parentNode
3.12 訪問兄弟節點
nextSibling 屬性可返回某個節點之後緊跟的節點(處於同一樹層級中)。
語法:
nodeObject.nextSibling
說明:如果無此節點,則該屬性返回 null。previousSibling 屬性可返回某個節點之前緊跟的節點(處於同一樹層級中)。
語法:
nodeObject.previousSibling
說明:
如果無此節點,則該屬性返回 null。
注意:
兩個屬性獲取的是節點。Internet Explorer 會忽略節點間生成的空白文本節點(例如,換行符號),而其它瀏覽器不會忽略。
解決問題方法:
判斷節點nodeType是否爲1, 如是爲元素節點,跳過。
3.13 插入節點appendChild()
在指定節點的最後一個子節點列表之後添加一個新的子節點。
語法:
appendChild(newnode)
參數:
newnode:指定追加的節點
3.14 插入節點insertBefore()
insertBefore() 方法可在已有的子節點前插入一個新的子節點。
語法:
insertBefore(newnode,node);
參數:
newnode: 要插入的新節點。
node: 指定此節點前插入節點。
3.15 刪除節點removeChild()
removeChild() 方法從子節點列表中刪除某個節點。如刪除成功,此方法可返回被刪除的節點,如失敗,則返回 NULL。
語法:
nodeObject.removeChild(node)
參數:
node :必需,指定需要刪除的節點。
3.16 替換元素節點replaceChild()
replaceChild 實現子節點(對象)的替換。返回被替換對象的引用。
語法:
node.replaceChild (newnode,oldnew )
參數:
newnode : 必需,用於替換 oldnew 的對象。
oldnew : 必需,被 newnode 替換的對象。
3.17 創建元素節點createElement
createElement()方法可創建元素節點。此方法可返回一個 Element 對象。
語法:
document.createElement(tagName)
參數:
tagName:字符串值,這個字符串用來指明創建元素的類型。
注意:
要與appendChild() 或 insertBefore()方法聯合使用,將元素顯示在頁面中。
四、HTML+CSS+JS動畫實例
4.1 頁面的橫向佈局
1、整個效果都是以小男孩走路爲前提,在三個主題頁面中切換並在每個主題頁面中會有不同的效果呈現
2、我們可以這樣理解,效果上
- 頁面主題會滾動
- 小男孩會走動
3、從頁面的效果,考慮頁面整體佈局結構應該需要這樣
- 頁面是一個橫向的
- 包含了3個主題頁面
- 頁面之間是無縫拼接的
- 頁面還要能滾動
4、實現:
做3個塊級元素,每一個塊元素代表一個主題頁面的容器節點。然後設置一個父容器是3個塊元素的寬,通過float處理,這樣就形成了一個橫向的3個無縫拼接的頁面
佈局結構如下:
<ul class='content-wrap'>
<!-- 第一副畫面 -->
<li> 頁面1 </li>
<!-- 第二副畫面 -->
<li> 頁面2 </li>
<!-- 第三副畫面 -->
<li> 頁面3 </li>
</ul>
4.2 頁面的滾動效果
1.列表內容一般來說要根據佈局的結構來,大體有2種:
- 移動父容器,改變父容器的座標
- 移動每一個子容器的座標
這裏選擇移動父容器
2.列表內容改變座標的處理可以分爲2種:
- 傳統的top,left座標修改
- CSS3中的transform屬性
3.CSS3引入了一個新的屬性Transform
transform 屬性向元素應用 2D 或 3D 轉換,該屬性允許我們對元素進行旋轉、縮放、移動或傾斜。其中會有一個值translate3d(x,y,z) 是用來控制元素的位置在頁面上的三軸的位置的。
CSS3 Transition的方法就可以實現,這是一個簡單的動畫屬性。
transition可以設置一些具體的參數,比如動畫執行的時間,變化的算法、動畫延時等等,具體大家可以搜索更細緻的資料。
這裏需要特別注意的就是:transform屬性是靜態屬性,不是動畫屬性,一旦寫到style裏面,將會直接顯示作用,無任何變化過程,簡單的一句話描述就是——通過設置transition的一些參數,讓translate3d這個屬性發生變化如何通過translate結合transition改變元素的頁面位置,我們具體看到下面的代碼
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>index</title>
<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
ul,
li {
list-style-type: none;
}
#content {
width: 100%;
height: 100%;
/* top: 20%;
left: 20%; */
overflow: hidden;
position: absolute;
}
.content-wrap {
position: relative;
}
.content-wrap > li {
background: #CAE1FF;
color: red;
float: left;
overflow: hidden;
position: relative;
}
li:nth-child(2) {
background: #9BCD9B;
}
li:nth-child(3) {
background: yellow;
}
button {
width: 100px;
height: 50px;
}
.button {
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div id='content'>
<ul class='content-wrap'>
<!-- 第一副畫面 -->
<li> 頁面1 </li>
<!-- 第二副畫面 -->
<li> 頁面2 </li>
<!-- 第三副畫面 -->
<li> 頁面3 </li>
</ul>
<div class="button">
<button>點擊切換頁面</button>
</div>
</div>
<script type="text/javascript">
var container = $("#content");
// 獲取第一個子節點
var element = container.find(":first");
// li頁面數量
var slides = element.find("li");
// 獲取容器尺寸
var width = container.width();
var height = container.height();
// 設置li頁面總寬度
element.css({
width: (slides.length * width) + 'px',
height: height + 'px'
});
// 設置每一個頁面li的寬度
$.each(slides, function(index) {
var slide = slides.eq(index); // 獲取到每一個li元素
slide.css({ // 設置每一個li的尺寸
width: width + 'px',
height: height + 'px'
});
});
// 綁定一個事件,觸發通過
$('button').click(function() {
// 在5秒的時間內,移動X的位置,爲2個頁面單位
element.css({
'transition-timing-function': 'linear',
'transition-duration': '5000ms',
'transform': 'translate3d(-' + (width * 2) + 'px,0px,0px)' //設置頁面X軸移動
});
});
</script>
</body>
</html>
通過點擊”點擊頁面開始切換”出現頁面切換的效果
4.3 加入小男孩
1.加入小男孩
小孩男走路是貫穿三個主題頁面,因此小男孩在佈局上不能嵌入任何一個頁面內,否則無法切換到下一個頁面中了。所以最終小男孩的佈局與頁面根節點屬於並列結構
CSS設置樣式:
<style type="text/css">
.charector {
width: 151px;
height: 291px;
background: url(http://img1.sycdn.imooc.com/55ade248000198ae10550582.png) -0px -291px no-repeat;
position: absolute;
/* 設置一個元素的座標 */
left: 6%;
top: 55%;
}
</style>
2.添加背景:
設置PageA.css,注意:在CSS文件裏,有時要用到background,即加一個背景圖片,添加的路徑根據圖片及css文件的相對位置分以下兩種類型:
1.同包下:background : url(xxx.jpg);
2.不同包: 在這種情況下有2中方法可以設置,一種是使用絕對路徑,即C:\Users\dellpc\Desktop\Pro\test\images\xxx.jpg,不過一般不推薦這麼用,不利於項目移植;一種是使用相對路徑,首先需要找到圖片文件和css文件共同的一個根目錄,然後再加上圖片的子目錄,比如:
css文件位置:Pro/test/css/style.css
圖片文件位置:Pro/platform/images/xxx.jpg
想要找到共同的根目錄就需要用到 “../” 這個路徑的意思是上一級目錄,如果是兩層上級目錄,就是 “../../” 那麼,按照這種寫法的話,a.css中得背景圖片css應該這麼寫:
background:url(../../platform/images/xxx.jpg )
)
Index.html
<ul class='content-wrap'>
<!-- 第一副畫面 -->
<li>
<div class="a_background">
<div class="a_background_top"></div>
<div class="a_background_middle"></div>
<div class="a_background_botton"></div>
</div>
</li>
<!-- 第二副畫面 -->
<li> 頁面2 </li>
<!-- 第三副畫面 -->
<li> 頁面3 </li>
</ul>
PageA.css
/*背景圖*/
.a_background {
width: 100%;
height: 100%;
position: absolute;
}
.a_background_top{
width: 100%;
height: 71.6%;
background-image: url("../images/background/a_background_top.png");
background-size: 100% 100%;
}
.a_background_middle{
width: 100%;
height: 13.1%;
background-image: url("../images/background/a_background_middle.png");
background-size: 100% 100%;
}
.a_background_botton{
width: 100%;
height: 15.3%;
background-image: url("../images/background/a_background_botton.png");
background-size: 100% 100%;
}
3.小男孩位置矯正
var getValue = function(className) {
var $elem = $('' + className + '');
// 走路的路線座標
return {
height: $elem.height(),
top: $elem.position().top
};
};
// 路的Y軸
var pathY = function() {
var data = getValue('.a_background_middle');
return data.top + data.height / 2;
}();
var $boy = $("#boy");
var boyHeight = $boy.height();
// 修正小男孩的正確位置
// 路的中間位置減去小孩的高度,25是一個修正值
$boy.css({
top: pathY - boyHeight + 25
});
4.小男孩走動
大多數的做法就是把圖片都合成一張大圖再利用CSS的以下屬性:
background-image、background-repeat、background-position組合進行背景定位,background-position可以用數字精確的定位出背景圖片的位置
新增一個class類slowWalk,在這個類中定義一個animation,通過關鍵幀keyframes定義一些規則,就是如何取圖片座標
slowWalk樣式,用於定義一些動畫參數,比如執行的時間、方式、算法、次數等等
@keyframes 規則用於創建動畫。在 @keyframes 中規定某項 CSS 樣式,就能創建由當前樣式逐漸改爲新樣式的動畫效果
右邊代碼區域所示,爲方便理解,解讀一下樣式的slowWalk類定義規則:
定義一個名爲person-slow的@keyframes規則,@keyframes用百分比來規定變化發生的時間, 0% 是動畫的開始,100% 是動畫的完成,規則中有4個百分比值的變化,每個比值分別通過position獲取一張圖片,分別是0%,25%,50%,75%,100%。在950毫米內從0%-100%發生4次變化,採用的算法是steps(1, start)一幀一幀的切換,通過設置infinite參數每950毫秒不斷循環
新增動畫樣式:
.slowWalk {
/* 填入動畫樣式規則 */
/*規定 @keyframes 動畫的名稱。*/
-webkit-animation-name: person-slow;
/*規定動畫完成一個週期所花費的秒或毫秒。默認是 0*/
-webkit-animation-duration: 950ms;
/*規定動畫被播放的次數。默認是 1。 infinite(循環播放)*/
-webkit-animation-iteration-count: infinite;
/*動畫切換的方式是一幀一幀的改變*/
-webkit-animation-timing-function: steps(1, start);
-moz-animation-name: person-slow;
-moz-animation-duration: 950ms;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: steps(1, start)
}
/* 普通慢走 */
@-webkit-keyframes person-slow {
0% {
background-position: -0px -291px;
}
25% {
background-position: -602px -0px;
}
50% {
background-position: -302px -291px;
}
75% {
background-position: -151px -291px;
}
100% {
background-position: -0px -291px;
}
}
@-moz-keyframes person-slow {
0% {
background-position: -0px -291px;
}
25% {
background-position: -602px -0px;
}
50% {
background-position: -302px -291px;
}
75% {
background-position: -151px -291px;
}
100% {
background-position: -0px -291px;
}
}
不要忘了給boy增添一個slowwalk 類。
ps:由於知識的侷限性,這裏只介紹到如何實現人物走動的視覺效果