zoukankan      html  css  js  c++  java
  • 移动web:图片切换(焦点图)

      在web页面上图片切换(焦点图)效果实在是太常见了,PC端、移动端到处都有它的身影。

      上次写了个tab选项卡的效果,在这里延续一下,改成图片切换的效果。

      如果不需要自动播放,稍微修改下html标签、和css样式,tab选项卡JS里动画持续时间、去掉点击切换事件部分就可以了。

      html

    <div class="mslide" id="slide">
            <ul class="mcontent">
                <li><a href="#a1"><img src="images/01.jpg" /></a></li>
                <li><a href="#a2"><img src="images/02.jpg" /></a></li>
                <li><a href="#a3"><img src="images/03.jpg" /></a></li>
                <li><a href="#a4"><img src="images/04.jpg" /></a></li>
            </ul>
            <ul class="mhead">
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
            </ul>
        </div><!-- End mslide -->
    View Code

      css

    body,div,ul,li{margin:0;padding:0;}
    ul,li{list-style: none;}
    body{font-size: 100%; font-family: Helvetica,STHeiti,Droid Sans Fallback;}
    
    .mslide {
        position:relative;
        width:100%;
        overflow:hidden;
        margin: 15px 0;
    }
    .mcontent {
        width:100%;
        overflow:hidden;
    }
    .mcontent li {
        width:100%;
        float:left;
    }
    .mcontent li img {
        width:100%;
    }
    .mhead {
        position:absolute;
        bottom:5px;
        left:0;
        z-index: 10;
        text-align:center;
        width:100%;
        height:15px;
        line-height:15px;
    }
    .mhead li {
        display:inline-block;
        width:10px;
        height:10px;
        border:1px solid #999;
        border-radius:6px;
        margin:0 3px;
        overflow:hidden;
        font-size:0;
        line-height:0;
        vertical-align: top;
        background: transparent;
        color:rgba(0,0,0,0);
    }
    .mhead li.current {
        background:#F00;
    }
    View Code

      JS

    /**
     * LBS mTabs  (修改成图片切换)
     * ===================================================
     * opts.mtab     tabs外围容器/滑动事件对象(一个CSS选择器)
     * opts.mhead     tabs标题容器/点击对象(一个CSS选择器)
     * opts.mcontent    tabs内容容器/滑动切换对象(一个CSS选择器) 
     * opts.index     tabs索引(默认0) 指定显示哪个索引的标题、内容
     * opts.current  tabs当前项的类名(默认current)
     * ===================================================
    **/
    ;(function(){
    window.mTabs = function(opts){
        if(typeof opts === undefined) return;
    
        this.mtab = document.querySelector(opts.mtab);
        this.mhead = document.querySelector(opts.mhead);
        this.mcontent = document.querySelector(opts.mcontent);
    
        this.mheads = this.mhead.children;
        this.mcontents = this.mcontent.children;
        
        this.length = this.mheads.length;
        if(this.length < 1) return;
        if(opts.index > this.length-1) opts.index = this.length-1;
        this.index = this.oIndex = opts.index || 0;
        this.current = opts.current || 'current';
        this.touch = {};
    
        this.init();
    }
    mTabs.prototype = {
        init: function(opts){
            this.set();
            this.initset();
            this.bind();
        },
        initset: function(){
            for(var i = 0; i < this.length; i++){
                this.mheads[i].index = i;
                this.mheads[i].className = this.mheads[i].className.replace(this.current,'');
                this.mcontents[i].className = this.mcontents[i].className.replace(this.current,'');
            } 
            this.mheads[this.index].className += ' '+this.current;
            this.mcontents[this.index].className += ' '+this.current;
            //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + (-this.index * this.width) + "px)";
            this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + (-this.index * this.width) + "px,0,0)";
        },
        set: function(){
            this.width =  document.documentElement.clientWidth || document.body.clientWidth;
            this.mcontent.style.width = this.length * this.width + 'px';        
            for(var i = 0; i < this.length; i++) this.mcontents[i].style.width = this.width + 'px';
            //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + (-this.index * this.width) + "px)";
            this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + (-this.index * this.width) + "px,0,0)";
        },
        bind: function(){
            var _this = this;
            this.mtab.addEventListener("touchstart",function(e){
                _this.touchStart(e);
            }, false);
            this.mtab.addEventListener("touchmove",function(e){
                _this.touchMove(e);
            }, false);
            this.mtab.addEventListener("touchend",function(e){
                _this.touchEnd(e);
            }, false);
            this.mtab.addEventListener("touchcancel",function(e){
                _this.touchEnd(e);
            }, false);
            this.mcontent.addEventListener('webkitTransitionEnd',function(){
                _this.transitionEnd();
            }, false);
            window.addEventListener("resize", function(){
                setTimeout(function(){
                    _this.set();
                },100);
            }, false);
            window.addEventListener("orientationchange",function(){
                setTimeout(function(){
                    _this.set();
                },100);
            }, false);
        },
        touchStart: function(e){
            this.touch.x = e.touches[0].pageX;
            this.touch.y = e.touches[0].pageY;
            this.touch.time = Date.now();
            this.touch.disX = 0;
            this.touch.disY = 0;
            this.touch.fixed = '';
        },
        touchMove: function(e){
            if(this.touch.fixed === 'up') return;
            e.stopPropagation();
            if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
            this.touch.disX = e.touches[0].pageX - this.touch.x;
            this.touch.disY = e.touches[0].pageY - this.touch.y;
            if(this.touch.fixed === ''){
                if( Math.abs(this.touch.disY) > Math.abs(this.touch.disX) ){
                    this.touch.fixed = 'up';
                }else{
                    this.touch.fixed = 'left';
                }
            }
            if(this.touch.fixed === 'left'){
                e.preventDefault();
                if( (this.index === 0 && this.touch.disX > 0) || (this.index === this.length-1 && this.touch.disX < 0) ) this.touch.disX /= 4;
                //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + ( this.touch.disX - this.index * this.width ) + "px)";
                this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + ( this.touch.disX - this.index * this.width ) + "px,0,0)";
            } 
        },
        touchEnd: function(e){    
            if(this.touch.fixed === 'left'){
                var _this = this, X = Math.abs(this.touch.disX);
                this.mcontent.style.webkitTransition = this.mcontent.style.transition = 'all 400ms';
                if( (Date.now() - this.touch.time > 100 && X > 10) || X > this.width/2 ){
                    this.touch.time = Date.now();
                    this.touch.disX > 0 ? this.index-- : this.index++;
                    this.index < 0 && (this.index = 0);
                    this.index > this.length - 1 && (this.index = this.length - 1);
                    if(this.index !== this.oIndex) this.replace();
                }
                //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + (-this.index * this.width) + "px)";
                this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + (-this.index * this.width) + "px,0,0)";
            }    
        },
        transitionEnd: function(){
            this.mcontent.style.webkitTransition = this.mcontent.style.transition = 'all 0ms';
        },
        replace: function(){
            this.mheads[this.index].className += ' '+this.current;
            this.mheads[this.oIndex].className = this.mheads[this.oIndex].className.replace(this.current,'').trim();
            this.mcontents[this.index].className += ' '+this.current;
            this.mcontents[this.oIndex].className = this.mcontents[this.oIndex].className.replace(this.current,'').trim();
            this.oIndex = this.index;
        }
    }
    }());
    View Code

      效果预览 (Chrome的移动模式、移动设备)

    • 1
    • 2
    • 3
    • 4

       这个根据tab选项卡修改而成的图片切换能适应大部分web页面的需求。点击下载

      现在来加上自动播放功能,在上面的html,css基础上做出一点修改,每次手动写入导航的指示的html标签太麻烦了,让程序来判断有几张图片,然后创建几个导航指示,这样html结构更简洁。

      html

    <div class="mslide" id="slideIMG">
        <ul class="mcontent">
            <li><a href="#a1"><img src="images/01.jpg" /></a></li>
            <li><a href="#a2"><img src="images/02.jpg" /></a></li>
            <li><a href="#a3"><img src="images/03.jpg" /></a></li>
            <li><a href="#a4"><img src="images/04.jpg" /></a></li>
        </ul>
    </div><!-- End mslide -->

       css

    body,div,ul,li{margin:0;padding:0;}
    ul,li{list-style: none;}
    body{font-size: 100%; font-family: Helvetica,STHeiti,Droid Sans Fallback;}
    
    .mslide {
        position:relative;
        width:100%;
        overflow:hidden;
        margin: 15px 0;
    }
    .mcontent {
        width:100%;
        overflow:hidden;
    }
    .mcontent li {
        width:100%;
        float:left;
    }
    .mcontent li img {
        width:100%;
    }
    .mhead {
        position:absolute;
        bottom:5px;
        left:0;
        z-index: 10;
        text-align:center;
        width:100%;
        height:15px;
        line-height:15px;
    }
    .mhead li {
        display:inline-block;
        width:10px;
        height:10px;
        border:1px solid #999;
        border-radius:6px;
        margin:0 3px;
        overflow:hidden;
        font-size:0;
        line-height:0;
        vertical-align: top;
        background: transparent;
        color:rgba(0,0,0,0);
    }
    .mhead li.current {
        background:#F00;
    }
    View Code

       JS代码和tab选项卡大部分相似,增加了自动播放、创建导航指示。

      先贴JS出代码,供参考

    /**
     * LBS mSlideIMG 顺序版-自动
     * Date: 2014-5-11
     * ===================================================
     * opts.mslide     外围容器/滑动事件对象(一个CSS选择器)
     * opts.mcontent  内容容器/滑动切换对象(一个CSS选择器) 
     * opts.index     索引(默认0) 指定显示哪个索引的导航指示、图片项
     * opts.navclass  导航容器的类名(默认mnav)
     * opts.current  当前项的类名(默认current)
     * opts.auto    是否自动播放 默认false
     * opts.delay    自动播放间隔时间 默认5秒 自动播放时有效
     * opts.duration    动画持续时间 默认400ms
     * ===================================================
    **/
    ;(function(){
    window.mSlideIMG = function(opts){
        if(typeof opts === undefined) return;
    
        this.mslide = document.querySelector(opts.mslide);
        this.mcontent = document.querySelector(opts.mcontent);
        this.mcontents = this.mcontent.children;
        this.mnav = null;
        this.mnavs = [];
    
        this.length = this.mcontents.length;
        if(this.length < 1) return;
        if(opts.index > this.length-1) opts.index = this.length-1;
        this.index = this.oIndex = opts.index || 0;
        
        this.current = opts.current || 'current';
        this.navclass = opts.navclass || 'mnav';
    
        this.duration = opts.duration || 400;
        this.auto = !!opts.auto || false;
        this.auto && (this.delay = opts.delay || 5);
        this.timer = null;
        this.touch = {};
    
        this.init();
    }
    mSlideIMG.prototype = {
        init: function(opts){
            this.set();
            this.initset();
            this.bind();
        },
        initset: function(){
            this.create();
            for(var i = 0; i < this.length; i++){ 
                if(getComputedStyle(this.mcontents[i],null).position === 'absolute') this.mcontents[i].style.position = 'relative';
                if(getComputedStyle(this.mcontents[i],null).cssFloat !== 'left') this.mcontents[i].style.cssFloat = 'left';
            } 
            this.mnavs[this.index].className = this.current;
            this.mcontents[this.index].className += ' '+this.current;
            //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + (-this.index * this.width) + "px)";
            this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + (-this.index * this.width) + "px,0,0)";
        },
        set: function(){
            this.width =  document.documentElement.clientWidth || document.body.clientWidth;
            this.mcontent.style.width = this.length * this.width + 'px';        
            for(var i = 0; i < this.length; i++) this.mcontents[i].style.width = this.width + 'px';
            //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + (-this.index * this.width) + "px)";
            this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + (-this.index * this.width) + "px,0,0)";
        },
        create: function(){
            this.mnav = document.createElement('ul'), li = null, i = 0;
            for(; i < this.length; i++){
                li = document.createElement('li');
                li.innerHTML = i+1;
                this.mnavs.push(li);
                this.mnav.appendChild(li);
            }
            this.mnav.className = this.navclass;
            this.mslide.appendChild(this.mnav);
        },
        bind: function(){
            var _this = this;
            this.mslide.addEventListener("touchstart",function(e){
                _this.touchStart(e);
                _this.auto && _this.stop();
            }, false);
            this.mslide.addEventListener("touchmove",function(e){
                _this.touchMove(e);
                _this.auto && _this.stop();
            }, false);
            this.mslide.addEventListener("touchend",function(e){
                _this.touchEnd(e);
                _this.auto && _this.start();
            }, false);
            this.mslide.addEventListener("touchcancel",function(e){
                _this.touchEnd(e);
                _this.auto && _this.start();
            }, false);
            this.mcontent.addEventListener('webkitTransitionEnd',function(){
                _this.transitionEnd();
            }, false);
            window.addEventListener("resize", function(){
                setTimeout(function(){
                    _this.set();
                },100);
            }, false);
            window.addEventListener("orientationchange",function(){
                setTimeout(function(){
                    _this.set();
                },100);
            }, false);
            this.auto && this.start();
        },
        touchStart: function(e){
            this.touch.x = e.touches[0].pageX;
            this.touch.y = e.touches[0].pageY;
            this.touch.time = Date.now();
            this.touch.disX = 0;
            this.touch.disY = 0;
            this.touch.fixed = '';
        },
        touchMove: function(e){
            if(this.touch.fixed === 'up') return;
            e.stopPropagation();
            if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
            this.touch.disX = e.touches[0].pageX - this.touch.x;
            this.touch.disY = e.touches[0].pageY - this.touch.y;
            if(this.touch.fixed === ''){
                if( Math.abs(this.touch.disY) > Math.abs(this.touch.disX) ){
                    this.touch.fixed = 'up';
                }else{
                    this.touch.fixed = 'left';
                }
            }
            if(this.touch.fixed === 'left'){
                e.preventDefault();
                if( (this.index === 0 && this.touch.disX > 0) || (this.index === this.length-1 && this.touch.disX < 0) ) this.touch.disX /= 4;
                //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + ( this.touch.disX - this.index * this.width ) + "px)";
                this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + ( this.touch.disX - this.index * this.width ) + "px,0,0)";
            } 
        },
        touchEnd: function(e){
            if(this.touch.fixed === 'left'){
                var _this = this, X = Math.abs(this.touch.disX);
                if( (Date.now() - this.touch.time > 100 && X > 10) || X > this.width/2 ){
                    this.touch.time = Date.now();
                    this.touch.disX > 0 ? this.index-- : this.index++;
                    this.index < 0 && (this.index = 0);
                    this.index > this.length - 1 && (this.index = this.length - 1);
                    if(this.index !== this.oIndex) this.replace();
                }
                this.mcontent.style.webkitTransition = this.mcontent.style.transition = 'all '+ this.duration +'ms';
                //this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translateX(" + (-this.index * this.width) + "px)";
                this.mcontent.style.webkitTransform = this.mcontent.style.transform = "translate3d(" + (-this.index * this.width) + "px,0,0)";
            }
        },
        transitionEnd: function(){
            this.mcontent.style.webkitTransition = this.mcontent.style.transition = 'all 0ms';
        },
        replace: function(){
            this.mnavs[this.index].className = this.current;
            this.mnavs[this.oIndex].className = '';
            this.mcontents[this.index].className += ' '+this.current;
            this.mcontents[this.oIndex].className = this.mcontents[this.oIndex].className.replace(this.current,'').trim();
            this.oIndex = this.index;
        },
        start : function(){
            if(this.length < 2) return;
            var _this = this;
            this.timer = setInterval(function(){
                _this.index++;
                 _this.index > _this.length - 1 && (_this.index = 0);
                if(_this.index !== _this.oIndex) _this.replace();
                _this.mcontent.style.webkitTransition = _this.mcontent.style.transition = 'all '+ _this.duration +'ms';
                 //_this.mcontent.style.webkitTransform = _this.mcontent.style.transform = "translateX(" + (-_this.index * _this.width) + "px)";
                _this.mcontent.style.webkitTransform = _this.mcontent.style.transform = "translate3d(" + (-_this.index * _this.width) + "px,0,0)";
            },this.delay*1000);
        },
        stop : function(){
            clearInterval(this.timer);
            this.timer = null;
         } 
    }
    }());
    View Code

      导航指示根据有几张图片来创建 (滑动切换容器ul.mcontent -> 包裹图片li标签,这里就是判断有几个li标签)

    this.mcontent = document.querySelector(opts.mcontent);
    this.mcontents = this.mcontent.children;
    //..
    this.length = this.mcontents.length;
    //..
    create: function(){
    	this.mnav = document.createElement('ul'), li = null, i = 0;
    	for(; i < this.length; i++){
    		li = document.createElement('li');
    		li.innerHTML = i+1;
    		this.mnavs.push(li);
    		this.mnav.appendChild(li);
    	}
    	this.mnav.className = this.navclass;
    	this.mslide.appendChild(this.mnav);
    }
    

      自动播放是间隔一段时间改变一个索引值来实现的,这个索引值在开始的时候默认定义为0。每间隔一段时间,这个索引值增加1。

    this.index = this.oIndex = opts.index || 0;
    //..
    start : function(){
    	//..
    	this.timer = setInterval(function(){
    		_this.index++;
    		_this.index > _this.length - 1 && (_this.index = 0);
    		//..
    		_this.mcontent.style.webkitTransition = _this.mcontent.style.transition = 'all '+ _this.duration +'ms';
    		_this.mcontent.style.webkitTransform = _this.mcontent.style.transform = "translate3d(" + (-_this.index * _this.width) + "px,0,0)";
    	},this.delay*1000);
    }
    

       有时候要清除自动播放,当用手指来切换图片时,要清除自动播放,手指离开时又开始自动播放。

    stop : function(){
    	clearInterval(this.timer);//清除定时
    	this.timer = null;
    }
    //..
    this.mslide.addEventListener("touchstart",function(e){
    	_this.touchStart(e);
    	_this.auto && _this.stop(); //手指移入 如果有自动播放则清除
    }, false);
    this.mslide.addEventListener("touchend",function(e){
    	_this.touchEnd(e);
    	_this.auto && _this.start(); //手指离开 重新开始自动播放
    }, false);
    

      有时同一个web页面,有好几个图片切换,希望有的能定时自动切换,有的不用定时,为程序增加一个接口设置是否自动播放,顺便把间隔时间,切换动画持续时间一起定义了。

    this.auto = !!opts.auto || false; //默认没有自动播放
    this.auto && (this.delay = opts.delay || 5); //默认间隔时间5秒
    this.duration = opts.duration || 400; //默认动画持续时间400毫秒
    

      自动播放的图片切换,差不多完成了,来看下效果 (Chrome的移动模式、移动设备)。

       说一些要注意的地方,外围容器(这里是类名为mslide的div标签)要设置相对或者绝对定位、并溢出隐藏;图片容器(这里是li标签)要浮动,为了都显示在一排滚动的容器(这里是类名为mcontent的ul标签)要足够宽;新建的导航指示是相对于外围容器绝对定位的,注意层级问题(这些能在样式里面定义就在样式里定义,程序为了全面可以多做判断)。

      这个图片切换当最后一项切换到第一项时,动画跨度大,方向也和前几次相反,有时需要更自然的切换,方向都一样,每次动画距离也一样,这是一种进价的图片切换(焦点图),也叫无缝切换。说下思路:可以采用绝对定位方式(这个例子里的li标签绝对定位,在li标签上做动画切换) ,根据索引值,在切换前修正位置,切换完成后修正位置;可以采用复制节点方式(复制这个例子里的li标签、全部或者部分),根据索引值判断修正位置(这个例子里动画切换的对象和要修正位置对象是mcontent)。

      可以看下效果:

       实际上根据业务需求,会做出不同的改变,比如图片要切换到那一项时才加载,图片切换在页面没有html标签(解析JSON数据生成标签)……不管它怎么变,只要掌握基本的原理,问题都能解决。

      下载图片切换(焦点图)

  • 相关阅读:
    web selenium 小笔记
    C#全局变量的使用
    一些传统阻止了新事物的发展
    javascript 类
    无聊的文档
    asp.net调用c++写的dll或ocx 方法
    在ASP.NET中的DatePicker控件
    保护眼睛的背景色
    web引用程序调用 windows的服务
    asp.net常用数据类型
  • 原文地址:https://www.cnblogs.com/eyeear/p/4626086.html
Copyright © 2011-2022 走看看