雙輪播加切換動畫效果元件

如意酱發表於2024-03-12

效果如圖,結合了一些動畫效果和圖片背景,元件開發思路:左側按鈕設定定時器為大輪播,下側按鈕設定定時器為小輪播

當輪播到當組的最後一個就 繼續大輪播,停掉小輪播,並處理一些特殊情況和翻頁情況。
程式碼已經註釋掉引入圖片的路徑換成背景顏色,可直接執行。

<template>
  <div class="centerWrap">
    <!-- 中上 -->
    <div class="centerWrap-top">
      <!-- 文字部分 -->
      <div class="textWrap">
        <span>{{ jarObj.type }}</span>
        <h1 :class="tipsMove ? 'textLight' : ''">{{ jarObj.id }}</h1>
        <p>{{ jarObj.tipsName }}</p>
      </div>
      <div class="rotateBox">
        <!-- 油品切換 -->
        <div class="jarBtnGroup">
          <div
            v-for="item in jarBtnList"
            :key="item.id"
            class="jarBtn"
            :class="jarBtnActive == item.id ? 'jarBtnActive' : ''"
            @click="jarBtnFn(item)"
          >
            <div class="jarBtnLight">
              {{ item.name }}
            </div>
          </div>
        </div>
        <!-- 右側小標籤 -->
        <transition name="el-zoom-in-center">
          <div class="tipsWrap tipsMove" v-if="tipsMove">
            <ul class="tipsBg">
              <li>
                <p>安全容量:</p>
                <span>{{ jarObj.rongliang }}</span>
              </li>
              <li>
                <p>可髮量:</p>
                <span>{{ jarObj.kefaliang }}</span>
              </li>
            </ul>
            <ul class="tipsBg">
              <li>
                <p>當前液位:</p>
                <span>{{ jarObj.yewei }}</span>
              </li>
              <li>
                <p>當前溫度:</p>
                <span>{{ jarObj.temp }}</span>
              </li>
              <li>
                <p>標準密度:</p>
                <span>{{ jarObj.midu }}</span>
              </li>
            </ul>
          </div>
        </transition>
        <!-- 背景盤子 -->
        <!-- <img class="roateBg" src="@/assets/images/screen/home-jar-pan.png" /> -->
        <!-- --------------中間罐-------------- -->
        <div class="bigBox rotateJar">
          <!-- <img class="bigBoxImg" src="@/assets/images/screen/bigBox.png" /> -->
          <!-- <img
            class="boxPointImg"
            src="@/assets/images/screen/bigBoxPoint.png"
          /> -->
          <jarHomeBox
            :number="jarObj.percen"
            :barEntityColor="['rgba(0,155,255,0.75)', 'rgba(0,155,255,0.75)']"
            :barEntityAfterColor="['#00a2ff', '#00d7ff']"
          ></jarHomeBox>
        </div>
      </div>
    </div>
    <!-- 中下 -->
    <div class="centerWrap-bottom">
      <!-- 罐選擇 -->
      <div class="tabsWrap">
        <div
          class="toPage toLeft"
          :class="[toLeft ? 'active' : '']"
          @click="toNext('up')"
        >
          <!-- <i class="iconfont icon-zuo"></i> -->
</div>
        <div class="tabsCenter">
          <div class="tabsGroup" :style="{ left: '-' + left + '%' }">
            <div
              class="tabsItem"
              :class="tabsItemActive == item.id ? 'tabsItemActive' : ''"
              @click="tabsClickFn(item, index)"
              v-for="(item, index) in tabsList"
              :key="item.id"
            >
              {{ item.id }}
            </div>
          </div>
        </div>
        <div
          class="toPage toRight"
          :class="[toRight ? 'active' : '']"
          @click="toNext('down')"
        >
          <!-- <i class="iconfont icon-you"></i> -->
</div>
      </div>
    </div>
  </div>
</template>

