Vue练习五十七_07_02_带Loading效果的图片切换

Demo在线效果浏览

(太多使用了$refs来直接操作dom,有待更正)

需求:

1. 鼠标移至/离开左侧/右侧,显示/隐藏向左/向右切换图片按钮

2. 加载时添加Loading.gif,加载完成后消失(根据网速)

3. 图片标题/文字动态显示

4. 向左/向右切换至第一张/最末一张图片后,再次点击,弹出提示无更多图片

解析:

1. Html结构:1个大的div(id为big),包含5个子div:masks_L, masks_R, btn_L, btn_R, title。从id可知其用途,前2个为蒙版(其用途是当mouseover其上时,分别显示向左/向右按钮,离开则隐藏),后2个为左/右侧按钮,第5个为标题div,内含一个span元素。

2. 根据id获取各div引用,获取 span元素的引用

3. 设置data数据,为一个数组对象,由imgSrc和title2个属性组成,分别表示图片路径和标题文字

4. 给masks_L, masks_R,btn_L, btn_R添加mouseover/mouseout事件,调用startMove辅助函数,传入左右按钮,属性及数值。

5. startMove()辅助函数接受4个参数,obj对象,attr属性,属性数值及回调函数fnEnd。给obj添加计时器setinterval,调用doMove()并传递所有参数,每30毫秒执行一次。

6. doMove()辅助函数,接受4个参数,先根据对象及属性,调用辅助函数getStyle获取当前属性值。如属性为透明度opacity,则值需乘以100进行换算。接下给obj设置属性值。

7. 给btnL和btnR添加click事件处理器。先判断是否已无更多图片,(此处根据iNow计数器进行判断)如是,则return,如否,调用loadImg(),加载对应图片。

8. loadImg(),加载图片函数。给big(最外层容器div)添加loading类,加载Loading gif图片。设置标题div高度为0,设置span透明度为0。获取img元素的引用,如存在则先删除(调用removeChild)。创建一个img元素及new一个Image实例。给实例添加onload事件处理器,当加载成功后,先清除掉big(最外层div)的类,给Img元素添加src属性,设置其宽度(最大不超过800)和高度。给span元素添加文字(标题)调用startMove()先设置title(外层div)的高度,再设置span的透明度(由0到100),从完全透明到完全不透明。

以上为对原生js写就的程序的粗浅分析。

在使用vue改写时,需要考虑的最主要的地方是:以数据来驱动,而尽量不要直接操作dom.

1 在给maskL,maskR,btnL,btnR添加mouseover/mouseout处理器时,尝试以vue中的transition组件来操作元素的显示/隐藏,既将btnL,btnR包裹在transition组件中,同时给mask/btn添加over/out事件处理器,添加bollean数据show,当over时,为真时显示,out则为false,隐藏。说白了,Mask相当于2个大型的按钮

<template>
  <div id="big" :class="{loading:isBigActive}" ref="myBig">
    <div id="masks_L" @mouseover="handleLeftOver" @mouseout="handleLeftOut"></div>
    <div id="masks_R" @mouseover="hanldeRightOver" @mouseout="handleRightOut"></div>
    <div ref="btnL" id="btn_L" @mouseover="handleLeftOver" @mouseout="handleLeftOut" @click="handleLeftClick"></div>
    <div ref="btnR" id="btn_R" @mouseover="hanldeRightOver" @mouseout="handleRightOut" @click="handleRightClick"></div>
    <div id="title" ref="myTitle"><span ref="mySpan"></span></div>
  </div>
