动画
现在我们知道如何选择和更改DOM元素,我们可以创建一个简单的动画。
让我们创建一个简单的HTML页面,其中包含将使用JS动画的框元素。
<style>
#container {
width: 400px;
height: 400px;
background: green;
position: relative;
}
#box {
width: 30px;
height: 30px;
background: red;
position: absolute;
}
</style>
<div id="container">
<div id="box"> </div>
</div>
尝试一下
我们的box元素在容器元素的内部。注意用于元素的 position 属性:
容器是相对的,盒子是绝对的。这将允许我们创建相对于容器的动画。
我们将动画红色框,使其移动到容器的右侧。
提示: 您需要熟悉CSS才能更好地理解提供的代码。
动画
要创建动画,我们需要以较小的时间间隔更改元素的属性。
我们可以通过使用 setInterval() 方法来实现这一点,它允许我们创建一个定时器并调用一个以定义的间隔(以毫秒为单位)反复更改属性的函数。
例如:
var t = setInterval(move, 500);
此代码创建一个每500毫秒调用一个 move() 函数的计时器。
现在我们需要定义 move() 函数,改变框的位置。
// 定义开始的位置
var pos = 0;
// 获取box元素
var box = document.getElementById("box");
function move() {
pos += 1;
box.style.left = pos+"px"; //px = pixels
}
提示: move() 函数在每次调用时将box元素的left属性增加1。
HTML DOM
通过 HTML DOM,JavaScript 可访问 HTML 文档的所有元素。
HTML DOM (文档对象模型)
当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。
HTML DOM 模型被构造为对象的树:
通过可编程的对象模型,JavaScript 获得了足够的能力来创建动态的 HTML。
- JavaScript 能够改变页面中的所有 HTML 元素
- JavaScript 能够改变页面中的所有 HTML 属性
- JavaScript 能够改变页面中的所有 CSS 样式
- JavaScript 能够对页面中的所有事件做出反应
DOM Tree
DOM 表示文档为树形结构。
HTML 元素成为树中的相关节点。
树中的所有节点之间都有某种关系。
节点可以有子节点。拥有同一父节点的节点称为兄弟节点。
例如,考虑以下结构:
<html>有两个子节点(<head>,<body>);
<head>有一个子节点(<title>)和一个父节点(<html>);
<title>有一个父节点(<head>),没有子节点;
<body>有两个子节点(<h1>和<a>)和一个父节点(<html>);
提示: 了解HTML文档中的元素之间的关系是很重要的,以便能够使用JavaScript来操作它们。
document 对象
document
对象是文档的根节点,window.document
属性就指向这个对象。也就是说,只要浏览器开始载入HTML
文档,这个对象就开始存在了,可以直接调用。
JavaScript中有一个预定义的 document 对象,可用于访问DOM上的所有元素。
换句话说,文档对象是网页中所有对象的所有者(或根)。
因此,如果要访问HTML页面中的对象,则始终访问 document 对象。
例如:
document.body.innerHTML = "Some text";
由于 body 是 DOM 的元素,因此我们可以使用 document 对象访问它并更改 innerHTML 属性的内容。
选择元素
所有HTML元素都是对象。并且我们知道每个对象都有属性和方法。
document 对象具有三种方法最常用于选择HTML元素:
//通过 id 找元素
document.getElementById(id)
//通过 类 找元素
document.getElementsByClassName(name)
//通过 标签 找元素
document.getElementsByTagName(name)
如图所示:
在下面的示例中,getElementById 方法用于选择 id="demo" 的元素并更改其内容:
var elem = document.getElementById("demo");
elem.innerHTML = "Hello World";
选择元素
getElementsByClassName() 方法通过类名查找所有元素,并将其作为数组返回。
例如,如果我们的HTML页面包含三个元素与 class="demo",以下代码将返回所有这些元素作为一个数组:
<div class="demo">
<span class="demo">Hi I'm Loen!</span>
</div>
<p class="demo">This is a paragraph</p>
<script>
var arr = document.getElementsByClassName("demo");
//访问第二个元素
arr[1].innerHTML = "Hi I am Peter";
</script>
尝试一下
类似地,getElementsByTagName 方法返回指定标签名称的所有元素,作为数组返回。
以下示例获取页面的所有段落元素并更改其内容:
<p>hi</p>
<p>hello</p>
<p>hi</p>
<script>
var arr = document.getElementsByTagName("p");
for (var x = 0; x < arr.length; x++) {
arr[x].innerHTML = "Hi there";
}
</script>
尝试一下
脚本将HTML改变成:
<p>Hi there</p>
<p>Hi there</p>
<p>Hi there</p>
提示: 我们通常使用数组的length属性循环遍历上面例子中的所有选择的元素。
使用DOM
DOM中的每个元素都有一组属性和方法,它们提供有关它们在DOM中的关系的信息:
element.childNodes 返回一个元素的子节点的数组。
element.firstChild 返回元素的第一个子节点。
element.lastChild 返回元素的最后一个子节点。
element.hasChildNodes 如果元素有任何子节点,则返回 true,否则为 false 。
element.nextSibling 返回相同树级别的下一个节点。
element.previousSibling 返回在同一树级别的上一个节点。
element.parentNode 返回元素的父节点。
例如,我们可以选择元素的所有子节点并更改其内容:
<html>
<body>
<div id ="demo">
<p>一些文本</p>
<p>另一些文本 </p>
</div>
<script>
var a = document.getElementById("demo");
var arr = a.childNodes;
for(var x=0;x<arr.length;x++) {
arr[x].innerHTML = "新的文本";
}
</script>
</body>
</html>
尝试一下
改变属性
选择要使用的元素后,您可以更改其属性。
正如我们在以前的课程中看到的,我们可以使用 innerHTML 属性更改元素的文本内容。
同样,我们可以改变元素的属性。
例如,我们可以更改图像的 src 属性:
<img id="myimg" src="https://www.w3cschool.cn/attachments/cover/cover_php.jpg" alt="" />
<script>
var el = document.getElementById("myimg"); // 通过id="myimg"获取元素
el.src = "https://www.w3cschool.cn/attachments/cover/cover_html.png";
</script>
尝试一下
我们可以更改链接的href属性:
<a href="http://www.baidu.com">百度</a>
<script>
var el = document.getElementsByTagName("a");
el[0].href = "https://www.w3cschool.cn";
el[0].innerHTML = "W3Cschool";
</script>
尝试一下
提示: 实际上,可以使用JavaScript更改元素的所有属性。
改变样式
HTML元素的样式也可以使用JavaScript进行更改。
可以使用元素的 style 对象来访问所有样式属性。
例如:
<div id="demo" style="width:200px">一些文本</div>
<script>
var x = document.getElementById("demo");
x.style.color = "6600FF";
x.style.width = "100px";
</script>
尝试一下
上面的代码改变了div元素的文本颜色和宽度。
提示: 所有CSS属性都可以使用JavaScript进行设置和修改。请记住,您不能在属性名称中使用破折号( - ):这些替换为驼峰写法,其中复合词以大写字母开头 比如: background-color属性应该被写为 backgroundColor。
添加和移除元素
使用以下方法创建新节点:
element.cloneNode() 克隆元素并返回结果节点。
document.createElement(element) 创建一个新的元素节点。
document.createTextNode(text) 创建一个新的文本节点。
例如:
var node = document.createTextNode("一些新的文本");
这将创建一个新的文本节点,但它将不会出现在文档中,直到您使用以下方法之一将其附加到现有元素:
element.appendChild(newNode) 将一个新的子节点添加到元素作为最后一个子节点。
element.insertBefore(node1, node2) 在节点2之前插入node1作为子节点。
例如:
<div id ="demo">一些文本</div>
<script>
//创建一个新的段落
var p = document.createElement("p");
var node = document.createTextNode("一些新的文本");
//添加文本到段落
p.appendChild(node);
var div = document.getElementById("demo");
//将段落添加到div中
div.appendChild(p);
</script>
移除元素
要删除HTML元素,您必须选择元素的父项并使用 removeChild(node) 方法。
例如:
<div id="demo">
<p id="p1">这是一个段落.</p>
<p id="p2">这是另外一个段落.</p>
</div>
<script>
var parent = document.getElementById("demo");
var child = document.getElementById("p1");
parent.removeChild(child);
</script>
尝试一下
这样会从页面中删除 id ="p1" 的段落。
提示: 实现相同结果的另一种方法是使用 parentNode 属性来获取要删除的元素的父项:
var child = document.getElementById("p1");
child.parentNode.removeChild(child);
替换元素
要替换HTML元素,使用 element.replaceChild(newNode,oldNode) 方法。
例如:
<div id="demo">
<p id="p1">这是一个段落</p>
<p id="p2">这是另一个段落</p>
</div>
<script>
var p = document.createElement("p");
var node = document.createTextNode("这是新的文本");
p.appendChild(node);
var parent = document.getElementById("demo");
var child = document.getElementById("p1");
parent.replaceChild(p, child);
</script>
尝试一下
提示: 上面的代码创建一个替换现有 p1 段落的新段落元素。
javascript事件
Events
事件
JavaScript使我们有能力创建动态页面,网页中的每一个元素都可以产生某些触发JavaScript函数的事件。
我们可以认为事件是可以被JavaScript侦测到的一种行为。
事件流
所谓事件流,也可理解为事件的轨迹。一般地,将事件流分为三个阶段:捕获阶段,目标阶段和冒泡阶段。
完整事件流
您可以编写事件触发执行的Javascript代码,例如用户单击HTML元素,移动鼠标或提交表单时。
当目标元素发生事件时,执行处理函数。
常见的HTML事件包括:
提示: 相应的事件可以添加到HTML元素作为属性。
例如:
<p id="tip">这边显示提示</p>
<h2 id="tip">这边显示提示</h2>
<hr>
<p onclick="clickfn()">点击我看看</p>
<br>
<input type="text" onfocus="focusfn()" onblur="blurfn()" value="获得焦点" />
<br><br>
<div onmouseover="moverfn()" onmouseout="moutfn()" style="">
鼠标移动进来看看
</div>
处理事件
当用户单击指定的按钮时,我们将显示一个提醒弹出窗口:
<button onclick="show()">点击我</button>
<script>
function show() {
alert("你好,我在这里!");
}
</script>
尝试一下
可以给元素绑定事件监听:
var x = document.getElementById("demo");
x.onclick = function () {
document.getElementById("date").innerHTML = new Date();
}
事件
当用户进入或离开页面时,触发 onload 和 onunload 事件。在页面加载后执行操作时,这些操作非常有用。
<body onload="doSomething()">
类似地,window.onload 事件可以用于在整个页面加载之后运行代码。
window.onload = function() {
alert("整个页面已经加载完成");
}
onchange 事件主要用于文本框。当文本框内的文本发生变化并且焦点从元素中丢失时,调用事件处理程序。
例如:
<input type="text" id="name" onchange="change()">
<script>
function change() {
var x = document.getElementById("name");
x.value= x.value.toUpperCase(); // 转成大写
}
</script>
尝试一下
以上程序在用户名发生改变时,将其值转成大写.
事件监听
addEventListener() 方法将事件处理程序附加到元素,而不会覆盖现有的事件处理程序。您可以向一个元素添加许多事件处理程序。
您还可以将许多同一类型的事件处理程序添加到一个元素,即两个“点击”事件。
element.addEventListener(event, function [, useCapture]);
第一个参数是事件的类型(如“click”或“mouseover”)。
第二个参数是事件发生时要调用的函数。
第三个参数是一个布尔值,指定是否使用事件冒泡或事件捕获。此参数是可选的,将在下一课中进行说明。
提示:在添加事件类型的时候没有on, 用的是 click 而不是 onclick
element.addEventListener("click", myFunction);
element.addEventListener("mouseover", myFunction);
function myFunction() {
alert("Hello W3Cschool");
}
删除事件监听
我们可以使用 removeEventListener 删除事件监听:
element.removeEventListener("mouseover", myFunction);
我们创建一个事件处理程序,在执行后会自动删除:
<button id="demo">开始</button>
<script>
var btn = document.getElementById("demo");
btn.addEventListener("click", myFunction);
function myFunction() {
alert(Math.random());
btn.removeEventListener("click", myFunction);
}
</script>
尝试一下
单击按钮后,将显示带有随机数的警报,并删除事件监听器。
提示: Internet Explorer版本8及更低版本不支持 addEventListener() 和 removeEventListener() 方法。但是,您可以使用 document.attachEvent() 方法在Internet Explorer中附加事件处理程序。
图像幻灯片
现在我们可以创建一个示例图像幻灯片项目。将使用“下一个”和“上一个”按钮更改图像。
现在,我们来创建我们的HTML,其中包括一个图像和两个导航按钮:
<div>
<button> 上一个 </button>
<img id="slider" src="https://www.w3cschool.cn/statics/images/logo.png" />
<button> 下一个 </button>
</div>
尝试一下
接下来,让我们在数组中定义我们的示例图像:
var images = [
"https://www.w3cschool.cn/statics/images/1.png",
"https://www.w3cschool.cn/statics/images/2.png,
"https://www.w3cschool.cn/statics/images/3.png"
];
提示: 我们将使用我们上传到我们的服务器的三个示例图像。您可以使用任意数量的图像。
图像幻灯片
现在我们需要处理 "上一个" 和 "下一个" 按钮点击并调用相应的功能来更改图像。
HTML:
<div>
<button onclick="prev()"> 上一个 </button>
<img id="slider" src="https://www.w3cschool.cn/statics/images/1.png" />
<button onclick="next()"> 下一个 </button>
</div>
JS:
var images = [
"https://www.w3cschool.cn/statics/images/1.png",
"https://www.w3cschool.cn/statics/images/2.png,
"https://www.w3cschool.cn/statics/images/3.png"
];
var num = 0;
function next() {
var slider = document.getElementById("slider");
num++;
if(num >= images.length) {
num = 0;
}
slider.src = images[num];
}
function prev() {
var slider = document.getElementById("slider");
num--;
if(num < 0) {
num = images.length-1;
}
slider.src = images[num];
}
提示: num 变量保存当前图像。下一个和上一个按钮点击由他们相应的功能来处理,这些功能会将图像的源更改为数组中的下一个/上一个图像。
表格验证
HTML5添加了一些允许表单验证的属性。例如,require 属性可以添加到输入字段,以使其强制填写。
更复杂的表单验证可以使用JavaScript来完成。
表单元素具有可以处理以执行验证的 onsubmit 事件。
例如,我们创建一个带有两个输入框和一个按钮的窗体。两个字段中的文本应该相同,不能为空,才可通过验证。
<form onsubmit="return validate()" method="post">
Number: <input type="text" name="num1" id="num1" />
<br />
Repeat: <input type="text" name="num2" id="num2" />
<br />
<input type="submit" value="Submit" />
</form>
现在我们需要定义 validate() 函数:
function validate() {
var n1 = document.getElementById("num1");
var n2 = document.getElementById("num2");
if(n1.value != "" && n2.value != "") {
if(n1.value == n2.value) {
return true;
}
}
alert("输入两个值不相等,请重新输入!");
return false;
}
只有当值不为空且相等时才返回 true 。
提示: 如果其 onsubmit 事件返回 false,表单将不会被提交。
综合运用开发老虎机游戏
任务
现在把我们之前的所学的知识点结合起来完成一个老虎机游戏。
1. 首先我们生成3个随机数,范围在1到3之间。
分别用变量 slotOne
、slotTwo
、slotThree
来存储着3个随机数。
提示: 你可能要用到 Math.floor()和Math.random() 方法。
2. 创建一个 if 语句, 当 slotOne
、slotTwo
、slotThree
的值都相等的时候, 把 "恭喜你赢了!" 追加到 class 为 logger 的html中,并return slotOne; 。
3. 分别更新每个老虎机上的HTML为对应的数字(老虎机的 class 为 slot)。
4. 设置所有的老虎机根据随机数来显示对应的图片, 最后点击 run。
1、首先我们生成3个随机数,范围在1到3之间。分别用 slotOne
、slotTwo
、slotThree
来存储着3个随机数。
Math.floor(Math.random() * (3 - 1 + 1)) + 1;
2、
现在我们的老虎机每次生成3个随机数,我们得去检查随机数是否全部相等的情况。
如果全部相等,我们应该提示用户他们赢了,并返回中奖号码,否则我们应该返回null。
当这3个随机数相等的时候,判定用户赢。创建一个if条件语句
,用多个条件按顺序来检查它们是否相等。类似于:
if (slotOne === slotTwo && slotTwo === slotThree){
return slotOne;
} else {
}
当3个随机数都一样的时候,我们把 "It's A Win"
追加到class logger
的html中。
3、用 jQuery 选择器 $(".slot")
获得所有老虎机。
一旦获取到所有老虎机,我们可以通过中括号操作符获取到每一个老虎机:
$($(".slot")[0]).html(slotOne);
jQuery将会获取到第一个老虎机,并更新它的HTML为正确的数字。
4、给老虎机加图片。可以通过不同的索引来获取每个图片。
$($('.slot')[0]).html('<img src = "' + images[slotOne-1] + '">');
<script>
var slotOne;
var slotTwo;
var slotThree;
function runSlots() {
var images = ["https://www.w3cschool.cn/statics/codecamp/images/9H17QFk.png", "https://www.w3cschool.cn/statics/codecamp/images/9RmpXTy.png", "https://www.w3cschool.cn/statics/codecamp/images/VJnmtt5.png"];
// 在这行的下面添加代码
$($('.slot')[0]).html('<img src = "' + images[slotOne-1] + '">');
$($('.slot')[1]).html('<img src = "' + images[slotTwo-1] + '">');
$($('.slot')[2]).html('<img src = "' + images[slotThree-1] + '">');
slotOne=Math.floor(Math.random()*(3-1+1))+1;
slotTwo=Math.floor(Math.random()*(3-1+1))+1;
slotThree=Math.floor(Math.random()*(3-1+1))+1;
if(slotOne==slotTwo && slotTwo==slotThree){
$('.logger').html("It's A Win");
return null;
}
// 在这行的上面添加代码
var logger = document.getElementsByClassName("logger")[0];
if (slotOne !== undefined && slotTwo !== undefined && slotThree !== undefined){
logger.innerHTML = slotOne + " " + slotTwo + " " + slotThree;
}
logger.innerHTML += ' Not A Win';
return [slotOne, slotTwo, slotThree];
}
$(document).ready(function() {
$('.go').click(function() {
runSlots();
});
});
</script>
<div>
<div class = 'container inset'>
<div class = 'header inset'>
<img src='/statics/codecamp/images/freecodecamp_logo.svg' alt='learn to code JavaScript at Free Code Camp logo' class='img-responsive nav-logo'>
<h2>FCC Slot Machine</h2>
</div>
<div class = 'slots inset'>
<div class = 'slot inset'>
</div>
<div class = 'slot inset'>
</div>
<div class = 'slot inset'>
</div>
</div>
<br/>
<div class = 'outset'>
<button class = 'go inset'>
Go
</button>
</div>
<br/>
<div class = 'foot inset'>
<span class = 'logger'></span>
</div>
</div>
</div>
<style>
.slot > img {
margin: 0!important;
height: 71px;
width: 50px;
}
.container {
background-color: #4a2b0f;
height: 400px;
width: 300px;
margin: 30px auto;
border-radius: 4px;
}
.header {
border: 2px solid #fff;
border-radius: 4px;
height: 55px;
margin: 14px auto;
background-color: #457f86
}
.header h2 {
height: 30px;
margin: auto;
}
.header h2 {
font-size: 14px;
margin: 0 0;
padding: 0;
color: #fff;
text-align: center;
}
.slots{
display: flex;
background-color: #457f86;
border-radius: 6px;
border: 2px solid #fff;
}
.slot{
flex: 1 0 auto;
background: white;
height: 75px;
width: 50px;
margin: 8px;
border: 2px solid #215f1e;
border-radius: 4px;
text-align: center;
}
.go {
width: 100%;
color: #fff;
background-color: #457f86;
border: 2px solid #fff;
border-radius: 2px;
box-sizing: none;
outline: none!important;
}
.foot {
height: 150px;
background-color: 457f86;
border: 2px solid #fff;
}
.logger {
color: white;
margin: 10px;
}
.outset {
-webkit-box-shadow: 0px 0px 15px -2px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 15px -2px rgba(0,0,0,0.75);
box-shadow: 0px 0px 15px -2px rgba(0,0,0,0.75);
}
.inset {
-webkit-box-shadow: inset 0px 0px 15px -2px rgba(0,0,0,0.75);
-moz-box-shadow: inset 0px 0px 15px -2px rgba(0,0,0,0.75);
box-shadow: inset 0px 0px 15px -2px rgba(0,0,0,0.75);
}
</style>
https://www.w3cschool.cn/minicourse/play/jscourse?cp=172&gid=0