面型对象编程——放大镜
HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
width: 980px;
margin: 0 auto;
}
ul {
list-style: none;
}
.fdj {
width: 400px;
position: relative;
}
.fdj1 {
width: 200px;
position: relative;
}
</style>
</head>
<body>
<div class="content">
<div class="container">
<div class="fdj"></div>
</div>
<div class="container">
<div class="fdj1"></div>
</div>
</div>
<script src="../js/glass.js"></script>
<script>
// 获取元素
let fdj = document.querySelector(".fdj");
let fdj1 = document.querySelector(".fdj1");
// 图片地址数组
let imgArr = [
{
iconPath: "../images/icon01.jpg",
smallImgPath: "../images/small01.jpg",
bigImgPath: "../images/big01.jpg"
},
{
iconPath: "../images/icon02.jpg",
smallImgPath: "../images/small02.jpg",
bigImgPath: "../images/big02.jpg"
},
{
iconPath: "../images/icon03.jpg",
smallImgPath: "../images/small03.jpg",
bigImgPath: "../images/big03.jpg"
},
]
// 创建实例对象
let z = new Zoom(fdj, imgArr);
z.render();
z.addStyle();
z.addEvevt();
let z1 = new Zoom(fdj1, imgArr);
z1.render();
z1.addStyle();
z1.addEvevt();
</script>
</body>
</html>
glass.js文件
let Zoom = (function(){
function offset(dom){
// 定义两个变量
var left = 0;
var top = 0;
// 计算自身元素左边框外到定位父元素的左边框内
var left = dom.offsetLeft;
var top = dom.offsetTop;
// 判断浏览器是否是IE8
var isIE8 = false;
if(window.navigator.userAgent.indexOf("MSIE 8") != -1){
isIE8 = true;
}
// 让自己指向上一层
dom = dom.offsetParent;
// 因为dom没有直接获取到页面的属性所以只能一层一层的往上找
while(dom != document.body){
// 如果是浏览器IE8,不需要加上clientLeft、clientTop
if(isIE8){
// 累加每一层的offsetLeft
left += dom.offsetLeft;
// 累加每一层的offsetTop
top += dom.offsetTop;
}else{
// 累加每一层的offsetLeft、clientLeft
left += dom.offsetLeft + dom.clientLeft;
// 累加每一层的offsetTop、clientTop
top += dom.offsetTop + dom.clientTop;
}
// 让dom指向上一层
dom = dom.offsetParent;
}
// 返回left、top
return{
left: left,
top: top
}
}
// 参数一表示外层大容器,参数二表示图片的地址
function Zoom(container, imgArr) {
// 容器属性
this.container = container;
// 图片地址数组属性
this.imgArr = imgArr;
// 创建小图图片
this.smallImage = document.createElement("img");
// 创建大图图片
this.bigImage = document.createElement("img");
// 创建图片列表
this.ul = document.createElement("ul");
// 创建镜片
this.glass = document.createElement("div");
// 定义图片容器列表
this.lis = [];
// 定义一个缩放比例
this.r = 0.5;
}
// 在原型里面添加属性,要保证原型里面原来的constructor还存在原型里面
Zoom.prototype = {
construtor: Zoom,
// 渲染结构
render(){
// 创建小图容器
let smallContainer = document.createElement("div");
// 设置小图图片
this.smallImage.src = this.imgArr[0].smallImgPath;
// 创建大图容器
let bigContainer = document.createElement("div");
// 设置大图图片
this.bigImage.src = this.imgArr[0].bigImgPath;
// 追加小图片、大图片
smallContainer.appendChild(this.smallImage);
bigContainer.appendChild(this.bigImage);
// 将小图容器、大图容器、图片列表容器追加到主容器中
this.container.appendChild(smallContainer);
this.container.appendChild(bigContainer);
this.container.appendChild(this.ul);
// 追加放大镜
smallContainer.appendChild(this.glass);
// 根据传递的图片地址数组,创建ul的li元素
this.imgArr.forEach((value) => {
// 创建li元素
let li = document.createElement("li");
// 创建img元素
let img = document.createElement("img");
// 设置img的src
img.src = value.iconPath;
// 将img追加到li
li.appendChild(img);
this.lis.push(li);
// 将li追加到ul
this.ul.appendChild(li);
});
},
// 添加样式
addStyle(){
// 获取小图容器元素
let smallContainer = this.smallImage.parentNode;
// 准备小图容器样式
let smallStyle = {
width: "100%",
height: smallContainer.clientWidth + "px"
}
// 设置小图容器样式
for (let i in smallStyle){
smallContainer.style[i] = smallStyle[i];
}
// 准备小图图片样式
let smallImgStyle = {
width: "100%",
height: "100%"
}
// 设置小图图片样式
for (let i in smallImgStyle){
this.smallImage.style[i] = smallImgStyle[i];
}
// 获取大图容器元素
let bigContainer = this.bigImage.parentNode;
// 准备大图容器样式
let bigStyle = {
width: smallContainer.clientWidth * 1.50 + "px",
height: smallContainer.clientWidth * 1.50 + "px",
position: "absolute",
overflow: "hidden",
left: "110%",
top: 0,
display: "none"
}
// 设置大图容器样式
for (let i in bigStyle){
bigContainer.style[i] = bigStyle[i];
}
// 准备大图图片样式
let bigImgStyle = {
position: "absolute",
top: "0",
left: "0",
width: smallContainer.clientWidth * 1.50 / this.r + "px",
height: smallContainer.clientWidth * 1.50 / this.r + "px"
}
// 设置大图图片样式
for (let i in bigImgStyle){
this.bigImage.style[i] = bigImgStyle[i];
}
// 准备放大镜样式
let glassStyle = {
position: "absolute",
top: 0,
left: 0,
backgroundColor: "rgba(0, 0, 0, 0.4)",
width: smallContainer.clientWidth * this.r + "px",
height: smallContainer.clientWidth * this.r + "px",
display: "none",
cursor: "pointer"
}
// 设置放大镜样式
for (let i in glassStyle){
this.glass.style[i] = glassStyle[i];
}
// 准备图片列表样式
let ulStyle = {
display: "flex",
justifyContent: "space-around",
padding: '10px 0',
cursor: "pointer"
}
// 设置图片列表样式
for (let i in ulStyle){
this.ul.style[i] = ulStyle[i];
}
// 设置ul中li被选中状态样式
this.lis.forEach((value) => {
value.style.border = "2px solid transparent";
})
},
// 添加事件
addEvevt() {
// 遍历图片列表
this.lis.forEach((value, index) => {
// 添加鼠标进入图片列表每个li的事件
value.addEventListener("mouseenter", () => {
// 改变小图图片
this.smallImage.src = this.imgArr[index].smallImgPath;
// 改变大图图片
this.bigImage.src = this.imgArr[index].bigImgPath;
// 节流,清除图片列表里面每一个li的边框样式
this.lis.forEach((value) => {
value.style.borderColor = "transparent";
})
// 设置选中的li边框颜色
value.style.borderColor = "red";
})
})
// 获取小图容器元素
let smallContainer = this.smallImage.parentNode;
// 鼠标进入事件,显示放大镜和大图容器
smallContainer.addEventListener("mouseenter", () => {
this.glass.style.display = "block";
this.bigImage.parentNode.style.display = "block";
})
// 鼠标离开事件,隐藏放大镜和大图容器
smallContainer.addEventListener("mouseleave", () => {
this.glass.style.display = "none";
this.bigImage.parentNode.style.display = "none";
})
// 添加拖拽事件(鼠标移动事件)
smallContainer.addEventListener("mousemove", (e) => {
// 浏览器兼容处理
let event = e || window.event;
// 获取鼠标到页面的距离
let pageX = event.pageX;
let pageY = event.pageY;
// 获取元素到页面的距离
let obj = offset(this.container);
let x = obj.left;
let y = obj.top;
// 计算放大镜glass的一半宽高
let halfX = this.glass.clientWidth / 2;
let halfY = this.glass.clientHeight / 2;
// 计算放大镜移动后的位置
let glassLeft = pageX - x - halfX;
let glassTop = pageY - y - halfY;
// 边界值判定
if (glassLeft < 0){
glassLeft = 0;
} else if(glassLeft > this.smallImage.clientWidth - this.glass.clientWidth){
glassLeft = this.smallImage.clientWidth - this.glass.clientWidth;
}
if (glassTop < 0){
glassTop = 0;
} else if(glassTop > this.smallImage.clientHeight - this.glass.clientHeight){
glassTop = this.smallImage.clientHeight - this.glass.clientHeight;
}
// 设置放大镜glass位置
this.glass.style.left = glassLeft + "px";
this.glass.style.top = glassTop + "px";
// 设置大图图像随着放大镜移动
let r = (this.smallImage.clientWidth * this.r / (this.bigImage.width - this.bigImage.parentNode.clientWidth));
this.bigImage.style.left = -glassLeft / r + "px";
this.bigImage.style.top = -glassTop / r + "px";
})
}
}
return Zoom;
})();
面向对象编程——轮播图
HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.carousel {
width: 600px;
height: 400px;
margin: 0 auto;
overflow: hidden;
position: relative;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="carousel"></div>
<script src="../js/Banner.js"></script>
<script>
let carousel = document.querySelector(".carousel");
let b = new Banner(carousel, [
"../images/1.jpeg",
"../images/2.jpeg",
"../images/3.jpeg",
"../images/4.jpeg",
"../images/5.jpeg",
"../images/6.jpeg"]);
</script>
</body>
</html>
Banner.js文件
let Banner = (function(){
// 封装运动函数,参数一表示元素,参数二表示一个对象(对象里面可以设置多个属性),参数三表示运动时间,参数四表示回调函数
function animate(ele, endObj, duration, callback) {
// 规定运动频率
let interval = 20;
// 运动次数 = 运动时间 / 运动频率
let stepCount = duration / interval;
// 获取元素起点位置
let startObj = {};
// 通过循环参数二对象里面的属性,获取元素开始时与参数二对象里面的属性的初始值
for (let i in endObj) {
// 将获取到的初始值放到一个startObj对象
// 因为使用getComputedStyle获取到的计算后样式,返回值是一个带有px的字符串,所以需要将其转为一个数值型
startObj[i] = parseInt(getComputedStyle(ele)[i]);
}
// 定义一个变量,用于计算运动了几次
let count = 0;
// 开启定时器
let timer = setInterval(() => {
// 每运动一次,count加1
count++;
// 通过循环改变元素的属性
for (let i in endObj) {
// 开始位置(或者说是开始属性) + (最终位置(或者说是最终属性) - 开始位置(或者说是开始属性)) / 运动总次数 * 当前运动的第几次
let result = startObj[i] + (endObj[i] - startObj[i]) / stepCount * count;
// 假设参数endObj里面函数有一个透明的属性opacity,需要进行判断,因为opacity没有单位px
ele.style[i] = (i.toLowerCase() === "opacity") ? result : (result + "px");
}
// 判断何时运动结束
if (count >= stepCount) {
clearInterval(timer);
// 回调函数
callback && callback();
// 上行代码等价于
// if(callback){callback()}
}
}, interval);
}
function Banner(container, imageArr, interval = 1000, waitInterval = interval * 2) {
this.container = container;
this.imageArr = imageArr;
this.interval = interval;
this.waitInterval = waitInterval;
// 图片容器ul属性
this.imgUL = document.createElement("ul");
// 左右按钮容器属性
this.btnContainer = document.createElement("div");
// 左按钮属性
this.leftBtn = document.createElement("span");
// 右按钮属性
this.rightBtn = document.createElement("span");
// 小圆点按钮容器ul属性
this.cirUL = document.createElement("ul");
// 定义数组,用于承载图片的li
this.liArr = [];
// 定义数组。用于承载图片
this.imgArr = [];
// 定义数组,用于承载小圆点按钮的li
this.cirArr = [];
// 定义定时器
this.timer = null;
// 定义锁
this.lock = true;
// 定义信号量
this.idx = 0;
this.init();
}
Banner.prototype = {
constructor: Banner,
// 初始化
init() {
this.create();
this.addStyle();
this.upTree();
this.bindEvent();
},
// 创建元素
create() {
this.createImageList();
this.createLeftBtn();
this.createRightBtn();
this.createCirList();
},
// 创建图片列表
createImageList() {
// 根据图片地址数组,循环创建每一个li元素
this.imageArr.forEach((value) => {
// 创建li
let li = document.createElement("li");
// 创建完li,载入数组
this.liArr.push(li);
// 创建图片
let img = new Image();
// 创建完图片,载入数组
this.imgArr.push(img);
// 设置路径
img.src = value;
// 让img成为li的子元素
li.appendChild(img);
// 让li成为ul的子元素
this.imgUL.appendChild(li);
})
// 创建猫腻图
let li = this.liArr[0].cloneNode(true);
// 将猫腻图加入liArr数组
this.liArr.push(li);
// 将猫腻图加入imgArr数组
this.imgArr.push(li.childNodes[0]);
// 将猫腻图追加到ul最后
this.imgUL.appendChild(li);
},
// 创建左按钮
createLeftBtn() {
this.btnContainer.appendChild(this.leftBtn);
},
// 创建右按钮
createRightBtn() {
this.btnContainer.appendChild(this.rightBtn);
},
// 创建小圆点
createCirList() {
this.imageArr.forEach(function () {
// 创建li
let li = document.createElement("li");
// 创建完li,载入数组
this.cirArr.push(li);
// 让li成为cirUL的子元素
this.cirUL.appendChild(li);
}.bind(this));
},
// 渲染方法
addStyle() {
this.addImageListStyle();
this.addBtnStyle();
this.addCirStyle();
},
// 添加图片列表样式
addImageListStyle() {
// 设置ul样式
this.imgUL.style.width = this.container.clientWidth * this.liArr.length + "px";
this.imgUL.style.height = this.container.clientHeight + "px";
this.imgUL.style.listStyle = "none";
this.imgUL.style.position = "absolute";
// 获取li,添加样式
this.liArr.forEach((value) => {
value.style.width = this.container.clientWidth + "px";
value.style.height = this.container.clientHeight + "px";
value.style.float = "left";
})
// 设置img样式
this.imgArr.forEach((value) => {
value.style.width = "100%";
value.style.height = "100%";
})
},
// 添加左右按钮容器样式
addBtnStyle() {
let conStyle = {
width: "100%",
height: this.container.clientHeight * 0.3 + "px",
position: "absolute",
top: "35%",
display: "flex",
justifyContent: "space-between"
}
for (let i in conStyle) {
this.btnContainer.style[i] = conStyle[i];
}
let btnStyle = {
display: 'block',
width: this.container.clientWidth * 0.15 + "px",
height: "100%",
textAlign: "center",
color: "white",
lineHeight: this.container.clientHeight * 0.3 + "px",
cursor: "pointer",
fontSize: this.container.clientHeight * 0.1 + "px",
backgroundColor: "rgba(0, 0, 0, 0.3)"
}
// 添加左右按钮样式
for (var i in btnStyle) {
this.leftBtn.style[i] = btnStyle[i];
this.rightBtn.style[i] = btnStyle[i];
}
this.leftBtn.innerHTML = "<";
this.rightBtn.innerHTML = ">";
},
// 添加小圆点按钮容器样式
addCirStyle() {
let conStyle = {
position: "absolute",
height: this.container.clientHeight * 0.15 + "px",
width: this.container.clientWidth * 0.5 + "px",
right: 0,
bottom: 0,
listStyle: "none",
display: "flex",
justifyContent: "space-around",
alignItems: "center"
}
for (let i in conStyle) {
this.cirUL.style[i] = conStyle[i];
}
// 添加小圆点按钮样式
let cirStyle = {
width: this.container.clientWidth * 0.04 + "px",
height: this.container.clientWidth * 0.04 + "px",
backgroundColor: "white",
borderRadius: "50%",
cursor: "pointer"
}
this.cirArr.forEach((value) => {
for (let i in cirStyle) {
value.style[i] = cirStyle[i];
}
})
// 默认为第一个小圆点添加样式
this.cirArr[0].style.backgroundColor = "red";
},
// 上树
upTree() {
this.container.appendChild(this.imgUL);
this.container.appendChild(this.btnContainer);
this.container.appendChild(this.cirUL);
},
// 绑定事件
bindEvent() {
this.bindLeftBtn();
this.bindRightBtn();
this.bindCirBtn();
this.bindAutoLoop();
this.bindMouseEnter();
this.bindMouseLeave();
},
// 绑定左按钮事件
bindLeftBtn() {
this.leftBtn.addEventListener("click", () => {
// 判断锁状态
if (!this.lock) {
return;
}
// 如果处于开锁状态,下面的代码将会被执行,动画结束前多次点击无效
this.lock = false;
// 点击一次信号量减1
this.idx--;
// 判断是否是第一张图片
if (this.idx < 0) {
// 因为小圆点的个数比图片的数量少1
this.idx = this.liArr.length - 1;
this.imgUL.style.left = -this.idx * this.container.clientWidth + "px";
this.idx--;
}
animate(this.imgUL, { left: -this.idx * this.container.clientWidth }, this.interval, () => {
// 开锁
this.lock = true;
});
// 添加小圆点样式
this.changeCirBtnStyle();
})
},
// 绑定右按钮事件
bindRightBtn() {
this.rightBtn.onclick = () => {
// 判断锁状态
if (!this.lock) {
return;
}
// 如果处于开锁状态,下面的代码将会被执行,动画结束前多次点击无效
this.lock = false;
// 点击一次信号量加1
this.idx++;
animate(this.imgUL, {left: -this.idx * this.container.clientWidth}, this.interval, () => {
// 判断是否是最后一张图
if(this.idx >= this.liArr.length - 1){
// 将图片列表位置归零
this.imgUL.style.left = 0;
// 将信号量归零
this.idx = 0;
}
// 开锁
this.lock = true;
});
// 添加小圆点样式
this.changeCirBtnStyle();
}
},
// 绑定小圆点按钮事件
bindCirBtn() {
this.cirArr.forEach((value, index) => {
// 为每一个小圆点添加点击事件
value.addEventListener("click", () => {
// 判断锁状态
if (!this.lock) {
return;
}
// 如果处于开锁状态,下面的代码将会被执行,动画结束前多次点击无效
this.lock = false;
// 切换图片
this.idx = index;
animate(this.imgUL, {left: -this.idx * this.container.clientWidth}, this.interval, () => {
// 开锁
this.lock = true;
})
// 添加小圆点样式
this.changeCirBtnStyle();
})
})
},
// 设置小圆点样式
changeCirBtnStyle(){
this.cirArr.forEach((value, index) => {
value.style.backgroundColor = index === this.idx ? "red" : "white";
})
if (this.idx >= this.liArr.length - 1) {
this.cirArr[0].style.backgroundColor = "red";
}
},
// 绑定自动轮播事件
bindAutoLoop() {
this.timer = setInterval(() => {
this.rightBtn.onclick();
}, this.waitInterval)
},
// 绑定鼠标进入事件
bindMouseEnter() {
this.container.addEventListener("mouseenter", () => {
clearInterval(this.timer);
})
},
// 绑定鼠标移出事件
bindMouseLeave() {
this.container.addEventListener("mouseleave", () => {
this.bindAutoLoop();
})
}
}
return Banner;
})();
面向对象编程——弹幕
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
.container{
width: 800px;
height: 600px;
margin: 0 auto;
}
.videoArea{
width: 100%;
height: 550px;
position: relative;
background: #000;
overflow: hidden;
}
.inputArea{
width: 100%;
height: 50px;
display: flex;
}
.inp{
flex: 8;
outline: none;
}
.sendMsg{
flex: 2;
cursor: pointer;
outline: none;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="videoArea" id="videoArea">
</div>
<div class="inputArea" id="inputArea">
<input type="text" name="inp" id="inp" class="inp" placeholder="请文注意文明用语">
<button class="sendMsg" id="sendMsg">发送</button>
</div>
</div>
<script>
// 获取元素
let videoArea = document.getElementById("videoArea");
let inp = document.getElementById("inp");
let sendMsg = document.getElementById("sendMsg");
// 定义一个数组用于存放弹幕
let arr = [];
// 点击发送按钮事件
sendMsg.addEventListener("click", () => {
// 获取弹幕内容
let val = inp.value;
// 判断获取到的弹幕内容是否为空
if(val === ""){
alert("弹幕内容不能为空!");
return;
}
// 屏蔽敏感词
let reg = /(色)|(杀)|(打)|(毒)|(赌)|(抢)|(操)/g;
// 提示用户注意言语
if(reg.test(val)){
alert("请注意您的言语!");
}
// 将敏感词替换
val = val.replace(reg, "*");
// 生成一个弹幕对象
arr.push(new Message(videoArea, val));
// 清空输入框内容
inp.value = "";
})
// 定义Message类
function Message(container, text){
this.container = container;
this.text = text;
// 创建元素
this.ele = document.createElement("div");
// 设置随机速度
this.speed = parseInt(Math.random() * 5) + 2;
// 备份速度,用于在弹幕被鼠标移入停止,鼠标离开后能够保持原来的速度移动
this.copySpeed = this.speed;
this.init();
}
Message.prototype = {
consturctor: Message,
init(){
this.create();
this.upTree();
this.addStyle();
this.bindEvent();
},
// 创建元素
create(){
// 创建弹幕元素
this.message = document.createElement("span");
// 添加弹幕内容
this.message.innerText = this.text;
// 追加
this.ele.appendChild(this.message);
},
// 上树
upTree(){
this.container.appendChild(this.ele);
},
// 添加样式
addStyle(){
// 准备弹幕容器样式
let eleStyle = {
position: "absolute",
left: "100%",
top: Math.random()*this.container.clientHeight + "px",
width: this.container.clientWidth + "px"
}
// 设置容器样式
for (let i in eleStyle){
this.ele.style[i] = eleStyle[i];
}
// 准备弹幕内容样式
let msgStyle = {
display: 'inline-block',
left: "100%",
height: "16px",
lineHeight: "16px",
fontSize: "14px",
color: `rgb(${Math.random()*255},${Math.random()*255},${Math.random()*255})`
}
// 设置弹幕内容样式
for (var i in msgStyle) {
this.message.style[i] = msgStyle[i]
}
},
// 运动
move() {
this.ele.style.left = this.ele.offsetLeft - this.speed + "px";
},
// 将元素删除
unload() {
this.ele.remove();
},
// 当鼠标进入元素时 要让当前这个停下 1 停止定时器 我们操作到了类之外的内容 而且一旦定时器停止 所有的弹幕都停了
// 2 仅仅把当前弹幕停止 把速度变为0即可
bindEvent() {
// 鼠标进入事件
this.ele.onmouseenter = () => {
// 鼠标移到哪条弹幕上面,就将哪条弹幕停止运动,为了防止鼠标进入某一条弹幕上后,后面的某一条弹幕经过鼠标箭头时,导致原来暂停的弹幕继续运动,后来的弹幕停止的现象,所以需要将弹幕的层级提升
this.ele.style.zIndex = 100;
// 将弹幕的速度设为0
this.speed = 0;
}
// 鼠标离开事件
this.ele.onmouseleave = () => {
// 鼠标离开后,将层级设为原来的1
this.ele.style.zIndex = 1;
// 恢复原来的移动速度
this.speed = this.copySpeed;
}
}
}
// 设置定时器
setInterval(function() {
// 遍历数组
arr.forEach((value, index) => {
// 让数组里面的每一条弹幕运动
value.move();
// 当弹幕全部离开后,将其删除
if (value.ele.offsetLeft < -value.ele.offsetWidth) {
value.unload();
arr.splice(index, 1);
}
})
}, 30)
</script>
</body>
</html>
面向对象编程——随机点名系统
HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
background-color: #444;
}
h1{
text-align: center;
margin: 50px auto;
}
.box{
width: 1000px;
height: auto;
margin: 0 auto;
}
</style>
</head>
<body>
<h1>随机点名系统</h1>
<div class="box" id="box"></div>
<script src="../js/Roll.js"></script>
<script>
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let box = document.getElementById("box");
let roll = new Roll(box, arr, 200, 20);
</script>
</body>
</html>
Roll.js文件
let Roll = (function(){
// 参数一表示主容器,参数二表示数组,参数三表示定时器间隔时间(默认是100毫秒),参数四是多选次数(默认是10),多选指的是随机选择多次后停止
function Roll(container, arr, duration = 100, count = 10){
// 容器
this.container = container;
// 数组
this.arr = arr;
// 定时器间隔时间
this.duration = duration;
// 多选次数
this.count = count;
// 被选中名字容器
this.box1 = document.createElement("div");
// 所有名字容器
this.box2 = document.createElement("div");
// 按钮容器
this.box3 = document.createElement("div");
// h2
this.clickedH2 = document.createElement("h2");
// 显示选中名字span
this.clickedSpan = document.createElement("span");
// 单选按钮
this.btn1 = document.createElement("button");
// 多选按钮
this.btn2 = document.createElement("button");
// 所有数组成员
this.nameArr = [];
this.init();
}
Roll.prototype = {
constructor: Roll,
init(){
this.upTree();
this.addStyle();
this.bindEvent();
},
// 元素上树
upTree(){
this.upClickName();
this.upAllName();
this.upBtnBox();
},
upClickName(){
this.clickedH2.innerText = "恭喜选中:"
// clickedSpan追加到clickedH2中
this.clickedH2.appendChild(this.clickedSpan);
// clickedH2追加到box1中
this.box1.appendChild(this.clickedH2);
// box1追加到container中
this.container.appendChild(this.box1);
},
upAllName(){
// 遍历数组
this.arr.forEach((value) => {
let nameSpan = document.createElement("span");
nameSpan.innerText = value;
this.nameArr.push(nameSpan);
// nameSpan追加到box2中
this.box2.appendChild(nameSpan);
// box2追加到container中
this.container.appendChild(this.box2);
})
},
upBtnBox(){
this.btn1.innerText = "单选";
this.btn2.innerText = "多选";
// btn1、btn2追加到box3中
this.box3.appendChild(this.btn1);
this.box3.appendChild(this.btn2);
// box3追加到container中
this.container.appendChild(this.box3);
},
// 添加样式
addStyle(){
this.addBoxStyle1();
this.addBoxStyle2();
this.addBoxStyle3();
},
// box1样式
addBoxStyle1(){
// 准备box1样式
let box1Style = {
width: this.container.clientWidth + "px",
height: "auto",
margin: "10px 0",
padding: "10px 0",
borderWidth: "2px",
borderStyle: "solid",
borderColor: "#CCC",
display: "flex",
justifyContent: "center",
alignItems: "center"
}
// 设置box1样式
for (let i in box1Style){
this.box1.style[i] = box1Style[i];
}
// 准备clickedSpan样式
let spanStyle = {
color: "red"
}
// 设置clickedSpan样式
for (let i in spanStyle){
this.clickedSpan.style[i] = spanStyle[i];
}
},
// box2样式
addBoxStyle2(){
// 准备box2样式
let box2Style = {
width: this.container.clientWidth + "px",
height: "auto",
margin: "10px 0",
borderWidth: "2px",
borderStyle: "solid",
borderColor: "#CCC",
display: "flex",
justifyContent: "center",
flexWrap: "wrap"
}
// 设置box2样式
for (let i in box2Style){
this.box2.style[i] = box2Style[i];
}
// 准备box2子元素样式
let nameStyle = {
display: "inline-block",
justifyContent: "space-between",
width: (this.container.clientWidth / 10) + "px",
margin: "10px",
height: "auto",
padding: "5px 0",
backgroundColor: "yellow",
textAlign: "center"
}
// 设置box2子元素样式
this.nameArr.forEach((value) => {
for (let i in nameStyle){
value.style[i] = nameStyle[i];
}
})
},
// box3样式
addBoxStyle3(){
// 准备box3样式
let box3Style = {
width: this.container.clientWidth + "px",
height: "auto",
margin: "10px 0",
padding: "10px 0",
borderWidth: "2px",
borderStyle: "solid",
borderColor: "#CCC",
display: "flex",
justifyContent: "center",
alignItems: "center"
}
// 设置box1样式
for (let i in box3Style){
this.box3.style[i] = box3Style[i];
}
// 准备btn1、btn2样式
let btnStyle = {
width: (this.container.clientWidth / 10) + "px",
height: "auto",
margin: "0 10px",
padding: "10px 0",
textAlign: "center",
backgroundColor: "green",
color: "#fff",
border: "none",
outline: "none",
cursor: "pointer"
}
// 设置btn1样式
for (let i in btnStyle){
this.btn1.style[i] = btnStyle[i];
}
// 设置btn2样式
for (let i in btnStyle){
this.btn2.style[i] = btnStyle[i];
}
},
// 绑定事件
bindEvent(){
this.bindBtnEvent1();
this.bindBtnEvent2();
},
// 单选事件
bindBtnEvent1(){
// 绑定单选按钮点击事件
this.btn1.addEventListener("click", () => {
// 首先样式重置
this.nameArr.forEach((value, index) => {
this.nameArr[index].style.backgroundColor = "yellow";
this.nameArr[index].style.color = "";
})
// 随机选择一个成员
let randomName = parseInt(Math.random() * this.nameArr.length);
// 将随机选中的成员添加样式
this.nameArr[randomName].style.backgroundColor = "red";
this.nameArr[randomName].style.color = "#fff";
// 将随机选中的成员渲染到页面
this.clickedSpan.innerText = this.nameArr[randomName].innerText;
})
},
// 多选事件
bindBtnEvent2(){
// 绑定多选按钮点击事件
this.btn2.addEventListener("click", () => {
// 定义一个计数器
let num = 0;
// 定义一个定时器
let timer = setInterval(() => {
// 首先样式重置
this.nameArr.forEach((value, index) => {
this.nameArr[index].style.backgroundColor = "yellow";
this.nameArr[index].style.color = "";
})
// 随机选择一个成员
let randomName = parseInt(Math.random() * this.nameArr.length);
// 计数器加1
num++;
// 将随机选中的成员添加样式
this.nameArr[randomName].style.backgroundColor = "red";
this.nameArr[randomName].style.color = "#fff";
// 定时器执行多次后停止
if(num >= this.count){
clearInterval(timer);
}
// 将随机选中的成员渲染到页面
this.clickedSpan.innerText = this.nameArr[randomName].innerText;
}, this.duration)
})
},
}
return Roll;
})()
面向对象编程——进度条
HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
position: relative;
width: 1000px;
height: 50px;
border: 1px solid #ccc;
margin: 100px auto;
}
.box1{
position: relative;
width: 500px;
height: 50px;
border: 1px solid #ccc;
margin: 100px auto;
}
</style>
</head>
<body>
<div id="box" class="box"></div>
<div id="box1" class="box1"></div>
<script src="../js/Progress.js"></script>
<script>
let box = document.getElementById("box");
let pro = new Progress(box, 0.4, "red", "blue");
let box1 = document.getElementById("box1");
let pro1 = new Progress(box1, 0.1, "yellow");
</script>
</body>
</html>
Progress.js文件
let Progress = (function(){
// 参数1表示进度条容器,参数二表示初始进度(默认值为0),参数三表示进度颜色(默认值为红色),参数四表示进度按钮颜色(默认值为橙色)
function Progress(container, start = 0, barColor = "red", btnColor = "orange"){
this.container = container;
this.start = start;
this.barColor = barColor;
this.btnColor = btnColor;
// 进度
this.bar = document.createElement("div");
// 按钮
this.btn = document.createElement("div");
// 进度值
this.proVal = document.createElement("div");
// 初始进度值
this.width = this.start * (this.container.clientWidth - this.container.clientWidth * 0.05);
this.init();
}
Progress.prototype = {
constructor: Progress,
init(){
this.upTree();
this.addStyle();
this.bindEvent();
},
// 元素上树
upTree(){
this.container.appendChild(this.bar);
this.container.appendChild(this.btn);
this.container.appendChild(this.proVal);
},
// 渲染方法
addStyle(){
this.addBtnStyle();
this.addBarStyle();
this.addProValStyle();
},
// 按钮样式
addBtnStyle(){
// 准备按钮样式
let btnStyle = {
position: "absolute",
height: this.container.clientHeight + "px",
width: this.container.clientWidth * 0.05 + "px",
left: this.width + "px",
backgroundColor: this.btnColor,
cursor: "pointer"
}
// 设置按钮样式
for (let i in btnStyle){
this.btn.style[i] = btnStyle[i];
}
},
// 进度样式
addBarStyle(){
// 准备进度样式
let barStyle = {
position: "absolute",
height: this.container.clientHeight + "px",
width: this.width + "px",
backgroundColor: this.barColor
}
// 设置进度样式
for (let i in barStyle){
this.bar.style[i] = barStyle[i];
}
},
// 进度值样式
addProValStyle(){
// 准备进度值样式
let proValStyle = {
position: "absolute",
height: this.container.clientHeight + "px",
width: "auto",
left: "100%",
textAlign: "center",
lineHeight: this.container.clientHeight + "px",
color: this.btn.style.backgroundColor,
fontSize: this.container.clientHeight * 0.7 + "px"
}
// 设置进度值样式
for (let i in proValStyle){
this.proVal.style[i] = proValStyle[i];
}
// 显示初始进度值
this.proVal.innerText = (this.width / (this.container.clientWidth - this.btn.offsetWidth) * 100).toFixed(2) + "%"
},
// 绑定事件
bindEvent(){
this.btnEvent();
},
// 按钮拖拽事件
btnEvent(){
// 绑定按钮点击事件
this.btn.addEventListener("mousedown", (e) => {
// 浏览器兼容处理
let event = e || window.event;
// 记录鼠标开始时点击的位置
let startX = event.clientX;
// 记录此时按钮的位置
let left = this.btn.offsetLeft;
// 绑定按钮移动事件
document.onmousemove = (e) => {
// 浏览器兼容处理
let event = e || window.event;
// 记录鼠标移动后的位置
let endX = event.clientX;
// 计算此时按钮距离左边的距离
let resultX = endX - startX + left;
// 边界值限定
if(resultX < 0){
// 限定不超出左边
resultX = 0;
}else if(resultX > this.container.clientWidth - this.btn.clientWidth){
// 限定不超出右边
resultX = this.container.clientWidth - this.btn.clientWidth;
}
// 设置鼠标移动后按钮的位置
this.btn.style.left = resultX + "px";
// 设置进度样式随着改变
this.bar.style.width = resultX + "px";
// 渲染进度值
this.proVal.innerText = (resultX / (this.container.clientWidth - this.btn.offsetWidth) * 100).toFixed(2) + "%";
console.log((resultX / (this.container.clientWidth - this.btn.offsetWidth) * 100).toFixed(2) + "%");
}
})
// 绑定鼠标弹起事件
document.addEventListener("mouseup", function() {
// 移除按钮移动事件
document.onmousemove = null;
})
}
}
return Progress;
})()
面向对象编程——简易版贪吃蛇小游戏
HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
html, body{
width: 100%;
height: 100%;
}
.container{
margin: 0 auto;
width: 600px;
height: 600px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="container" class="container"></div>
<script src="../js/Game.js"></script>
<script src="../js/Map.js"></script>
<script src="../js/Snake.js"></script>
<script src="../js/Food.js"></script>
<script>
let container = document.getElementById("container");
let map = new Map(container.clientWidth, container.clientHeight, 20, 20, "#4d4d4d");
let snake = new Snake("red");
let food = new Food(5, 5, "yellow");
let game = new Game(container, map, snake, food, "hard");
</script>
</body>
</html>
Game.js文件
function Game(container, map, snake, food, level){
// 容器
this.container = container;
// 地图
this.map = map;
// 蛇
this.snake = snake;
// 食物
this.food = food;
// 等级(定时器时间间隔)
this.interval = level === "hard" ? 100 : level === "easy" ? 500 : 250;
// 定时器
this.timer = null;
this.flag = false;
// 初始化
this.init();
}
// 渲染地图
Game.prototype = {
constructor: Game,
init(){
this.renderMap();
this.renderSnake();
this.bindEvent();
this.start();
},
renderMap(){
this.container.appendChild(this.map.dom);
// this.container.appendChild(this.map.controls);
},
renderSnake(){
// 根据蛇的坐标,更改地图样式
this.snake.arr.forEach(({x, y}) => {
this.map.arr[x][y].style.backgroundColor = this.snake.snakeColor;
})
},
renderFood(){
let {x, y} = this.food;
this.map.arr[x][y].style.backgroundColor = this.food.foodColor;
},
bindEvent() {
document.addEventListener("keydown", (e) => {
// 只有按下 ↑ ↓ ← →这几个键的时候 或者 w s a d这几个键时 改变蛇的方向
switch (e.keyCode) {
case 65:
case 87:
case 83:
case 68:
case 37:
case 38:
case 39:
case 40:
this.snake.switchDirection(e.keyCode);
break;
}
})
},
// 检测
check(){
// 地图边界检测
this.checkMap();
// 吃到食物检测
this.checkFood();
// 撞到自己检测
this.checkSnake();
},
// 地图边界检测
checkMap(){
// 获取蛇头的坐标
let x = this.snake.arr.slice(-1)[0].x;
let y = this.snake.arr.slice(-1)[0].y;
// 检测是否达到地图边界
if(x < 0 || x >= this.map.row || y < 0 || y >= this.map.col){
// 游戏结束
this.gameover();
}
},
// 吃到食物检测
checkFood(){
// 获取蛇头部坐标
let snakeHeadX = this.snake.arr.slice(-1)[0].x;
let snakeHeadY = this.snake.arr.slice(-1)[0].y;
// 获取食物坐标
let foodX = this.food.x;
let foodY = this.food.y;
if(snakeHeadX === foodX && snakeHeadY === foodY){
// 吃到食物,变长
this.snake.growUp();
// 重置食物
this.resetFood();
}
},
// 撞到自己检测
checkSnake(){
// 把蛇分为头部和身体两部分
// 蛇头坐标
let x = this.snake.arr.slice(-1)[0].x;
let y = this.snake.arr.slice(-1)[0].y;
// 蛇身体
let bodyArr = this.snake.arr.slice(0, -1);
let isExist = bodyArr.some((value) => {
return value.x === x && value.y === y;
})
// 判断是否撞到自己
if(isExist){
// 游戏结束
this.gameover();
}
},
// 添加事件
start(){
this.flag = true;
this.timer = setInterval(() => {
// 蛇移动
this.snake.move();
// 检测
this.check();
if(!this.flag){
clearInterval(this.timer);
return;
}
// 清除屏幕
this.map.clear();
// 重新渲染蛇
this.renderSnake();
// 重新渲染食物
this.renderFood();
}, this.interval)
},
// 游戏结束
gameover(){
this.flag = false;
},
// 重置食物
resetFood(){
// 重新获取一个食物坐标
let x = parseInt(Math.random() * this.map.col);
let y = parseInt(Math.random() * this.map.row);
// 判定食物是否落在蛇身上
let isExist = this.snake.arr.some((value) => {
return value.x === x && value.y === y;
})
if(isExist){
// 重新重置食物
this.resetFood();
return;
}
this.food.x = x;
this.food.y = y;
}
}
Map.js文件
// 参数一表示容器宽度。参数二表示容器高度,参数三表示地图行数,参数四表示地图列数,参数五表示地图颜色
function Map(width, height, row, col, mapColor = "#444"){
this.width = width;
this.height = height;
this.row = row;
this.col = col;
this.mapColor = mapColor;
// 创建地图容器
this.dom = document.createElement("div");
// 定义数组,方便获取每一列元素,是一个二维数组
this.arr = [];
// 定义数组,用于存放行元素
this.rowArr = [];
// 初始化
this.init();
}
Map.prototype = {
constructor: Map,
init(){
this.create();
// this.createControls();
this.addStyle();
},
// 创建地图
create(){
// 循环创建行
for (let i = 0; i < this.row; i++){
// 定义行元素
let rowElement = document.createElement("div");
// 将rowElement追加到rowArr数组中
this.rowArr.push(rowElement);
// 定义数组,用于存放列元素
let colArr = [];
// 循环创建列
for (let j = 0; j < this.col; j++){
// 定义列元素
let colElement = document.createElement("div");
// 将corElement追加到rowElement中
rowElement.appendChild(colElement);
// 将corElement追加到colArr数组中
colArr.push(colElement);
}
// 内层循环结束,将colArr追加到arr数组中
this.arr.push(colArr);
// 将rowElement追加到map中
this.dom.appendChild(rowElement);
}
},
// 添加样式
addStyle(){
this.addMapStyle();
this.addRowStyle();
this.addColStyle();
},
// 添加map样式
addMapStyle(){
// 准备Map样式
let mapStyle = {
width: "100%",
height: "100%",
backgroundColor: this.mapColor
}
// 设置Map样式
for (let i in mapStyle){
this.dom.style[i] = mapStyle[i];
}
},
// 添加行样式
addRowStyle(){
// 准备行样式
let rowStyle = {
width: "100%",
height: 100 / this.row + "%",
borderBottom: "1px solid #CCC",
boxSizing: "border-box"
}
// 设置行样式
for (let i in rowStyle){
for (let j = 0; j < this.rowArr.length; j++){
this.rowArr[j].style[i] = rowStyle[i];
}
}
// 设置最后一行没有下边框
this.rowArr.slice(-1)[0].style.borderBottom = "none";
},
// 添加列样式
addColStyle(){
// 准备列样式
let colStyle = {
float: "left",
width: 100 / this.col + "%",
height: "100%",
borderRight: "1px solid #ccc",
boxSizing: "border-box"
}
// 设置列样式
this.arr.forEach((value) => {
value.forEach((value) => {
for (let i in colStyle){
value.style[i] = colStyle[i];
}
})
// 设置最后一列没有右边框
value.slice(-1)[0].style.borderRight = "none";
})
},
// 添加控制面板样式
addControlsStyle(){
// 准备控制面板样式
let controlsStyle = {
width: "100%",
height: "10%",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "#CCC"
}
// 设置控制面板样式
for (let i in controlsStyle){
this.controls.style[i] = controlsStyle[i];
}
},
// 蛇移动后,清除屏幕(重置地图样式)
clear(){
this.arr.forEach((value) => {
value.forEach((value) => {
value.style.backgroundColor = this.mapColor;
})
})
},
}
Snake.js文件
function Snake(snakeColor = "red"){
// 蛇的颜色
this.snakeColor = snakeColor;
// 设置蛇的起始长度和位置
this.arr = [{x: 0, y: 0}, {x: 0, y: 1}];
// 设置蛇默认的运动方向,上下左右分别是U\D\L\R
this.direction = "R";
// 设置锁
this.lock = true;
this.init();
}
Snake.prototype = {
constructor: Snake,
init(){
this.move();
this.switchDirection();
},
// 判断键盘事件,确定运动方向
switchDirection(code){
// 判断锁状态,在蛇的上一步运动结束后,才能改变蛇的下一步运动方向
if(!this.lock){
return;
}
// 键盘事件
// 如果传递的是W或者↑,表示向上运动,并且向上运动时不能直接180度掉头向下运动
// 如果传递的是S或者↓,表示向下运动,并且向下运动时不能直接180度掉头向上运动
// 如果传递的是A或者←,表示向左运动,并且向左运动时不能直接180度掉头向右运动
// 如果传递的是D或者→,表示向右运动,并且向右运动时不能直接180度掉头向左运动
if((code === 87 || code === 38) && this.direction != "D"){
this.direction = "U";
} else if ((code === 83 || code === 40) && this.direction != "U"){
this.direction = "D";
} else if ((code === 65 || code === 37) && this.direction != "R"){
this.direction = "L";
} else if ((code === 68 || code === 39) && this.direction != "L"){
this.direction = "R";
}
this.lock = false;
},
// 蛇运动
// 蛇的头部是数组的最后一个成员,蛇的尾部是数组的第一个成员
// 蛇默认向右运动,蛇运动的时候,可以看做是将蛇的尾巴去掉,添加新的蛇头
move(){
// 去掉蛇尾
this.arr.shift();
// 定义新蛇头
let newHead = {
x: this.arr[this.arr.length - 1].x,
y: this.arr[this.arr.length - 1].y
}
// 根据运动方向确定新蛇头的位置
// 如果向右 y + 1
// 如果向左 y - 1
// 如果向上 x - 1
// 如果向下 x + 1
if (this.direction === "R"){
newHead.y++;
} else if(this.direction === "L"){
newHead.y--;
} else if(this.direction === "U"){
newHead.x--;
} else if(this.direction === "D"){
newHead.x++;
}
// 将新位置追加到数组
this.arr.push(newHead);
// 开锁
this.lock = true;
},
// 蛇吃到食物,身体边长
growUp(){
// 在蛇尾添加一个成员
let newTail = {
x: this.arr[0].x,
y: this.arr[0].y
}
this.arr.unshift(newTail);
// console.log(this.arr.length)
}
}
Food.js文件
// 参数一表示第一次食物在x上的位置,参数二表示第一次食物在y上的位置,参数三表示食物颜色
function Food(x = 0, y = 3, foodColor = "green"){
this.x = x;
this.y = y;
this.foodColor = foodColor;
}