task31 进阶:把轮播改成无缝轮播吧

2019-05-17  本文已影响0人  vivienYang2019

1. 无缝的轮播怎么做

什么是无缝轮播?


有缝轮播.png

从第一张到倒数第二张图片还好,但是从最后一张图片到第一张图片就有问题了,并没有从最后一张图片直接切换到第一张图片,而是经过了中间的图片慢慢过渡到第一张图片(第一张图片到最后一张图片也同理),这显然不是预期的效果。问题既然已经发现了,就要去解决它,那么如何才能达到从最后一张图片直接切换到第一张图片(或第一张到最后一张),也就是无缝的效果,答案很简单,我们需要多一张图片(这张图片和第一张图片是相同的)放在图片列表的最后!为什么需要这样一张图片,请往下看。
我们在上面已经清楚要解决的就是首尾图片间的切换问题,所以在引入多一张图片之后,可以让轮播从倒数第二张图片(在没有引入图片之前的最后一张图片)切换到最后一张图片(新引入的图片)的动画完成之后,再瞬间跳转到第一张图片,请看下图(我把外面容器的overflow:hidden去掉了以便大家理解):


无缝轮播原理.png

参考文档

开始实现


Emmet.png
img[src="./$.png"][width=400[height=300][alert=图片]*5

Emmet 语法


image.png
image.png
box-sizing:border-box;//???什么意思

box-sizing

box-sizing.png 3s6s.png
9s12s.png

on('transitionend') 监听动画结束,让img回到可视window的右边
one('transitionend') 只监听最近的一次,监听执行完一次后就把这个监听器给删了
具体分析,拿3张图片测试要怎么移动,然后进行分析和抽象。
进行分析和抽象,图片有3种状态:current,leave,enter(状态机的概念)

有3种状态,对应可以写3个类
css定义这3个类的位置等
js负责改变每个img的类↓


imgCss.png imgJs.png
$('.images > img:nth-child(1)').addClass('current')
$('.images > img:nth-child(2)').addClass('enter')
$('.images > img:nth-child(3)').addClass('enter')
let n = 1
setInterval(()=>{
  $(`.images > img:nth-child(${x(n)})`).removeClass('current').addClass('leave')
    .one('transitionend', (e)=>{
      $(e.currentTarget).removeClass('leave').addClass('enter')
    })
  $(`.images > img:nth-child(${x(n+1)})`).removeClass('enter').addClass('current')
  n += 1
},3000)


function x(n){
  if(n>3){
    n = n%3
    if (n===0){
      n =3
    }
  } // n = 1 2 3
  return n
}
let n
初始化()
setInterval(()=>{
  makeLeave(getImage(n))
    .one('transitionend', (e)=>{
      makeEnter($(e.currentTarget))
    })
  makeCurrent(getImage(n+1))
  n += 1
},3000)

// 下面可以不看
function getImage(n){
  return $(`.images > img:nth-child(${x(n)})`)
}
function x(n){
  if(n>3){
    n = n%3
    if (n===0){
      n =3
    }
  } // n = 1 2 3
  return n
}
function 初始化(){
  n = 1
  $(`.images > img:nth-child(${n})`).addClass('current')
    .siblings().addClass('enter')
}
function makeCurrent($node){
  return $node.removeClass('enter leave').addClass('current')
}
function makeLeave($node){
  return $node.removeClass('enter current').addClass('leave')
}
function makeEnter($node){
  return $node.removeClass('leave current').addClass('enter')
}

一个注意事项:current的z-index要比其他的大,因为从leave改变位置到enter位置会从current的区域经过

.carouselWrapper .carouselBox > img.current{
  transform: translateX(0);
  z-index: 2;
}

2. DOM Events 知识

事件的历史.png
domLevel的版本
dom level 2中的事件
image.png
https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html image.png
event flow, event capture, event bubbling(事件冒泡), mouse event, key events这些概念都是dom level 2中提出的,dom level3基本上没做修改,dom level 4还在草案阶段

dom level 1的知识

一道题,哪一个可以打印出hi?


image.png

答案:bcx
为什么bc是对的?


image.png
为什么x是对的?
image.png

在html中的onclick要加括号'()'
在js中的onclick不要加括号'()'

dom level2的知识

dom level1中的onclick和dom level 2中的addEventListener区别

——会打印出1和2,而且一定是先打印1再打印2,有顺序的


removeEventListener.png

——只会打印出2,因为f1和f3在add后被remove掉了,xxx的click事件只剩f2监听了

事件模型

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>事件模型</title>
  <style>
    div{
      padding: 30px;
      border: 1px solid salmon;
    }
  </style>
</head>
<body>
  <div id="grand1">
    爷爷
    <div id="parent1">
      爸爸
      <div id="child1">
        儿子
      </div>
    </div>
  </div>
  <script>
    // 1 当我点击儿子的时候,我是否点击了父亲和爷爷
    // yes

    // 2 当我点击儿子的时候,三个函数是否调用
    grand1.addEventListener('click',function fn1(){
      console.log('爷爷')
    })
    parent1.addEventListener('click',function fn2(){
      console.log('爸爸')
    })
    child1.addEventListener('click',function fn3(){
      console.log('儿子冒泡')
    },false)
    child1.addEventListener('click',function fn3(){
      console.log('儿子捕获')
    },true)
    // yes

    // 3 请问fn1,fn2,fn3的执行顺序
    // 1-2-3 or 3-2-1?

    // W3C 都可以
    // falsy值: false, 0, NaN, '', null, undefined
    // addEventListener不传第三个参数/传false 儿子-爸爸-爷爷
    // addEventListener第三个参数传true 爷爷-爸爸-儿子

    // 总结事件模型
    // true的走左边的队列(从上到下阶段,捕获阶段),
    // false或不传的走右边的队列(从下到上阶段,冒泡阶段)
    // 先捕获,后冒泡
    // 最后一个结点是先捕获还是先冒泡??
    // 写的顺序 ???特例!!!就是写在点的元素本身上的event listener,不是按照先捕获后冒泡的顺序执行,而是按照写的顺序来执行
  </script>
</body>
</html>
上一篇下一篇

猜你喜欢

热点阅读