</template>
<script>
function getStyle(obj,attr){return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj,null)[attr]}
export default {
  data(){
    return{
      iNow:0,
      isbtnLShow:false,
      isbtnRShow:false,
      isBigActive:false,
      imgdata:[
        {'imgSrc':'http://img1.gtimg.com/news/pics/hv1/106/238/825/53706421.jpg','title':'7月26日,吊车将事故现场的车头残片吊至大型运输车辆上。'},
        {'imgSrc':'http://img1.gtimg.com/news/pics/hv1/105/238/825/53706420.jpg','title':'7月26日,一辆大卡车准备驶离事故现场。'},
        {'imgSrc':'http://img1.gtimg.com/news/pics/hv1/101/238/825/53706416.jpg','title':'7月26日,工人在给最后一节车厢盖上彩条布,准备运离现场。'},
        {'imgSrc':'http://img1.gtimg.com/news/pics/hv1/99/238/825/53706414.jpg','title':'7月26日,一名工人在事故现场最后一节车厢上作业。'},
        {'imgSrc':'http://img1.gtimg.com/news/pics/hv1/100/238/825/53706415.jpg','title':'7月26日,工人在给最后一节车厢盖上彩条布,准备运离现场。'}
      ]
    }
  },
  methods:{
    handleLeftOver(){
      this.startMOve(this.$refs.btnL,'opacity',100);
      //this.isbtnLShow=true;
    },
    handleLeftOut(){
      this.startMOve(this.$refs.btnL,'opacity',0);
      //this.isbtnLShow=false;
    },
    hanldeRightOver(){
      this.startMOve(this.$refs.btnR,'opacity',100);
      //this.isbtnRShow=true;
    },
    handleRightOut(){
      this.startMOve(this.$refs.btnR,'opacity',0);
      //this.isbtnRShow=false;
    },
    startMOve(obj,attr,iTarget,fnEnd){
      var _this=this;
      clearInterval(obj.timer);
      obj.timer=setInterval(() => {
        _this.doMove(obj,attr,iTarget,fnEnd);
      }, 20);
    },
    doMove(obj,attr,iTarget,fnEnd){
                var iCur = parseFloat(getStyle(obj, attr));
                if (attr == "opacity") {
                    iCur = parseInt(iCur * 100)
                }
                var iSpeed = (iTarget - iCur) / 5;
                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);

                if (iTarget == iCur) {
                    clearInterval(obj.timer);
                    fnEnd && fnEnd();
                }
                else {
                    if (attr == "opacity") {
                        obj.style.filter = "alpha(opacity = " + (iCur + iSpeed) + ")";
                        obj.style.opacity = (iCur + iSpeed) / 100;
                    }
                    else {
                        obj.style[attr] = iCur + iSpeed + "px";
                    }
                }
    },
    handleLeftClick(){
      if(this.iNow <= 0){
        alert('前面没有图片了!');
        return;
      }
      this.iNow--;
      this.loadImg();
    },
    handleRightClick(){
      if(this.iNow >= this.imgdata.length -1){
        alert('这是最后一张图片了!');
        return;
      }
      this.iNow++;
      this.loadImg();
    },
    loadImg(){
      var _this =this;
      this.isBigActive=true;
      var myBig=this.$refs.myBig;
      var myTitle=this.$refs.myTitle;
      var mySpan=this.$refs.mySpan;
      mySpan.style.opacity=myTitle.style.height=0;
      var oImg=myBig.getElementsByTagName('img');
      oImg[0] && myBig.removeChild(oImg[0]);
      var oTemp = document.createElement('img');
      var oNewImg=new Image();
      oNewImg.onload=function(){
        _this.isBigActive=false;
        oTemp.src=oNewImg.src;
        myBig.appendChild(oTemp);
        oTemp.style.width = (oTemp.offsetWidth > 800 ? 800 : oTemp.offsetWidth) + 'px';
        myBig.style.height = oTemp.style.height = oTemp.offsetHeight * oTemp.offsetWidth / oTemp.offsetWidth + 'px';
        //console.log(_this.imgdata);
        mySpan.innerHTML=_this.imgdata[_this.iNow].title;
        _this.startMOve(myTitle,'height',50,function(){
          _this.startMOve(myTitle.childNodes[0],'opacity',100);
        })
      };
      oNewImg.src=this.imgdata[this.iNow].imgSrc;
    }
  },
  mounted(){
    this.loadImg();
  }
}
</script>
<style>
body, div, ul, li{
  margin: 0;
  padding: 0;
}
li{
  list-style: none;
}
body{
  font: 12px/1.5 5fae8f6f96c59ed1;
  background:#000;
}
#big{
  position: relative;
   800px;
  height: auto !important;
  height: 400px;
  min- 400px;
  margin: 20px auto;
  text-align: center;
}
#title{
  position: absolute;
  top:0;
  left: 0;
   100%;
  background: #000;
  color: #fff;
  opacity: 0.7;
  filter: alpha(opacity=70);
  font-size: 20px;
  height: 50px;
}
#title span{
  padding: 0 50px;
  line-height: 50px;
  display: block;
}
#big.loading{
  background: url(./assets/lesson7/loading.gif) 50% 50% no-repeat;
}
#masks_L, #masks_R{
  position: absolute;
  top:0;
   400px;
  height: 100%;
  cursor: pointer;
  background: #f0f0f0;
  opacity: 0;
  filter: alpha(opacity=0);
}
#masks_L{
  left: 0;
}
#masks_R{
  right: 0;
}
#btn_L, #btn_R{
  position: absolute;
  top:50%;
  margin-top: -40px;
   39px;
  height: 80px;
  overflow: hidden;
  cursor: pointer;
  text-indent: -9999px;
  background:url(./assets/lesson7/btn.png) no-repeat;
  opacity: 0;
  filter: alpha(opacity=0);
}
#btn_L{
  left: 10px;
  background-position: 0 0;
}
#btn_R{
  right: 10px;
  background-position: -39px 0;
}
</style>
原文地址:https://www.cnblogs.com/sx00xs/p/11553856.html