css和html代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>document</title>
<style type="text/css">
*{
padding:0;
margin:0
}
img{
vertical-align:middle;
}
#box{
width:1250px;
height:360px;
margin:100px auto;
font-family:'Microsoft yahei';
}
#box ul li{
list-style:none;
float:left;
margin:0 10px;
position:relative;
overflow:hidden;
}
#box ul li a{
width:230px;
height:360px;
position:absolute;
left: 0;
top: 360px;
background:url("images/new-bg.png");
text-decoration:none;
}
#box ul li a p{
color:#fff;
font-size:14px;
text-align:center;
}
#box ul li a p.p1{
padding-top:160px;
}
</style>
</head>
<body>
<div id='box'>
<ul id="list">
<li>
<img src='images/1.jpg'/>
<a href='#'>
<p class='p1'>秋冬上新 领券立减20</p>
<p>点击进入</p>
</a>
</li>
<li>
<img src='images/2.jpg'/>
<a href='#'>
<p class='p1'>钜惠满138减15</p>
<p>点击进入</p>
</a>
</li>
<li>
<img src='images/3.jpg'/>
<a href='#'>
<p class='p1'>冬装尖品 强势登陆</p>
<p>点击进入</p>
</a>
</li>
<li>
<img src='images/4.jpg'/>
<a href='#'>
<p class='p1'>十一国庆除出游季</p>
<p>购新衣才够【型】</p>
</a>
</li>
<li>
<img src='images/5.jpg'/>
<a href='#'>
<p class='p1'>秋上新</p>
<p>点击进入</p>
</a>
</li>
</ul>
</div>
</html>
js实现思路
- 什么是js语言?js语言是基于原型的动态解释性语言,其基本操作分为css样式操作和dom节点操作。基于原型:存在对象、声明,就有原型。动态解释性:语言可以在任何环境下运行,没有限制。js不仅仅能够用于特效,插件框架开发、机器学习、数据分析、人工智能,都可以通过js实现
- 实现简单的鼠标划入操作思路:
(1)获取dom元素
(2)考虑两个事件:mouseenter、mouseleave,注册事件实现移入移出操作。
元素获取
- 获取元素有三种方法:原生js方法(get方法)、$方法、query方法。其中get方法由js原生提供,获取速度最优,$和query方法都是由get系列封装而成。不同在于$是jQuery提供,性能最差;query由html5提供,而且经过了优化,获取速度仅次于get原生方法。
- 在这里我们使用原生js方法实现:
<script>
var oBox=document.getElementById('box');
var aLi=oBox.getElementsByTagName('li');
</script>
使用for循环进行事件注册
- for循环可以给每个li绑定一个事件,从而实现了事件注册
//使用for循环进行事件注册
for(var i=0,aLiLen=aLi.length;i<aLiLen;i++){
//这样较for(var i=0;i<aLi.length;i++)性能更优,因为不必每次计算aLi.length
aLi[i].onmouseenter=function(){
console.log(1);
}
}
- 首先注意的是,由于box有多个li子元素,所以aLi是一个伪数组。即具有数组的属性(下标、长度),而没有数组的方法(foreach、push、sort)。其次注意,enter、leave、over、out的区别:enter、leave在不冒泡条件下进行,由外到里;out、over在冒泡条件下进行,由里到外。冒泡:事件的执行顺序由子集向父集发出,即由里到外。
- 但是,一般情况下,我们不采用for循环进行事件注册。原因:
(1)当事件绑定特别多时,容易造成事件覆盖。即只执行后边的事件,前边事件不执行
(2)性能特别差,进行循环遍历为每个li绑定事件;但是鼠标不进入的话,就不会触发事件。这样会造成浏览器加载资源的浪费(当一万个事件时...)
因此,我们通常采用事件代理(事件委托)实现事件注册。事件代理基于事件监听实现,不必给每个li进行绑定
基于事件监听的事件代理
- 在实现特效时,首先要学会观察,不要着急一上来就干。思考此特效的实现过程:鼠标移入-》获取鼠标坐标-》获取元素宽高,进而得到元素距离浏览器各边的大小-》计算鼠标坐标和四条边的距离-》哪边的绝对值最小,就说明从哪边移入(移入瞬间,差值接近0)
- 若有两个的绝对值是相等的,我们执行哪个事件呢?当然是后边的,因为事件覆盖嘛。
- 在计算得到四个绝对值中的最小值后,我们加以val的判断,就能得到鼠标是从哪个方向移入或者移出了。但是后边的动画怎么实现呢?我们分两步完成,假设鼠标从上边移入,我们先瞬间令背景图移动到最上边,然后缓慢的移下来。这个动画的实现过程我们使用链式操作实现。链式操作的原理很简单,就是每次方法执行完后返回this对象,这样后面的方法就可以继续在this环境下执行。
//获取元素
var oBox=document.getElementById('box');
var aLi=oBox.getElementsByTagName('li');
// //使用for循环进行事件注册
// for(var i=0,aLiLen=aLi.length;i<aLiLen;i++){
// //这样较for(var i=0;i<aLi.length;i++)性能更优,因为不必每次计算aLi.length
// aLi[i].onmouseenter=function(){
// console.log(1);
// }
// }
//基于事件监听的事件代理
oBox.addEventListener('mouseenter',function(e){
//检验和调试
//最后的false\true参数表示是否冒泡。默认为false,表示冒泡阶段
//console.log(1);//参数为true一次打印多个1;false一次打印一个1
//console.log(e);//true一次会触发多个事件,是我们想要的
//console.log(e.target.tagName);//确认真的没错
//代码优化
var target=e.target;
if(target.tagName.toLowerCase()=='li'){
//得到鼠标移入li瞬间的鼠标坐标
var x=e.clientX;
var y=e.clientY;
//得到li四条边距离浏览器左部和顶部的距离
var oT=target.offsetTop;
var oB=oT+target.offsetHeight;
var oL=target.offsetLeft;
var oR=oL+target.offsetWidth;
//计算鼠标坐标和四条边的距离,取绝对值
var diffT=Math.abs(y-oT);
var diffB=Math.abs(y-oB);
var diffL=Math.abs(x-oL);
var diffR=Math.abs(x-oR);
//取最小值为方向
var direction=Math.min(diffT,diffB,diffL,diffR);
//判断是鼠标移入还是移出
var val=e.type.toLowerCase();
//console.log(diffT,diffB,diffL,diffR);//检验一下
//switch语句选择方向
switch(direction){
//方法是一样的,只是方向不一样。我们只要封装函数即可
case diffT:
moveTo('top',val,target);
//console.log('从上移入');
break;
case diffB:
moveTo('bottom',val,target);
//console.log('从下移入');
break;
case diffL:
moveTo('left',val,target);
//console.log('从左移入');
break;
case diffR:
moveTo('right',val,target);
//console.log('从右移入');
break;
}
}
},true);
function moveTo(aspect,mouse,aim){
//aspect表示鼠标移入方向;
// mouse表示鼠标
// aim表示操作的对象
// from瞬间移动的距离
// to后来的距离,默认为0
if(mouse=='mouseenter'){
aim.children[1].css(aspect).enter(aspect);
}else{
}
}
Node.prototype.css=function(aspect){
if(aspect=='top'){
this.style[aspect]=-360+'px';
this.style.left=0;
}
return this;
}
Node.prototype.enter=function(aspect){
setTimeout(function(){
this.style[aspect]=0+'px';
this.style.transition='.3s';
}.bind(this),0)
//this在此处默认指向windows(因为settimeout是windows调用的函数),我们使用bind强制事件绑定,使其指向当前对象
// this.style[aspect]=to+'px';
// this.style.transition='.3s';
//若不使用setTimeOut伪异步操作的话,会发生事件覆盖,即前边的css被后边的enter覆盖
return this;
}
问题
浏览器打开后,特效有时从上边出来,有时从下边出来,不知道为啥
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。