Animation(下)

Animation

案例:利用封装的代码,书写轮播图
//(一) 定时切换图片
//1.初始化索引
var index  = 0;
let timer = setInterval(function(){
	//2.设置定时器让索引递增,改变图片的top值为,为-图片大小*索引
    index++;
    //3.当索引大于等于图片数量时,将索引重置为0
    if(index >= ul.children.length){
        index = 0;
    }
    ul.style.top = -320 * index +'px';
}, 1000)
//(二) 利用封装animate实现动画
//1.初始化索引
var index  = 0;
let timer = setInterval(autoPlay, 1000)
lbt.onmouseenter = ()=>{
	clearInterval(timer);
}
lbt.onmouseleave = ()=>{
	timer = setInterval(autoPlay,1000);
}
function autoPlay(){
    //2.设置定时器让索引递增,将-图片大小*索引作为每次动画的目标值
    index++;
    //3.当索引大于等于图片数量时,将索引重置为0
    if(index >= ul.children.length){
        index = 0;
    }
    var target = -320 * index;
    animate(ul,"top",target);
}

完善animate封装

function animate(ele,opt,callback){
	// 2.记录动画的数量,遍历时加1。执行后减1。动画结束后执行回调函数
	let timerLen = 0;
    // 1.遍历opt,获取所有attr和target
    for(var attr in opt){
        timerLen++;
        createTimer(attr);
    }
    function createTimer(attr){
        let target = opt[attr];
        // 3.1设置定时器的名字与attr关联
        let timerName = attr + 'timer';
        // 3.2清除定时器,避免多个定时器用作于一个效果
		clearInterval(ele[timerName]);
		ele[timerName] = setInterval(()=>{
            let current = getCss(ele,attr);//100px,45deg,0.5(string)
            let unit = current.match(/[a-z]+$/i);//[0:px,index:6,input:current],null
            unit = unit ? unit[0] : '';
            current = parseFloat(current);
            let speed = (target-current)/10;
		   speed = speed>0 ? Math.ceil(speed) : Math.floor(speed);//1,-1
		   current += speed;
		   if(current === target ){
				clearInterval(ele[timerName]);
				// 每一个动画完成数量减一
				timerLen--;
				// 动画结束后执行回掉函数
                if(timerLen === 0){
                    typeof callback==='function' && callback();
                }
             }
             ele.style[attr] = current + unit;
		},30);
	}
}			
案例:实现一个动画结束后再改变字体颜色之类的效果
案例:链式动画
案例:水平无缝滚动
2)无缝滚动
    * 把第一张复制到最后
ul.appendChild(ul.children[0].cloneNode(true));
1)获取ul子元素的长度设置ul宽度,达到水平排列的效果
let len = ul.children.length;
let imgWidth;
ul.querySelector('img').onload = function(){
	imgWidth = this.offsetWidth;
	ul.style.width = imgWidth*len + 'px';
}
3)水平轮播效果
let timer = setInterval(autoPlay,3000);
function autoPlay(){
    index++;
    show();
}
function show(){
	//当show()执行到最后一张图片len-1时,代表索引为0的图片。
	//再次进入autofocus,index++后,其实要执行的下一次索引应该为1。所以要把当前位置改成0.
    if(index >= len){//0,1,2,3,4
        ul.style.left = 0;
        index = 1;
    }
    animate(ul,{left:-imgWidth*index});
    // 遍历所有页码,取消高亮,给点点被点击的页码添加高亮
    for(let i=0;i<len-1;i++){//0,1,2,3
        page.children[i].className = '';
    }
    if(index === len - 1){
        page.children[0].className = 'active';
    }else{
        page.children[index].className = 'active'
    }
}
4)移入移出,清除轮播效果
focus.onmouseenter = ()=>{clearInterval(timer);}
focus.onmouseleave = ()=>{timer = setInterval(autoPlay,3000);}
5)添加分页效果,点击分页切换
let page = setPage();
function setPage(){
    let page = document.createElement('div');
    page.className = 'page';
    for(let i=1;i<len;i++){
        let span = document.createElement('span');
        span.innerText = i;
        if(i===1){
            span.classList.add('active');
        }
        page.appendChild(span);
    }
    focus.appendChild(page);
    return page;
}
focus.onclick = e=>{
    if(e.target.parentNode.className === 'page'){
        index = e.target.innerText-1;
        show();
    }
}
6)添加前后按钮,实现上一张、下一张的效果(待完成...)

案例:瀑布流

(1)获取图片宽,计算当前容器能容纳多少列
//	* 列数 = parseInt(容器宽度/图片宽度)
let imgWidth = items[0].offsetWidth;
let col = Math.floor((window.innerWidth-17)/imgWidth);//10.6
//2)计算水平间隔
//    * 间隔 = (容器宽度-17)%图片宽度/(列数+1),17为滚动条宽度
let gap = ((window.innerWidth-17)%imgWidth)/(col+1);
// 3)创建一个数组pos
//	  * 用来保存第一行每列图片左上角坐标(left,top)
let pos = [];
for(let i=0;i<col;i++){
    pos.push({
        left:(i+1)*gap + i*imgWidth,
        top:gap
    })
}
// 4)遍历所有图片,往容器里添加图片
    //  当前图片加载时,遍历数组pos,查找最小top值及对应的索引,给当前元素设置样式
    //  然后更新当前索引,即minIdx的top值,top = 容器高度(由图片高度跟上一次gap撑开) + gap 
for(let i=0;i<items.length;i++){
    let currentImg = items[i].querySelector('img');
    // 等图片加载完成获取div高度
    currentImg.onload = function(){
        let minIdx = 0;
        let minTop = pos[minIdx].top;
        for(let j=1;j<pos.length;j++){
            if(pos[j].top < minTop){
                minTop = pos[j].top;
                // 更新最小索引值
                minIdx = j;
            }
        }
        animate(items[i],{left:parseInt(pos[minIdx].left),top:parseInt(pos[minIdx].top)})
        // 然后更新当前top值
        pos[minIdx].top += gap + items[i].offsetHeight;
    }
}             

猜你喜欢

转载自blog.csdn.net/Schrodinge/article/details/88318825