<script>
import jarHomeBox from "@/components/jarHomeBox.vue"; //油罐元件
export default {
  name: "jarBoxs",
  components: { jarHomeBox },
  props: {},
  data() {
    return {
      //中間油品列表
      jarBtnList: [
        {
          id: 1,
          name: "92#汽油",
          list: [
            {
              id: "G-208-030",
              tipsName: "92#車用汽油(VIB)",
              percen: 37,
              type: "公路髮油",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "1935mm",
              temp: "19.4℃",
              midu: "826kg/m³",
            },
            {
              id: "G-203-030",
              tipsName: "92#車用汽油(VIB)",
              percen: 40,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "826kg/m³",
            },
            {
              id: "G-104-200",
              tipsName: "92#車用汽油(VIB)",
              percen: 80,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "4035mm",
              temp: "19.4℃",
              midu: "826kg/m³",
            },
          ],
        },
        {
          id: 2,
          name: "95#汽油",
          list: [
            {
              id: "G-204-030",
              tipsName: "95#車用汽油(VIB)",
              percen: 10,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "1035mm",
              temp: "19.4℃",
              midu: "826kg/m³",
            },
            {
              id: "G-105-200",
              tipsName: "95#車用汽油(VIB)",
              percen: 40,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "826kg/m³",
            },
          ],
        },
        {
          id: 3,
          name: "98#汽油",
          list: [
            {
              id: "G-207-020",
              tipsName: "98#車用汽油(VIA)(VIB)",
              percen: 78,
              type: "公路髮油",
              rongliang: "1652m³",
              kefaliang: "1242.2噸",
              yewei: "1335mm",
              temp: "24.4℃",
              midu: "826kg/m³",
            },
            {
              id: "G-206-020",
              tipsName: "98#車用汽油(VIA)(VIB)",
              percen: 40,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "875.1g/m³",
            },
          ],
        },
        {
          id: 4,
          name: "0#柴油",
          list: [
            {
              id: "D-210-050",
              tipsName: "0#車用柴油(VI)",
              percen: 90,
              type: "不動罐",
              rongliang: "1652m³",
              kefaliang: "1242.2噸",
              yewei: "3335mm",
              temp: "24.4℃",
              midu: "826g/m³",
            },
            {
              id: "D-209-030",
              tipsName: "0#車用柴油(VI)",
              percen: 40,
              type: "公路髮油",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-205-050",
              tipsName: "0#車用柴油(VI)",
              percen: 96,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "4200mm",
              temp: "26.4℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-202-030",
              tipsName: "0#車用柴油(VI)",
              percen: 20,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "1000mm",
              temp: "14.4℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-201-030",
              tipsName: "0#車用柴油(VI)",
              percen: 40,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-106-200",
              tipsName: "0#車用柴油(VI)",
              percen: 69,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "3205mm",
              temp: "19.4℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-103-100",
              tipsName: "0#車用柴油(VI)",
              percen: 40,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-102-200",
              tipsName: "0#車用柴油(VI)",
              percen: 60,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "3000mm",
              temp: "15.9℃",
              midu: "875.1g/m³",
            },
            {
              id: "D-101-200",
              tipsName: "0#車用柴油(VI)",
              percen: 49,
              type: "不動罐",
              rongliang: "4565m³",
              kefaliang: "1242.2噸",
              yewei: "2035mm",
              temp: "19.4℃",
              midu: "875.1g/m³",
            },
          ],
        },
      ],
      //中部罐名稱
      tabsList: [],
      jarObj: {}, //選中的罐內容
      tipsMove: true, //標籤動效
      toLeft: false, //上一頁
      toRight: false, //下一頁
      page: 1, //中間tab頁碼
      left: 0, //中間tab位置
      tabsItemActive: "", //中間tab點選
      jarBtnActive: 1, //旋轉罐按鈕
      timer: null, //油品切換定時器
      num: 0, // 索引
      timer2: null, //罐切換定時器
      num2: 0, // 索引
      typeTimer: null, //型別定時器
      typeNum: 0, //型別索引
    };
  },
  watch: {},
  mounted() {
    this.jarBtnFn(this.jarBtnList[0]);
    this.typePlay(); //罐型別輪播
  },
  methods: {
    //中間上部油品選擇
    jarBtnFn(val) {
      //清空兩個定時器
      clearInterval(this.timer);
      clearInterval(this.timer2);
      this.num = val.id - 1; //大定時器索引
      this.jarBtnActive = val.id; //油品高亮
      this.tabsList = val.list;
      //處理罐上下頁高亮顯示
      let length = this.tabsList.length;
      if (length < 5) {
        this.toLeft = false;
        this.toRight = false;
      } else {
        this.toLeft = false;
        this.toRight = true;
      }
      //立即執行一次 罐選擇
      this.num2 = 0;
      this.page = 1;
      this.left = 0;
      this.tabsClickFn(this.tabsList[this.num2], this.num2);
      this.play2(); //罐選擇自動
    },
    //油品切換自動播放
    autoPlay() {
      if (this.num == 3) {
        this.num = 0;
      } else {
        this.num++;
      }
      this.jarBtnFn(this.jarBtnList[this.num]);
    },
    // 油品(大輪播)設定定時器
    play() {
      this.timer = setInterval(this.autoPlay, 5000);
    },
    //罐切換自動播放
    autoPlay2() {
      let length = this.jarBtnList[this.num].list.length;
      if (this.num2 == length - 1) {
        //當輪播到當組的最後一個就 繼續大輪播,停掉小輪播
        this.tabsClickFn(this.tabsList[this.num2], this.num2);
        this.num2 = 0;
        this.page = 1;
        this.play(); //大輪播開始
        clearInterval(this.timer2);
      } else if (this.num2 == 0) {
        //輪播第一個時的特殊處理
        this.num2++;
        this.page = 1;
        this.toNext("up");
      } else {
        //處理帶翻頁的輪播
        if (this.num == 3 && this.num2 > 4) {
          this.toNext("down");
        }
        this.tabsClickFn(this.tabsList[this.num2], this.num2);
        this.num2++;
      }
    },
    // 罐(小輪播)設定定時器
    play2() {
      this.timer2 = setInterval(this.autoPlay2, 4000);
    },
    //罐tab切換
    tabsClickFn(val, index) {
      this.tabsItemActive = val.id;
      this.num2 = index;
      this.jarObj = val;
      this.tipsMove = false;
      //動效延遲
      setTimeout(() => {
        this.tipsMove = true;
      }, 100);
    },
    //上頁下頁
    toNext(val) {
      let num = 0;
      num = Math.ceil(this.tabsList.length / 5);
      if (val == "up") {
        // 上一頁
        if (this.page == 1) {
          this.left = 0;
        } else {
          this.page--;
          this.left = (this.page - 1) * 100;
        }
      } else {
        // 下一頁
        if (this.page == num) {
        } else {
          this.page++;
          this.left = (this.page - 1) * 100;
        }
      }
      // 翻頁按啟用判斷
      if (this.tabsList.length < 5) {
        this.toLeft = false;
        this.toRight = false;
      } else {
        if (this.page == num) {
          this.toLeft = true;
          this.toRight = false;
        } else if (this.page == 1) {
          this.toLeft = false;
          this.toRight = true;
        }
      }
    },
    //油品切換自動播放
    typeAutoPlay() {
      if (this.typeNum == 5) {
        this.typeNum = 0;
      } else {
        this.typeNum++;
      }
    },
    // 油品(大輪播)設定定時器
    typePlay() {
      this.typeTimer = setInterval(this.typeAutoPlay, 2000);
    },
  },
  beforeDestroy() {
    clearInterval(this.timer);
    clearInterval(this.timer2);
    clearInterval(this.typeTimer);
  },
};
</script>
<style lang="scss" scoped>
//中間地圖
.centerWrap {
  width: calc(44% - 50px);
  height: 100%;
  margin: 0 25px;
  box-sizing: border-box;
  position: relative;
  display: flex;
  flex-direction: column;
  background: #0242a3;
  // 中上
  .centerWrap-top {
    width: 100%;
    height: 60%;
    position: relative;
    //文字部分
    .textWrap {
      width: 100%;
      position: absolute;
      bottom: 80%;
      left: 0;
      text-align: center;
      span {
        font-size: 20px;
        font-family: Microsoft YaHei;
        font-weight: bold;
        color: #02aeff;
        line-height: 38px;
      }
      h1 {
        font-size: 30px;
        font-family: Microsoft YaHei;
        font-weight: bold;
        color: #ffffff;
        line-height: 30px;
        text-shadow: 0 0 20px RGBA(0, 174, 255, 1);
      }
      p {
        font-size: 15px;
        font-family: Microsoft YaHei;
        font-weight: 400;
        color: #ffffff;
        line-height: 24px;
        opacity: 0.5;
      }
      .textLight {
        animation: textLight 0.3s ease-in-out;
        @keyframes textLight {
          0% {
            color: #ffffffc4;
            text-shadow: 0 0 20px RGBA(0, 0, 0, 0.5);
          }
          100% {
            color: #ffffff;
            text-shadow: 0 0 25px RGBA(0, 174, 255, 1);
          }
        }
      }
    }
    // 罐樣式
    .rotateBox {
      width: 100%;
      height: 100%;
      position: relative;
      // 左側按鈕組
      .jarBtnGroup {
        .jarBtn {
          width: 135px;
          height: 40px;
          margin-bottom: 15px;
          box-sizing: border-box;
          line-height: 40px;
          color: #fff;
          font-size: 16px;
          font-weight: 400;
          text-align: center;
          font-family: Microsoft YaHei;
          // background: url("~@/assets/images/screen/home-jar-bar2.png") no-repeat;
          // background-size: 100% 100%;
          background: #2660f3;
          cursor: pointer;
          .jarBtnLight {
            width: 100%;
            height: 100%;
          }
        }
        .jarBtnActive {
          // background: url("~@/assets/images/screen/home-jar-bar1.png") no-repeat;
          // background-size: 100% 100%;
          background: #02aeff;
        }
        .jarBtn:hover {
          .jarBtnLight {
            // background: url("~@/assets/images/screen/home-jar-bar3.png")
            //   no-repeat;
            // background-size: 100% 100%;
            background: #00e4ff;
          }
        }
      }
      // 右側小標籤
      .tipsWrap {
        height: 215px;
        top: 50px;
        right: 30px;
        position: absolute;
        // background: url("~@/assets/images/screen/home-jar-textBg.png") no-repeat;
        // background-size: 100% 100%;
        background: #02aeff;
        padding: 15px 15px;
        box-sizing: border-box;
        overflow: hidden;

        .tipsBg {
          background: RGBA(1, 174, 255, 0.3);
          border-radius: 5px;
          margin-top: 10px;
          padding: 10px;
          box-sizing: border-box;
          li {
            font-size: 14px;
            font-family: Microsoft YaHei;
            font-weight: 400;
            display: flex;
            line-height: 24px;
            p {
              width: 70px;
              color: #aad1f7;
              text-align: right;
            }
            span {
              width: calc(100% - 70px);
              color: #fff;
              text-align: left;
            }
          }
        }
      }
      .tipsMove {
        animation: tipsMove 0.6s ease;
        //變小
        @keyframes tipsMove {
          0% {
            height: 0px;
          }
          100% {
            height: 215px;
          }
        }
      }
      // 底盤圖片
      .roateBg {
        width: 660px;
        bottom: -40px;
        height: 60%;
        position: absolute;
        left: calc(50% - 330px);
        z-index: 0;
      }

      //中間罐
      .bigBox {
        width: 200px;
        height: 271px;
        margin-left: -100px;
        position: absolute;
        left: 50%;
        bottom: 64px;
        bottom: 15%;
        z-index: 2;
        background: #00e4ff;
        // 外層罐圖片
        .bigBoxImg {
          width: 100%;
          position: absolute;
          z-index: 11;
        }
        // 粒子背景-大罐
        .boxPointImg {
          width: 189px;
          height: 170px;
          position: absolute;
          top: 90px;
          left: 5px;
          z-index: 8;
        }
      }
      .rotateJar {
        .boxPointImg {
          width: 189px;
          height: 170px;
          position: absolute;
          top: 90px;
          left: 5px;
          z-index: 8;
        }
      }
    }
  }
  //油罐狀態
  .centerWrap-bottom {
    width: 100%;
    height: 40%;
    position: absolute;
    left: 0;
    bottom: 0;
    .tabsWrap {
      width: 100%;
      height: 35px;
      line-height: 35px;
      margin-bottom: 15px;
      display: flex;
      justify-content: space-between;
      .tabsCenter {
        width: calc(100% - 50px);
        height: 100%;
        position: relative;
        overflow: hidden;
        .tabsGroup {
          width: 2000px;
          height: 100%;
          position: absolute;
          left: 0;
          top: 0;
          transition: left 1s ease;
          .tabsItem {
            width: 137px;
            height: 100%;
            display: inline-block;
            vertical-align: top;
            white-space: nowrap;
            margin: 0 4px;
            // background: url("~@/assets/images/screen/tabsItem.png") no-repeat;
            background: #8389a2;
            background-size: 100% 100%;
            font-size: 18px;
            font-family: Microsoft YaHei;
            font-weight: 400;
            text-align: center;
            color: #ffffff;
            cursor: pointer;
          }
          .tabsItem:hover {
            color: #00e4ff;
          }
          .tabsItemActive {
            // background: url("~@/assets/images/screen/tabsItemActive.png")
            //   no-repeat;
            // background-size: 100% 100%;
            background: #aad1f7;
          }
        }
      }
      .toPage {
        width: 21px;
        height: 35px;
        line-height: 35px;
        cursor: pointer;
        color: #8389a2;
        text-align: center;
        // background: url("~@/assets/images/screen/to.png") no-repeat;
        // background-size: 100% 100%;
        font-size: 14px;
      }
      .toLeft {
        margin-right: 4px;
      }
      .toRight {
        margin-left: 4px;
      }
      .active {
        color: #fff;
      }
    }
  }
}
</style>

相關文章