操作元素节点的 style 属性, 修改样式
因为 JavaScript 不能直接操作 css, 所以只能用操作 style
属性的方式来修改样式
html
<html lang="en">
<head>
<title>js</title>
</head>
<body>
<div id="app"></div>
<!-- javascript -->
<script type="text/javascript">
window.onload = function () {
var app = document.getElementById("app");
app.style.width = "200px";
app.style.height = "300px";
app.style.background = "black";
};
</script>
</body>
</html>
注意: 特殊属性, js 的保留字 float
必须这样设置 cssFloat
getComputedStyle 获取元素的 css 样式(包括默认值)
CSSStyleDeclaration 是 CSS 属性键值对的集合, 是一个 Array-Like
html
<html lang="en">
<head>
<title>js</title>
</head>
<style>
#app {
width: 100px;
height: 150px;
background-color: red;
}
</style>
<body>
<div id="app"></div>
<!-- javascript -->
<script type="text/javascript">
var app = document.getElementById("app");
// console.log(app.style.width); // 通过style属性是获取不到的
var appStyle = window.getComputedStyle(app); // 获取的是一个 CSSStyleDeclaration 对象
console.log(appStyle.width); // 100px
</script>
</body>
</html>
这个方法是非常好用的, 但是很可惜万恶的 IE8 不支持这个方法
javascript
/**
* get element computed styles
* @returns {string|number|undefined}
*/
function getStyles(el, prop) {
if (window.getComputedStyle) {
getStyles = function (el, prop) {
var styles = window.getComputedStyle(el, null);
return styles[prop] ? styles[prop] : undefined;
};
} else {
getStyles = function (el, prop) {
// ie
var styles = el.currentStyle;
return styles[prop] ? styles[prop] : undefined;
};
}
return getStyles(el, prop);
}
getComputedStyle 获取伪元素的样式
getComputedStyle 的第二个参数就是填写伪元素类型的, 填写其他的报错
html
<html lang="en">
<head>
<title>js</title>
</head>
<style>
#app {
width: 500px;
height: 500px;
}
#app::before {
content: "";
width: 100px;
height: 100px;
background: red;
}
#app::after {
content: "";
width: 200px;
height: 200px;
background: blue;
}
</style>
<body>
<div id="app"></div>
<!-- javascript -->
<script type="text/javascript">
var app = document.getElementById("app");
var afterStyle = window.getComputedStyle(app, "after");
var beforeStyle = window.getComputedStyle(app, "before");
console.log("beforeStyle: ", beforeStyle.width); // 100px
console.log("afterStyle: ", afterStyle.height); // 200px
</script>
</body>
</html>
大量操作元素的样式的策略
- style
- className(推荐)
html
<html lang="en">
<head>
<title>js</title>
</head>
<style>
.some-styles {
width: 100px;
height: 200px;
background: black;
}
</style>
<body>
<div id="box1"></div>
<div id="box2"></div>
<!-- javascript -->
<script type="text/javascript"></script>
<script type="text/javascript">
var box1 = document.getElementById("box1"),
box2 = document.getElementById("box2");
// bad: 这样的代码很难维护
box1.style.width = "100px";
box1.style.height = "200px";
box1.style.background = "black";
// good: css和js代码是分开的, 容易理解和维护代码
box2.classList.add("some-styles");
</script>
</body>
</html>
定时器动画
下拉菜单
html
<html lang="en">
<head>
<title>js</title>
</head>
<style>
html,
body,
.dropdown,
.main,
.item {
padding: 0;
margin: 0;
list-style: none;
}
.dropdown {
width: 150px;
margin: 20px;
}
.dropdown .trigger {
border: none;
width: 150px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
color: #fff;
background-color: #222;
position: relative;
/* margin-bottom: 5px; */
}
.trigger::after {
content: "v";
position: absolute;
top: 7px;
right: 15px;
}
.active.trigger::after {
content: "^" !important;
font-size: 20px;
top: 10px;
}
.dropdown .dropdown-menu {
height: 0px;
overflow: hidden;
background-color: #555;
color: #fff;
}
.dropdown-menu .menu-item {
justify-content: center;
align-items: center;
display: flex;
height: 40px;
}
.menu-item:hover {
cursor: pointer;
background-color: #222;
}
</style>
<body>
<div class="dropdown">
<a href="javascript:;" class="trigger">下拉菜单</a>
<div class="dropdown-menu">
<div class="menu-item">项目1</div>
<div class="menu-item">项目2</div>
<div class="menu-item">项目3</div>
<div class="menu-item">项目4</div>
<div class="menu-item">项目5</div>
</div>
</div>
<!-- javascript -->
<script type="text/javascript"></script>
<script>
(function () {
/**
* 计算一个元素当前的样式
*/
var getStyle = (function () {
if (window.getComputedStyle) {
return function (ele, prop) {
var styles = window.getComputedStyle(ele, null);
return styles[prop] ? styles[prop] : undefined;
};
}
return function (el, prop) {
// ie
var styles = el.currentStyle;
return styles[prop] ? styles[prop] : undefined;
};
})();
var dropdown = document.getElementsByClassName("dropdown")[0],
trigger = dropdown.getElementsByClassName("trigger")[0],
menu = dropdown.getElementsByClassName("dropdown-menu")[0],
menuHeight = 0,
speed = 5,
steps = 5,
timer;
/**
* handle on mouse enter event
*/
dropdown.onmouseenter = function () {
// handle icon
trigger.classList.add("active");
// show menus animate
var showMenu = function () {
menuHeight = parseInt(getStyle(menu, "height")) || 0;
menuHeight += steps;
if (menuHeight >= 200) {
menu.style.height = 200 + "px";
timer && clearInterval(timer);
return;
}
menu.style.height = menuHeight + "px";
};
timer && clearInterval(timer);
timer = setInterval(showMenu, speed);
};
/**
* handle on mouse leave event
*/
dropdown.onmouseleave = function () {
// handle icon
trigger.classList.remove("active");
// hide menus animate
var hideMenu = function () {
menuHeight = parseInt(getStyle(menu, "height")) || 0;
menuHeight -= steps;
if (menuHeight <= 0) {
menu.style.height = "0px";
timer && clearInterval(timer);
return;
}
menu.style.height = menuHeight + "px";
};
timer && clearInterval(timer);
timer = setInterval(hideMenu, speed);
};
})();
</script>
</body>
</html>
课后作业
淘宝首页无限轮播图 完成了无限轮播: 但是问题是: 第一张和最后一张不是连续的, 最后一张切换到第一张的时候有一段空白
index.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<title>js</title>
<link rel="stylesheet" href="./css/index.css" />
</head>
<style></style>
<body>
<div class="slider">
<ul class="slider-wrapper">
<li class="slider-item"><img src="./images/1.jpg" /></li>
<li class="slider-item"><img src="./images/2.jpg" /></li>
<li class="slider-item"><img src="./images/3.jpg" /></li>
<li class="slider-item"><img src="./images/4.jpg" /></li>
<li class="slider-item"><img src="./images/5.jpg" /></li>
<li class="slider-item"><img src="./images/6.jpg" /></li>
</ul>
</div>
<script src="./js/index.js"></script>
<script>
var slider = new Slider({
slider: "slider-wrapper",
showPoints: true,
});
</script>
</body>
</html>
css/index.css
css
html,
body {
margin: 0;
padding: 0;
}
/* clear ul, li tag list-style */
.slider .slider-wrapper,
.slider .slider-item {
list-style: none;
margin: 0;
padding: 0;
}
.slider {
width: 500px;
margin: 30px;
position: relative;
overflow: hidden;
}
.slider .slider-wrapper {
width: 3000px;
display: flex;
}
.slider-item img {
width: 500px;
}
/* === */
.point-wrapper,
.point-item {
margin: 0;
padding: 0;
list-style: none;
}
.point-wrapper {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
height: 20px;
display: flex;
align-items: center;
justify-content: space-around;
}
.point-wrapper .point-item {
width: 10px;
height: 10px;
margin: 0 5px;
border-radius: 15px;
background: #fff;
opacity: 0.5;
}
.point-item.active,
.point-item:hover {
background: #f00;
}
js/index.js
javascript
(function () {
"use strict";
/**
* 计算一个元素当前的样式
*/
var getStyle = (function () {
if (window.getComputedStyle) {
return function (ele, prop) {
var styles = window.getComputedStyle(ele, null);
return styles[prop] ? styles[prop] : undefined;
};
}
return function (el, prop) {
var styles = el.currentStyle;
return styles[prop] ? styles[prop] : undefined;
};
})();
function Slider(options) {
var slider = document.getElementsByClassName(options.slider)[0];
this.speed = options.speed || 2000;
this.showPoints = options.showPoints || true;
this.slider = slider;
this.items = slider.children;
this.count = slider.childElementCount;
this.pointItems = [];
if (this.showPoints) {
this.pointItems = this.initPoints("point-wrapper", "point-item");
}
this.start();
this.index = 0;
this.timer;
this.animateTimer;
}
// 初始化指示灯
Slider.prototype.initPoints = function (pointClass, itemClass) {
var mouseEnterHandler = (i) => {
return () => {
this.timer && clearInterval(this.timer);
this.animateTimer && clearInterval(this.animateTimer);
this.index = i;
this.move();
};
};
var mouseLeaveHandler = (i) => {
this.index = i;
return this.start.bind(this);
};
var pointWrapper = document.createElement("ul");
pointWrapper.classList.add(pointClass);
var item;
var pointItems = [];
for (var i = 0, len = this.count; i < len; i++) {
item = document.createElement("li");
item.classList.add(itemClass);
(function (i) {
item.onmouseenter = mouseEnterHandler(i);
item.onmouseleave = mouseLeaveHandler(i);
})(i);
pointItems.push(item);
pointWrapper.appendChild(item);
}
this.slider.appendChild(pointWrapper);
pointItems[0].classList.add("active");
return pointItems;
};
// 开启循环
Slider.prototype.start = function () {
this.timer && clearInterval(this.timer);
this.timer = setInterval(() => {
this.index += 1;
if (this.index >= this.count) {
this.index = 0;
}
this.move();
}, this.speed);
};
// 切换动画
Slider.prototype.move = function () {
var sliderWidth = parseInt(getStyle(this.slider, "width")), // 总宽度
itemWidth = sliderWidth / this.count, // 每一个item的宽度
target = this.index * itemWidth, // 目标位置
current = target - itemWidth; // 当前位置
this.selectPoint();
this.animateTimer && clearInterval(this.animateTimer);
this.animateTimer = setInterval(() => {
// start move animate
current += 10;
if (current >= target) {
current = target;
this.slider.style.marginLeft = -current + "px";
this.animateTimer && clearInterval(this.animateTimer);
return;
}
this.slider.style.marginLeft = -current + "px";
}, 5);
};
// 选中一个指示灯
Slider.prototype.selectPoint = function () {
var items = this.pointItems;
for (var i = 0, len = items.length; i < len; i++) {
items[i].classList.remove("active");
}
items[this.index].classList.add("active");
};
window.Slider = Slider;
})();