动画帧
var box = document.querySelector(".box");
var l = 0
var timer = null;
function move(){
l+=10;
box.style.left = l+'px'
if(l>=300){
cancelAnimationFrame(timer);
console.log(1111);
return;
}
timer = requestAnimationFrame(move);
}
box.addEventListener("click",()=>{
timer = requestAnimationFrame(move);
});
自定义获取css
function css(...args){
if(arguments.length==2){
var val = "";
switch(arguments[1]){
case 'width':
case 'height':
val=parseFloat(getComputedStyle(arguments[0])[arguments[1]]);
break;
case 'zIndex':
case 'backgroundColor':
default:
val = getComputedStyle(arguments[0])[arguments[1]] ;
break;
}
return val;
}else if(arguments.length==3){
switch(arguments[1]){
case "width":
case "height":
arguments[0].style[arguments[1]] = arguments[2] +'px';
break;
case 'zIndex':
case 'backgroundColor':
default:
arguments[0].style[arguments[1]] = arguments[2];
}
}
}
自定义运动框架
function motion(obj){
let {el,attr,duration,target,type} = obj;
if(!el){
alert("请传入元素");
return
}else if(!attr){
alert("请传入所要改变的属性");
return
}else if(!target){
alert("强传入改变的值");
return
}
duration = obj.duration || 1000;
type= obj.type || 'easeOut';
var t = 0;
var speed= 1000/60;
var d = Math.ceil(duration/speed);
var des ={};
for(key in attr){
des[key] = target[key]-attr[key];
}
el.timer = requestAnimationFrame(move);
function move(){
if(t>=d){
cancelAnimationFrame(el.timer);
obj.fn&&obj.fn();
return
}else{
el.timer=requestAnimationFrame(move);
}
t++;
for(key in des){
el.style[key] =Tween[type](t,attr[key],des[key],d)+'px';
}
}
}
调用该框架
var w = css(box,'width');
var h = css(box,"height");
box.addEventListener("click",function(){
motion({
el:box,
attr:{
width:w,
},
duration:1000,
target:{
width:500,
},
type:"elasticIn",
fn:function(){
motion({
el:box,
attr:{
height:h,
},
duration:1000,
target:{
height:600,
},
type:"elasticIn",
})
}
});
});
时钟案例
var list = document.querySelector("#lattice-list");
var h = document.querySelector(".hour");
var m = document.querySelector(".min");
var s = document.querySelector(".sec");
for(var i=0;i<12;i++){
list.innerHTML+=`<li style="transform:rotate(${i*30}deg)"></li>`
}
function clock(){
var date = new Date();
var sec = date.getSeconds();
var min = date.getMinutes()+sec/60;
var hour = date.getHours()+min/60;
h.style.transform="rotate("+(30*hour)+"deg)";
m.style.transform="rotate("+(6*min)+"deg)";
s.style.transform="rotate("+(6*sec+45)+"deg)";
}
clock();
setInterval(()=>{
clock();
},1000);
幻灯片案例
var lis = document.querySelectorAll("li");
lis = Array.from(lis);
console.log(lis.length);
var images = document.querySelectorAll("li img");
images = Array.from(images);
var next = document.querySelector(".next_div");
var arr = [];
lis.forEach((item,index)=>{
var obj = {};
obj.l = css(item,"left");
obj.t = css(item,"top");
obj.z = css(item,"z-index");
obj.o = css(item,"opacity");
obj.img = {};
obj.img.w = css(images[index],"width");
obj.img.h = css(images[index],"height");
arr.push(obj);
});
next.addEventListener("click",function(){
lis.unshift(lis.pop());
images.unshift(images.pop());
arr.forEach((item,index)=>{
mTween({
el: lis[index],
attr:{
left:item.l,
top:item.t,
zIndex:item.z,
opacity:item.o
}
});
mTween({
el: images[index],
attr:{
width:item.img.w,
height:item.img.h
}
});
});
});
Windows日历(案例)
思路
- 运用js html css 技术 以及封装框架(自定义获取样式方法)
- 该项目分为 表盘木块 日历模块
公共方法
var week=['日','一','二','三','四','五','六'];
function getEl(selector){
return document.querySelector(selector);
}
function add0(num){
return num<10?"0"+num:""+num;
}
时钟模块
(function(){
var list = getEl("#lattice-list");
var hour = getEl(".hour");
var min = getEl(".min");
var sec = getEl(".sec");
list.innerHTML = createLattice();
function createLattice(){
var inner = "";
var deg = 360/12;
for(var i =0; i<12;i++){
inner+=`<li class="lattice" style="transform:rotate(${i*deg}deg)"></li>`
}
return inner;
}
clock();
setInterval(clock,30);
function clock(){
var date = new Date();
var ms = date.getMilliseconds();
var s = date.getSeconds()+ms/1000;
var m = date.getMinutes()+s/60;
var h = date.getHours()+m/60;
var secDeg = 6*s+45;
var minDeg = 6*m;
var horDeg = 30*h;
css(sec,"rotate",secDeg);
css(min,"rotate",minDeg);
css(hour,"rotate",horDeg);
}
})();
时钟旁边日期模块
(function(){
var now =getEl("#now");
var option = getEl("#option");
var date = new Date();
var y = date.getFullYear();
var m = add0(date.getMonth()+1);
var day = add0(date.getDate());
var w = date.getDay();
now.innerHTML =`<p>${y}年 ${m}月 ${day}日</p><p>星期${week[w]}</p>`;
})();
日期模块
function initDateView(board,year,month){
var str="";
var str = "<ul class='week'>";
for(var i=0;i<7;i++){
str +=`<li class="date-cell">${week[i]}</li>`;
}
str+="</ul>"
str+='`<ul class="date">';
var lastMonthDates = new Date(year,month,0).getDate();
var thisMonthDay = new Date(year,month,1).getDay();
var thisMonthDates = new Date(year,month+1,0).getDate();
for(var i=0;i<42;i++){
if(thisMonthDay>i){
var num = lastMonthDates-(thisMonthDay-i-1);
str +=`<li class="date-cell other-date">${lastMonthDates-(thisMonthDay-i-1)}</li>`
}else if(i-thisMonthDay<thisMonthDates){
if(year==nowYear && month==nowMonth && nowDate==i-thisMonthDay+1){
str += `<li class="date-cell active">${i-thisMonthDay+1}</li>`
}else{
str += `<li class="date-cell ">${i-thisMonthDay+1}</li>`;
}
}else{
str += `<li class="date-cell other-date">${i-thisMonthDay-thisMonthDates+1}</li>`;
}
}
str += "</ul>"
board.innerHTML =str;
}
月份模块
function initMonthView(board,year){
var str ="<ul class='month'>";
for(var i =1;i<13;i++){
if(year==nowYear && nowMonth==i-1){
str+=`<li class="month-cell active">${i}月</li>`;
}else{
str+=`<li class="month-cell">${i}月</li>`
}
}
str+="</ul>";
board.innerHTML = str;
var lis = board.querySelectorAll("li");
lis.forEach(item=>{
item.addEventListener("click",()=>{
nextOptionType = 0;
nowMonth = parseInt(item.innerHTML)-1;
tabViews();
});
})
}
年份模块
function initYearsView(board,year){
var startYear = Math.floor(year/10)*10;
var endYear = startYear+9;
var str ="<ul class='year'>";
for(var i =0;i<16;i++){
if(i<4){
str+=`<li class="year-cell other-yaer">${startYear-(4-i)}</li>`
}else if(i<14){
if(nowYear == startYear+(i-4)){
str+=`<li class="year-cell active">${startYear+(i-4)}</li>`
}else{
str+=`<li class="year-cell">${startYear+(i-4)}</li>`
}
}else{
str+=`<li class="year-cell other-yaer">${endYear+(i-14)+1}</li>`
}
}
str +="</ul>"
board.innerHTML = str;
var lis =board.querySelectorAll("li");
lis.forEach(item=>{
item.addEventListener("click",()=>{
nowYear = Number(item.innerHTML);
nextOptionType=1;
tabViews();
});
})
}
视图切换模块
(function(){
var board = getEl(".board");
var option = getEl("#option");
var main = getEl("#main");
var prev = getEl("#prev");
var next = getEl("#next");
var date = new Date();
var nowYear= date.getFullYear();
var nowMonth = date.getMonth();
var nowDate = date.getDate();
var setYear= nowYear;
var setMonth = nowMonth;
var setDate = nowDate;
var optionType = 0;
var nextOptionType;
initDateView(board,setYear,setMonth);
initOptionView();
option.addEventListener("click",()=>{
nextOptionType = optionType+1;
if(nextOptionType>2){
nextOptionType=2;
}else{
tabViews();
}
initOptionView();
console.log(optionType+"============"+nextOptionType);
});
function initOptionView(){
switch(optionType){
case 0:
option.innerHTML = nowYear + '年' + (nowMonth+1) + '月';
console.log(nowMonth);
break;
case 1:
option.innerHTML = nowYear + '年';
break;
case 2:
var startYear = Math.floor(nowYear/10)*10;
var endYear = startYear + 9;
option.innerHTML = startYear + ' - ' + endYear;
break;
}
}
function tabViews(){
if(optionType<nextOptionType){
main.innerHTML =`<div class="board toHide"></div> <div class="board toShow"></div>`;
var board = main.querySelectorAll(".board");
board.forEach(item => {
item.addEventListener("animationend",()=>{
if(item.classList.contains("toHide")){
main.removeChild(item);
}
});
});
switch(nextOptionType){
case 1:
initDateView(board[0],setYear,setMonth);
initMonthView(board[1],setYear);
optionType = nextOptionType;
break;
case 2:
initMonthView(board[0],setYear);
initYearsView(board[1],setYear);
optionType = nextOptionType;
break;
}
}else{
main.innerHTML =`<div class="board toBlow"></div> <div class="board toNarrow"></div>`;
var board = main.querySelectorAll(".board");
board.forEach(item => {
item.addEventListener("animationend",()=>{
if(item.classList.contains("toBlow")){
main.removeChild(item);
}
});
});
switch(nextOptionType){
case 0:
initDateView(board[1],setYear,setMonth);
initMonthView(board[0],setYear);
optionType = nextOptionType;
break;
case 1:
initYearsView(board[0],setYear);
initMonthView(board[1],setYear,setMonth);
optionType = nextOptionType;
break;
}
}
initOptionView();
}
prev.addEventListener("click",()=>{
scrollDateView(-1);
});
next.addEventListener("click",()=>{
scrollDateView(1);
});
function getTime(){
var date = new Date(nowYear,nowMonth);
nowYear = date.getFullYear();
nowMonth = date.getMonth();
}
function scrollDateView(dir){
if(dir>0){
main.innerHTML =`<div class="board topOut"></div> <div class="board toTop"></div>`;
var board = main.querySelectorAll(".board");
switch(optionType){
case 0 :
initDateView(board[0],nowYear,nowMonth);
nowMonth = nowMonth+1;
getTime();
initDateView(board[1],nowYear,nowMonth);
break;
case 1:
initYearsView(board[0],nowYear);
nowYear = nowYear+1;
getTime();
initYearsView(board[1],nowYear);
break;
case 2:
initYearsView(board[0],nowYear);
nowYear = nowYear+10;
getTime();
initYearsView(board[1],nowYear);
break;
}
}else{
main.innerHTML =`<div class="board bottomOut"></div> <div class="board toBottom"></div>`;
var board = main.querySelectorAll(".board");
switch(optionType){
case 0 :
initDateView(board[0],nowYear,nowMonth);
nowMonth = nowMonth-1;
getTime();
initDateView(board[1],nowYear,nowMonth);
break;
case 1:
initYearsView(board[0],nowYear);
nowYear = nowYear-1;
getTime();
initYearsView(board[1],nowYear);
break;
case 2:
initYearsView(board[0],nowYear);
nowYear = nowYear-10;
getTime();
initYearsView(board[1],nowYear);
break;
}
}
initOptionView();
}
})();
Dom
获取元素
var list = box.childNodes;
var child = box.children;
var first = box.firstChild;
var ele = box.firstElementChild;
console.log(first,ele);
var text = box.nextSibling;
console.log(text);
var tag = box.nextElementSibling;
var pre = box.previousElementSibling;
var father = box.parentNode;
var offset = box.offsetParent;
创建节点
var d = document.createElement("div");
插入节点
document.body.append(d);
document.body.appendChild(d);
document.body.insertBefore(d,box);
替换节点(会删除旧节点)
box.replaceChild(d,p);
删除节点
box.removeChild(d);
box.remove();
克隆元素
var clone = box.cloneNode(true);
动态文件夹(案例)
var create = document.querySelector("#create");
var folder = document.querySelector("#folder");
create.addEventListener("click",()=>{
var li = document.createElement("li");
li.innerHTML = `<div class="checkbox"></div>
<div class="name">新建文件夹</div>`;
li.addEventListener("click",()=>{
var checkbox = li.querySelector(".checkbox");
if(li.classList.contains("border")){
li.classList.remove("border");
checkbox.innerText = "";
}else{
checkbox.innerText = "√";
li.classList.add("border");
}
});
folder.append(li);
})
学生管理系统(案例)
(function(){
var btn = document.querySelector("#addBtn");
var usernameInp = document.querySelector("#username");
var ageInp = document.querySelector("#age");
var genderInp = document.querySelector("#gender");
var username = usernameInp.value;
var age = ageInp.value;
var gender = genderInp.value;
var tbody = document.querySelector("tbody");
var checkAll = document.querySelector("#checkAll");
var id = 0;
btn.addEventListener("click",()=>{
checkAll.checked =false;
var tr = document.createElement("tr");
var th1 = document.createElement("th");
th1.innerHTML = `<input type="checkbox"/> `;
tr.append(th1);
var checkBtn = th1.querySelector("input");
checkBtn.addEventListener("change",function(){
var flag =isCheckAll();
if(flag){
checkAll.checked =true;
}else{
checkAll.checked =false;
}
})
var th2 = document.createElement("th");
id++
th2.innerHTML = id;
tr.append(th2);
var th3 = document.createElement("th");
th3.innerText = username;
tr.append(th3);
var th4 = document.createElement("th");
th4.innerText = age;
tr.append(th4);
var th5 = document.createElement("th");
th5.innerText = gender;
tr.append(th5);
var th6 = document.createElement("th");
th6.innerHTML = `<a href="javascript:;">↑</a><a href="javascript:;">↓</a>`;
tr.append(th6);
var sortBtns =th6.querySelectorAll("a");
console.log(sortBtns.length);
sortBtns[0].addEventListener("click",function(){
var parent = this.parentNode.parentNode;
var sibling =parent.previousElementSibling;
console.log(sibling);
tbody.insertBefore(parent,sibling);
});
sortBtns[1].addEventListener("click",function(){
var parent = this.parentNode.parentNode;
var sibling =parent.nextSibling;
if(sibling){
tbody.insertBefore(sibling,parent);
}else{
tbody.insertBefore(parent,tbody.childNodes[0]);
}
});
var th7 = document.createElement("th");
th7.innerHTML = `<a href="javascript:;">删除</a>`;
var removeBtn = th7.querySelector("a");
removeBtn.addEventListener("click",function(){
var parent =this.parentNode.parentNode;
parent.remove();
});
tr.append(th7);
tbody.append(tr);
});
checkAll.addEventListener("click",function(){
var checkItem = tbody.querySelectorAll("input[type=checkbox]");
if(this.checked){
checkItem.forEach((item)=>{
item.checked = true;
});
}
});
function isCheckAll(){
var checkItem = tbody.querySelectorAll("input[type=checkbox]");
var flag =[...checkItem].every(item => item.checked && checkItem.length>0);
return flag;
}
})();
nodetype
var div = document.querySelector("div");
var list = div.childNodes;
console.log(list);
console.log(document.nodeType);
list.forEach(item=>{
console.log(item.nodeType);
});
var name = div.nodeName;
console.log(name);
设置属性
var arr = div.attributes;
console.log(arr);
div.setAttribute("name","tag");
div.tag = "tag";
div.getAttribute("tag");
div.removeAttribute("key");
div.hasAttribute("key");
div.dataset.index = 123;
var value = div.dataset.index;
console.log(value);
value = div.getAttribute("data-index");
console.log(value);
value = div.index
console.log(value);
offset属性
var box = document.querySelector(".box");
var w = box.offsetWidth
var t = box.offsetTop;
console.log(t);
client
var w = box.clientWidth;
var l =box.clientLeft;
console.log(l);
scroll
var w = box.scrollWidth;
window.addEventListener("scroll",()=>{
var rect = search.getBoundingClientRect();
if(rect.bottom<0){
banner.style.display = "block";
}else{
banner.style.display = "none";
}
});
window内置属性
var w =window.innerWidth;
console.log(w);
window.addEventListener("resize",()=>{
console.log(window.innerWidth);
});
var btn = document.querySelector("input");
btn.addEventListener("click",()=>{
window.scrollTo(0,0);
});
document
var dw = document.documentElement.clientWidth;
无限下拉菜单
var data = data;
// return省略{}也要省略return
function getChildren(id){
return data.filter(item=>item.pid==id);
}
// 该参数必须是个数组
function renderUI(arr){
console.log(arr);
var str = "<ul>"
arr.forEach(item => {
str +=`<li>
<p>${item.title}</p>
${getChildren(item.id)&&renderUI(getChildren(item.id))}
</li>`;
});
str +="</ul>";
return str;
}
// console.log(getChildren(-1));
// console.log(renderUI(getChildren(-1)));
menu.innerHTML = renderUI(getChildren(-1));
menu.addEventListener("click",(e)=>{
var obj =e.target;
if(obj.tagName=="P"){
obj.nextElementSibling.classList.toggle("show");
}
});
返回顶部(案例)
(function(){
var search = document.querySelector("#search");
var banner = document.querySelector("#banner");
var float = document.querySelector("#float");
var backTop = document.querySelector("#backTop");
var fT = getFloatPosition(float).fTop;
function adsorb(){
var sRect = search.getBoundingClientRect();
if(sRect.bottom<0){
banner.style.display = "block";
}else{
banner.style.display = "none";
}
}
function getFloatPosition(el){
var fRect = el.getBoundingClientRect();
var fY = window.scrollY;
var fX = window.scrollX;
var ftop = fRect.top;
var fleft = fRect.left;
return{
fTop:fY+ftop,
fLeft:fX+fleft
}
}
function getPageOffset(){
var bannerH = banner.offsetHeight;
if(scrollY+bannerH>fT){
float.style.position="fixed";
float.style.top = bannerH +'px';
}else{
float.style.position="absolute";
float.style.top = "50%";
}
}
function backUp(){
if(scrollY>innerHeight){
backTop.style.display="block";
}else{
backTop.style.display="none";
}
}
backTop.addEventListener("click",()=>{
document.body.scrollTop = document.documentElement.scrollTop=0;
});
window.addEventListener("scroll",()=>{
adsorb();
getPageOffset();
backUp();
});
})();
location
console.log(location);
console.log(location.href);
console.log(location.hash);
console.log(location.search);
var btns = document.querySelectorAll("a");
var content = document.querySelector(".content");
window.addEventListener("hashchange",()=>{
switch(location.hash){
case "#about":
content.innerHTML = "<h2>关于我们</h2>";
break;
case "#join":
content.innerHTML = "<h2>加入我们</h2>";
break;
}
});
btns[2].addEventListener("click",()=>{
location.reload();
});
history
btn.addEventListener("click",()=>{
history.go(-2);
});
btns[1].addEventListener("click",()=>{
history.back();
});
btns[0].addEventListener("click",()=>{
history.forward();
});
btns[1].addEventListener("click",()=>{
history.go(2);
});
navigator
console.log(navigator.userAgent);
console.log(navigator.appName);
console.log(navigator.appVersion);
history
console.log(screen);
console.log(screen.width);
console.log(screen.height);
hashchange(案例)
{
var lis = document.querySelectorAll(".nav li");
var container = document.querySelector(".list-group");
var pagination = document.querySelector(".pagination");
var data = data;
window.addEventListener("hashchange",()=>{
var hash = location.hash;
hash = hash.substring(2);
var hashArray = hash.split("/");
lis.forEach(item=>{
item.classList.remove("active");
});
if(hashArray[0]=='sh'){
lis[0].classList.add("active");
if(hashArray[1]=='details'){
renderDetailsPage(
{
type:'society',
pid: hashArray[2]
}
);
}else{
renderList(
{
type:'society',
pageNumber:hashArray[1]?hashArray[1]:0,
}
);
}
}else if(hashArray[0]=='xy'){
lis[1].classList.add("active");
if(hashArray[1]=='details'){
renderDetailsPage(
{
type:'campus',
id: hashArray[2]
}
);
}else{
renderList(
{
type:'campus',
pageNumber:hashArray[1]?hashArray[1]:0,
}
);
}
}
});
function renderList(props){
let {type,pageNumber} = props;
var newArray = data[type];
var len = 5;
var start = parseInt(pageNumber)*len;
var end =(parseInt(pageNumber)+1)*len;
var newData = newArray.filter((item,index)=>{return index>=start && index<end});
console.log(newData.length);
var str="";
newData.forEach(item=>{
str+=`<li class="list-group-item">
<a href="#/${item.type}/details/${item.id}">
<h4 class="list-group-item-heading">职位需求:${item.job}需求人数:${item.nub}名</h4>
<p class="list-group-item-text">${item.ask}</p>
</a>
</li>`;
});
container.innerHTML = str;
renderPageList({type,pageNumber});
}
function renderPageList(props){
let {type,pageNumber}=props;
var pages = Math.ceil(data[type].length/5);
var subType =data[type][0].type;
var str = "";
[...'.'.repeat(pages)].forEach((item,index)=>{
str+=`<li class="${index==pageNumber?"active":"false"}"><a href="#/${subType}/${index}">${index+1}</a></li>`
});
pagination.innerHTML = str;
};
renderList({
type:"society",
pageNumber:0
});
function renderDetailsPage(props){
let{type,pid} = props;
var detail = data[type].filter((item,index)=>{return item.id==pid})[0];
console.log(detail);
var str = `
<div class="panel panel-default">
<div class="panel-heading">招聘岗位:${detail.job}</div>
<div class="panel-body">
<p>${detail.ask}</p>
<p>招聘人数:${detail.nub}人</p>
<p>发布时间:${detail.data}</p>
</div>
</div> `;
container.innerHTML = str;
pagination.style.display = "none";
}
}
事件
事件机制
- 事件冒泡 js的事件机制执行顺序,由内向外!
- 默认为false, 为true,为捕获执行,由外向内=》由内向外,父控件先捕获,子控件在冒泡
mouseenter 和 mouseleave
- 如果我们用mouseover和mouseout来做事件,当鼠标移到子控件身上会触发父控件的mouseout事件,但我们实际没有移出父控件。这种情况下用mouseenter 和 mouseleave更为合适
事件案例
(function(){
var title = document.querySelector(".title");
var list = document.querySelector(".list");
var menu = document.querySelector(".menu");
menu.addEventListener("click",(e)=>{
e.stopPropagation();
if(getComputedStyle(list)['display'] === "block"){
list.style.display = "none";
}else{
list.style.display = "block";
}
});
document.body.addEventListener("click",()=>{
list.style.display = "none";
});
list.addEventListener("click",(e)=>{
if(e.target.tagName =="LI"){
title.innerText =e.target.innerText;
}
})
})();
事件函数(参数)
a.addEventListener("click",(e)=>{
e.preventDefault();
},{passive:true});
鼠标右键(事件)
document.addEventListener("contextmenu",(e)=>{
e.preventDefault();
},{passive:true});
限制移动盒子(案例)
function css(el,attr){
return parseFloat(getComputedStyle(el)[attr]);
}
var container = document.querySelector(".container");
var box = document.querySelector(".box");
var cw = css(container,"width");
var bw = css(box,"width");
box.addEventListener("mousedown",(e)=>{
var startX = e.clientX;
var startY = e.clientY;
var l = css(box,"left");
var t = css(box,"top");
function move(e){
console.log(css(box,"left"));
var distanceX = e.clientX-startX;
var distanceY = e.clientY-startY;
var endl = l+distanceX;
var endt = t+distanceY;
var maxL = css(container,"width")-css(box,"width");
var maxT = css(container,"height")-css(box,"height");
if(endl<0){
endl = 0;
}
if(endt<0){
endt = 0;
}
if(endt>maxT){
endt = maxT;
}
if(endl>maxL){
endl = maxL;
}
box.style.left = endl+"px";
box.style.top = endt+"px";
}
window.addEventListener("mousemove",move);
window.addEventListener("mouseup",(e)=>{
e.preventDefault();
window.removeEventListener("mousemove",move);
},{once:true});
});
放大镜(案例)
(function(){
var left = document.querySelector("#left");
var mask = document.querySelector("#mask");
var right = document.querySelector("#right");
var img2 = document.querySelector("#img2");
function css(el,attr){
return parseFloat(getComputedStyle(el)[attr]);
}
left.addEventListener("mouseenter",(e)=>{
mask.style.display = "block";
right.style.display = "block";
var scaleW = css(right,"width")/css(img2,"width");
var scaleH = css(right,"height")/css(img2,"height");
mask.style.width = css(left,"width")*scaleW +'px';
mask.style.height = css(left,"height")*scaleH+'px';
left.addEventListener("mousemove",(e)=>{
var lRect = left.getBoundingClientRect();
var l = e.clientX-lRect.left;
var t = e.clientY-lRect.top;
var mask_l =l-css(mask,"width")/2;
var mask_t = t-css(mask,"height")/2;
mask.style.left =mask_l+'px';
mask.style.top = mask_t+'px';
var showScaleWidth = img2.offsetWidth/left.offsetWidth;
var showScaleHeight = img2.offsetHeight/left.offsetHeight;
img2.style.left = -mask_l * showScaleWidth+'px';
img2.style.top = -mask_t * showScaleHeight+'px';
});
})
})();
拖拽综合(案例)
function css(el,attr){
return parseFloat(getComputedStyle(el)[attr]);
}
var box = document.querySelector(".box");
var l=0;
var t=0;
box.addEventListener("mousedown",(e)=>{
clearInterval(timer);
var oldL = css(box,"left");
var odlT = css(box,"top");
var startX = e.clientX;
var startY = e.clientY;
var nBox = document.createElement("div");
nBox.className="newBox";
document.body.append(nBox);
function move(e){
var distanceX = e.clientX-startX;
var distanceY = e.clientY-startY;
l = oldL+distanceX;
t = odlT+distanceY;
nBox.style.left = l+'px';
nBox.style.top = t+'px';
}
document.addEventListener("mousemove",move);
document.addEventListener("mouseup",(e)=>{
document.removeEventListener("mousemove",move);
box.style.left= l+'px';
box.style.top = t+'px';
nBox.remove();
e.preventDefault();
},{once:true})
});
var isLeft = false;
var isTop = false;
var isRight = false;
var isBottom = false;
var run = ()=>{
if(isLeft){
l-=10;
}
if(isTop){
t-=10;
}
if(isBottom){
t+=10;
}
if(isRight){
l+=10
}
box.style.left = l+'px';
box.style.top = t+'px';
};
var timer = setInterval(run,30);
window.addEventListener("keydown",(e)=>{
clearInterval(timer);
timer=setInterval(run,30);
switch(e.keyCode){
case 37:
isLeft = true;
break;
case 38:
isTop = true;
break;
case 39:
isRight = true;
break;
case 40:
isBottom = true;
break;
}
});
window.addEventListener("keyup",(e)=>{
switch(e.keyCode){
case 37:
isLeft = false;
break;
case 38:
isTop = false;
break;
case 39:
isRight = false;
break;
case 40:
isBottom = false;
break;
}
clearInterval(timer);
});
自定义滚动条
let arr = ['河北', '山西', '辽宁', '吉林', '黑龙江', '江苏', '浙江', '安徽', '福建', '江西','山东', '河南', '湖北', '湖南', '广东', '海南', '四川', '贵州', '云南', '陕西', '甘肃', '青海', '台湾',
'北京', '天津', '上海', '重庆'
];
var list = document.querySelector(".list");
var wrap = document.querySelector(".wrap");
var scrollWrap = document.querySelector(".scroll-wrap");
var scrolls = document.querySelector(".scroll");
var newArr = arr.map((item,index)=>{return `<li>${item}</li>`;});
list.innerHTML=newArr.join("");
function css(el,attr,val){
if(arguments.length==3){
el.style[attr] = val+'px';
}else{
return parseFloat(getComputedStyle(el)[attr]);
}
}
var scale = css(wrap,'height')/css(list,'height');
css(scrolls,'height',css(scrollWrap,"height")*scale);
var ld = css(list,'height')-css(wrap,"height");
var sd = css(scrollWrap,'height')-css(scrolls,'height');
scrolls.addEventListener('mousedown',(e)=>{
var t = css(scrolls,'top');
var startY = e.clientY;
let move =(e)=>{
var endY = e.clientY-startY;
var distanceY = endY+t;
distanceY = Math.max(0,distanceY);
distanceY = Math.min(sd,distanceY);
scrolls.style.top = distanceY+'px';
list.style.top = -(distanceY/sd*ld)+'px';
e.preventDefault();
}
document.addEventListener("mousemove",move);
document.addEventListener("mouseup",(e)=>{
document.removeEventListener("mousemove",move);
e.preventDefault();
},{once:true});
});
function myScroll(el,upFn,downFn){
el.addEventListener("mousewheel",function(e){
if(e.wheelDelta>0){
console.log('向上');
upFn&&upFn.call(el);
}else{
console.log('向下');
downFn&&downFn.call(el);
}
e.preventDefault();
});
el.addEventListener('DOMMouseScroll',function(e){
if(e.detail>0){
console.log('向下');
downFn&&downFn.call(el);
}else{
console.log('向上');
upFn&&upFn.call(el);
}
e.preventDefault();
});
}
myScroll(wrap,function(){
var t = css(scrolls,'top');
t-=10;
t = Math.max(0,t);
scrolls.style.top =t+'px';
list.style.top = -(ld*t/sd)+'px';
},function(){
var t = css(scrolls,'top');
t+=10;
t = Math.min(sd,t);
scrolls.style.top =t+'px';
list.style.top = -ld*(t/sd)+'px';
});
画方框(案例)
function css(el,attr,val){
if(attr==='backgroundColor'){
el.style[attr]=val;
}else if(arguments.length==3){
el.style[attr]=val+'px';
}else{
return parseFloat(getComputedStyle(el)[attr]);
}
}
window.addEventListener("mousedown",(e)=>{
var startX = e.clientX;
var startY = e.clientY;
var box = document.createElement("div");
box.classList.add('squart');
document.body.append(box);
let move = (e)=>{
var endX = e.clientX;
var endY = e.clientY;
var width = Math.abs(endX-startX);
var height = Math.abs(endY-startY);
var l = Math.min(startX,endX);
var t = Math.min(startY,endY);
css(box,'width',width);
css(box,'height',height);
css(box,'left',l);
css(box,'top',t);
}
window.addEventListener('mousemove',move);
window.addEventListener('mouseup',(e)=>{
window.removeEventListener('mousemove',move);
e.preventDefault();
},{once:true});
e.preventDefault();
});
正方形碰撞检测
var box1 = document.querySelector("div");
var box2 = document.querySelector(".box2");
function css(el,attr,val){
if(attr==='backgroundColor'){
el.style[attr]=val;
}else if(arguments.length==3){
el.style[attr]=val+'px';
}else{
return parseFloat(getComputedStyle(el)[attr]);
}
}
box1.addEventListener("mousedown",function(e){
var startX = e.clientX;
var startY = e.clientY;
var l = css(box1,'left');
var t = css(box1,'top');
function move(e){
var disX = e.clientX-startX+l;
var disY = e.clientY-startY+t;
css(box1,'left',disX);
css(box1,'top',disY);
var flag = isCollision(box1,box2);
if(flag){
css(box1,'backgroundColor','yellow');
}else{
css(box1,'backgroundColor','pink');
}
}
document.addEventListener("mousemove",move);
document.addEventListener("mouseup",function(e){
document.removeEventListener('mousemove',move);
e.preventDefault();
},{once:true});
e.preventDefault();
});
function isCollision(el1,el2){
var el1Rect = el1.getBoundingClientRect();
var el1T = el1Rect.top;
var el1L = el1Rect.left;
var el1B = el1Rect.bottom;
var el1R = el1Rect.right;
var el2Rect = el2.getBoundingClientRect();
var el2T = el2Rect.top;
var el2L = el2Rect.left;
var el2B = el2Rect.bottom;
var el2R = el2Rect.right;
if(el1R>el2L && el1L<el2R && el1T<el2B && el1B>el2T){
return true;
}
return false;
}
选框(案例)
function css(el,attr,val){
if(attr==='backgroundColor'){
el.style[attr]=val;
}else if(arguments.length==3){
el.style[attr]=val+'px';
}else{
return parseFloat(getComputedStyle(el)[attr]);
}
}
[...'.'.repeat(15)].forEach((item,index)=>{
document.body.innerHTML+=`<div class="div">${index+1}</div>`;
});
var box2 = document.querySelector(".box2");
var arr=[];
var list = document.querySelectorAll(".div");
list = Array.from(list);
document.addEventListener("mousedown",(e)=>{
var startX = e.clientX;
var startY = e.clientY;
var box = document.createElement("div");
box.classList.add("box");
document.body.append(box);
let move =(e)=>{
var endX = e.clientX;
var endY = e.clientY;
var width = Math.abs(endX-startX);
var height = Math.abs(endY-startY);
var l = Math.min(endX,startX);
var t = Math.min(endY,startY);
css(box,'width',width);
css(box,'height',height);
css(box,'top',t);
css(box,'left',l);
arr = list.filter((item,index)=>{
if(isCollision(box,item)){
item.classList.add("active");
return item;
};
});
e.preventDefault();
}
document.addEventListener("mousemove",move);
document.addEventListener("mouseup",(e)=>{
document.removeEventListener('mousemove',move);
box.remove();
arr.forEach(item=>{
box2.append(item);
item.classList.remove("active");
});
e.preventDefault();
},{once:true});
e.preventDefault();
});
function isCollision(el1,el2){
var el1Rect = el1.getBoundingClientRect();
var el1T = el1Rect.top;
var el1L = el1Rect.left;
var el1B = el1Rect.bottom;
var el1R = el1Rect.right;
var el2Rect = el2.getBoundingClientRect();
var el2T = el2Rect.top;
var el2L = el2Rect.left;
var el2B = el2Rect.bottom;
var el2R = el2Rect.right;
if(el1R>el2L && el1L<el2R && el1T<el2B && el1B>el2T){
return true;
}
return false;
}
圆形碰撞
var box1 = document.querySelector(".box1");
var circle = document.querySelector('#circle');
function css(el,attr,val){
if(arguments.length==3){
el.style[attr] =val+'px';
}else{
return parseFloat(getComputedStyle(el)[attr]);
}
}
circle.addEventListener("mousedown",(e)=>{
var startX = e.clientX;
var startY = e.clientY;
var l = css(circle,'left');
var t = css(circle,'top');
let move = (e)=>{
var distanceX = e.clientX-startX+l;
var distanceY = e.clientY-startY+t;
css(circle,'left',distanceX);
css(circle,'top',distanceY);
var flag = circleCollision(circle,box1);
if(flag){
circle.style.backgroundColor = '#999';
}else{
circle.style.backgroundColor = 'pink';
}
e.preventDefault();
};
document.addEventListener("mousemove",move);
document.addEventListener("mouseup",(e)=>{
document.removeEventListener('mousemove',move);
e.preventDefault();
},{once:true});
e.preventDefault();
});
function circleCollision(el1,el2){
var el1W = el1.offsetWidth;
var el1H = el1.offsetHeight;
var el1R = el1.getBoundingClientRect();
var el1T = el1R.top;
var el1L = el1R.left;
var el1Center={
x:el1L+el1W/2,
y:el1T+el1H/2
}
var el2W = el2.offsetWidth;
var el2H = el2.offsetHeight;
var el2R = el2.getBoundingClientRect();
var el2T = el2R.top;
var el2L = el2R.left;
var el2Center={
x:el2L+el2W/2,
y:el2T+el2H/2
}
return Math.sqrt(Math.pow((el2Center.x-el1Center.x),2)+ Math.pow((el2Center.y-el1Center.y),2))<=(el1W/2+el2W/2)
}
百度网盘(案例)
定义公共方法
var topId = 0;
var nowId = 0;
var topPid = -1;
function getItemById(id){
return data.filter(item=>item.id==id)[0];
}
function getChildrenByPid(id){
return data.filter(item => item.pid==id);
}
function getParent(pid){
var parent={};
data.forEach(item => {
if(item.id==pid){
parent = item;
}
});
return parent;
}
function getAllParent(pid){
var arr=[];
while(pid>topPid){
var parent = getParent(pid);
pid = parent.pid;
arr.unshift(parent);
}
return arr;
}
右侧路径渲染
function renderBreadNav(){
var str=``;
var currentItem = getItemById(nowId);
var arr = getAllParent(currentItem.pid);
arr.forEach(item=>{
str+=`<a data-id="${item.id}">${item.title}</a>`;
});
str+=`<span>${currentItem.title}</span>`
return str;
}
右侧文件夹区域渲染
function renderFolders(){
var inner=``;
var childrenList = getChildrenByPid(nowId);
childrenList.forEach(item=>{
inner+=` <li class="folder-item" data-id="${item.id}">
<img src="img/folder-b.png" alt="">
<span class="folder-name">${item.title}</span>
<input type="text" class="editor" value="${item.title}">
<label class="checked">
<input type="checkbox" />
<span class="iconfont icon-checkbox-checked"></span>
</label>
</li>`;
});
return inner;
}
左侧树状图渲染
function renderTreeMenu(pid,level){
var inner = "";
var children = getChildrenByPid(pid);
var currentItem = getItemById(nowId);
var allParent = getAllParent(currentItem.pid);
allParent.push(currentItem);
inner =` <ul>
${children.map(item =>{
var childrenItem = getChildrenByPid(item.id);
// 当前id递归中的子集li的class='open'
return item =
`<li class="${allParent.includes(item)?"open":""}">
<p style="padding-left:${40+level*20}px" class="${childrenItem.length?"has-child":""} ${item.id==nowId?"active":""}" data-id=${item.id}><span>${item.title}</span></p>
${childrenItem.length? renderTreeMenu(item.id,level+1):""}
</li>`;
}).join("")}
</ul>`;
return inner;
}
界面渲染(基础篇)
menuList.addEventListener("click",function(e){
var item = e.target.tagName=='SPAN'? e.target.parentNode:e.target;
if(item.tagName=="P"){
nowId = item.dataset.id;
render();
}
});
breadNav.addEventListener("click",(e)=>{
if(e.target.tagName=='A'){
nowId = e.target.dataset.id;
render();
}
});
folders.addEventListener("click",(e)=>{
console.log(e.target);
var item = e.target.tagName=="IMG"?e.target.parentNode:e.target;
if(item.tagName=='LI'){
nowId = item.dataset.id;
render();
}
});
ES6
变量
for(let i = 0;i<4;i++){
setTimeout(()=>{
console.log(i);
},100)
}
for(var i = 0;i<4;i++){
setTimeout(()=>{
console.log(i);
},100)
}
常量
const varabel=12;
console.log(varabel);
解构
数组解构
let arr =[1,2,3];
var [a,b,c]= arr;
字符串解构
let str = "wangao";
let [a,b,c] = str;
console.log(a);
扩展运算符
[...'.'.repeat(3)].forEach(item=>console.log(item));
展开运算符
let arr = [...nodeList];
let arr= [1,2,3,4];
let [a,b,...c] = arr;
console.log(c);
合并对象
let obj={
a:12,
b:14
};
let obj2 = {
c:13,
d:14
};
let obj4={...obj,...obj2};
console.log(obj4);
set集合
let arr = [1,1,2,2,3,3];
let set = new Set(arr);
var length = set.size;
console.log(length);
set.add(8);
set.delete(3);
var flag = set.has(2);
console.log(flag);
set.clear();
console.log(set);
map集合
let arr =[[1,2],[3,4]];
let map = new Map(arr);
map.forEach((key,value)=>{
console.log(key+'=>'+value);
});
map.set(5,6);
map.set(5,7);
let value =map.get(3);
console.log(value);
let flag = map.has(3);
console.log(flag);
map.delete(1);
console.log(map);
map.clear();
箭头函数
let fn = (...args )=>console.log(args);
let result = fn(3);
console.log(result);
let fun = ()=>console.log(this);
fun();
document.addEventListener("click",function(){
let fun = ()=>console.log(this);
fun();
});
数组新增方法
Array.from()
let arr = [1,2,3,4];
arr2 = Array.from(arr);
arr2[1]=10;
console.log(arr);
Aarray.of()
let arr3 = Array.of(1,4,8,10);
console.log(arr3);
find()和findIndex()
var num =arr.find(item=>{
console.log(item);
return item>5;
});
console.log(num);
includes()
let arr = [1,3,5,7,9];
let flag = arr.includes(3)
console.log(flag);
flat()
let arr = [[1,3],[[1,2,[3,4,5]]],[5,7,9]];
var arr3 = arr.flat(Infinity);
console.log(arr3);
flatMap()
let arr = [[1,2],[3,4,5],[6,7,9]];
var arr2 = arr.flatMap((item)=>{
var item2 = item.filter(ele=>ele>4);
return item2;
});
console.log(arr2);
新增字符串方法
let str = "helloworld";
let flag =str.endsWith('d',10);
console.log(flag);
let flag2 = str.startsWith("hel");
console.log(flag2);
let result = str.includes("hel");
console.log(result);
".".repeat(10);
object
let obj1= {
a:123,
b:456
}
let obj2 ={
c:789,
d:1012,
}
let obj3 = Object.assign({},obj1,obj2);
console.log(obj3);
let flag = Object.is(obj1,obj2);
console.log(flag);
对象的简洁
let a =10;
let n ='d';
let obj ={
a,
[n]:13,
add(c,d){
return c+d;
}
}
Ajax
封装Ajax函数
let ajaxNet=(obj)=>{
let {type,url,args,success} = obj;
let http = new XMLHttpRequest();
type = type ||"GET";
switch(type.toLowerCase()){
case 'get':
http.open(type,url+'?'+obj2String(args),true);
http.addEventListener('load',()=>{
if(http.readyState=='4' && http.status==200){
success && success(http.responseText);
}
});
http.send();
break;
case 'post':
http.open(type,url,true);
http.addEventListener('load',()=>{
if(http.readyState=='4'&& http.status==200){
success && success(http.responseText);
}
});
http.setRequestHeader("Content-type",'application/x-www-form-urlencoded');
http.send(obj2String(args));
break;
}
}
Ajax案例
function renderUl(data,nowpage){
let newArr =data.map((item)=>{
return`<li>${item.title}</li>`;
});
return newArr.join("");
}
function renderOl(data,nowPage=1){
let newOl = data.map((item,index) => {
return`<li class="${nowPage==index+1?"active":""}">${index+1}</li>`;
});
return newOl.join("");
}
function obj2String(obj){
let arr = [];
for (let key in obj) {
arr.push(key+'='+obj[key]);
}
return arr.join('&');
}
let ajaxNet=(obj)=>{
let {type,url,args,success} = obj;
let http = new XMLHttpRequest();
type = type ||"GET";
switch(type.toLowerCase()){
case 'get':
http.open(type,url+'?'+obj2String(args),true);
http.addEventListener('load',()=>{
if(http.readyState=='4' && http.status==200){
success && success(http.responseText);
}
});
http.send();
break;
case 'post':
http.open(type,url,true);
http.addEventListener('load',()=>{
if(http.readyState=='4'&& http.status==200){
success && success(http.responseText);
}
});
http.setRequestHeader("Content-type",'application/x-www-form-urlencoded');
http.send(obj2String(args));
break;
}
}
let ul = document.querySelector("ul");
let ol = document.querySelector("ol");
ajaxNet({
url:'http://localhost:8787/getNews',
args:{
page:1,
count:4
},
success:(res)=>{
let json = JSON.parse(res);
let{data,totalPage} = json;
ul.innerHTML= renderUl(data);
console.log(json);
console.log([...'.'.repeat(totalPage)]);
ol.innerHTML = renderOl([...'.'.repeat(totalPage)]);
}
});
ol.addEventListener("click",(e)=>{
if(e.target.tagName=="LI"){
let page = e.target.innerHTML;
ajaxNet({
url:'http://localhost:8787/getNews',
args:{
page,
count:4
},
success:(res)=>{
let json = JSON.parse(res);
let{data,totalPage} = json;
ul.innerHTML= renderUl(data);
console.log(json);
console.log([...'.'.repeat(totalPage)]);
ol.innerHTML = renderOl([...'.'.repeat(totalPage)],page);
}
});
}
});
tudo(案例)
{
let data = [
{
id:0,
title:'起床',
todo:false,
edit:false
},{
id:1,
title:'吃饭',
todo:false,
edit:false
},{
id:2,
title:'睡觉',
todo:true,
edit:false
},{
id:3,
title:'打豆豆',
todo:false,
edit:false
}
];
let content= document.querySelector(".content");
let undone = (arr)=>{
return arr.reduce((el1,el2)=>{
return el2.todo?el1:el1+1;
},0);
}
let findEleById =(id)=>{
return data.filter( item =>item.id==id)[0];
}
let renderDone = ()=>{
return`<span class="todo-clear">
<a href="#">Clear <span>${data.length-undone(data)}</span>已完成事项</a>
</span>`;
}
let renderUndone = ()=>{
return `<span class="todo-count">
<span class="number">${undone(data)}</span>
<span class="word">项待完成</span>
</span>`;
}
let toBlur = (e)=>{
let {target} = e;
let {id} = target.parentNode.parentNode.dataset;
data.forEach(item=>{
if(target.value.trim()){
if(item.id == id){
item.title = target.value;
item.edit = false;
}
}
});
render(data);
console.log(data);
e.stopPropagation();
}
let undoneLe = undone(data);
let render = (arr)=>{
content.innerHTML =
`<ul id="todo-list">
${arr.length?renderLi(arr):""}
</ul>
<div id="todo-stats">
${undoneLe?renderUndone():""}
${data.length-undoneLe?renderDone():""}
</div>`;
let list = document.querySelectorAll(".edit input");
list.forEach((item,index)=>{
if(data[index].edit){
item.select();
}
item.addEventListener("blur",toBlur);
});
}
let renderLi = (arr)=>{
return arr.map((item) => {
return item = `<li class="${item.edit?"editing":""}">
<div class="todo ${item.todo?'done':''}" data-id="${item.id}">
<div class="display">
<input class="check" type="checkbox"${item.todo?'checked':""}>
<div class="todo-content">${item.title}</div>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text" value="${item.title}">
</div>
</div>
</li>`;
}).join("");
}
render(data);
content.addEventListener("change",({target})=>{
if(target.className!="check"){
return;
}
if(target.tagName=="INPUT"){
let parent =target.parentNode.parentNode;
let pid = parent.dataset.id;
let item = findEleById(pid);
item.todo = target.checked;
render(data);
}
});
let newTodo = document.querySelector("#new-todo");
window.addEventListener("keydown",({keyCode})=>{
if(keyCode==13){
if(newTodo.value.trim()){
let text = newTodo.value;
data.push({
id: Date.now(),
title:text,
todo:false,
edit:false
});
render(data);
newTodo.value="";
}else{
alert("请输入计划!!!")
}
}
});
content.addEventListener("click",({target})=>{
if(target.className=="todo-destroy"){
let {id} = target.parentNode.parentNode.dataset;
data = data.filter(item=>item.id!=id);
render(data);
}
});
content.addEventListener("click",(e)=>{
let {target} = e;
if(target.tagName=="A"||target.parentNode.tagName=="A"){
data = data.filter(item=>item.todo==false);
render(data);
e.preventDefault();
}
});
content.addEventListener("dblclick",(e)=>{
let {target} = e;
if(target.className=="todo-content"){
let {id} = target.parentNode.parentNode.dataset;
data.forEach(item=>{
if(item.id==id){
item.edit= true;
}
});
render(data);
}
});
}