javascript css实现3d轮播图

11 篇文章 0 订阅
11 篇文章 0 订阅

 Vue 代码

<template>
  <div class="mobile-unit">
    <div class="mobile-unit-container">
      <div class="items">
        <div
          class="mobile-unit-item five-in-one"
          :class="[{ 'is-active': currentComponent === 'FiveInOne' }]"
          @click="toggleComponent('FiveInOne')"
          v-show="equipmentData.data.indexOf('五合一') !== -1"
          ref="FiveInOne"
        >
          <i></i>
          <span>五合一</span>
        </div>
        <div
          class="mobile-unit-item ozone-radar"
          :class="[{ 'is-active': currentComponent === 'OzoneRadar' }]"
          @click="toggleComponent('OzoneRadar')"
          v-show="equipmentData.data.indexOf('雷达') !== -1"
          ref="OzoneRadar"
        >
          <i></i>
          <span>雷达</span>
        </div>
        <div
          class="mobile-unit-item mass-spectrometer"
          :class="[{ 'is-active': currentComponent === 'MassSpectrometer' }]"
          @click="toggleComponent('MassSpectrometer')"
          v-show="equipmentData.data.indexOf('质谱仪') !== -1"
          ref="MassSpectrometer"
        >
          <i></i>
          <span>质谱仪</span>
        </div>
        <div
          class="mobile-unit-item ship"
          :class="[{ 'is-active': currentComponent === 'UnmannedShip' }]"
          @click="toggleComponent('UnmannedShip')"
          v-show="equipmentData.data.indexOf('无人船') !== -1"
          ref="UnmannedShip"
        >
          <i></i>
          <span>无人船</span>
        </div>
        <div
          class="mobile-unit-item portable-equipment"
          :class="[{ 'is-active': currentComponent === 'PortableEquipment' }]"
          @click="toggleComponent('PortableEquipment')"
          v-show="equipmentData.data.indexOf('便携设备') !== -1"
          ref="PortableEquipment"
        >
          <i></i>
          <span>便携设备</span>
        </div>
        <div
          class="mobile-unit-item uav"
          :class="[{ 'is-active': currentComponent === 'Uav' }]"
          @click="toggleComponent('Uav')"
          v-show="equipmentData.data.indexOf('无人机') !== -1"
          ref="Uav"
        >
          <i></i>
          <span>无人机</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import {
  ref,
  reactive,
  watch,
  getCurrentInstance,
  onMounted,
  onUnmounted,
  onDeactivated,
} from "vue";

export default {
  setup() {
    let currentComponent = ref(null);
    let FiveInOne = ref(null);
    let OzoneRadar = ref(null);
    let MassSpectrometer = ref(null);
    let UnmannedShip = ref(null);
    let PortableEquipment = ref(null);
    let Uav = ref(null);
    let timers = [];
    const toggleComponent = (value) => {
      currentComponent.value = currentComponent.value !== value ? value : null;
      if (equipmentData.data.length <= 1) return;
      if (currentComponent.value) {
        timers.forEach((item) => {
          clearInterval(item);
        });
      } else {
        starRotate(true);
      }
    };

    let equipmentData = reactive({
      data: ["便携设备", "无人机", "无人船", "质谱仪", "雷达", "五合一"],
    });

    onDeactivated(() => {
      timers.forEach((item) => {
        clearInterval(item);
      });
    });
    onUnmounted(() => {
      timers.forEach((item) => {
        clearInterval(item);
      });
    });
    onMounted(() => {
      console.log("onmounted了");

      watch(
        () => equipmentData.data,
        (value) => {
          starRotate(false);
        },
        { deep: true, immediate: true }
      );
    });

    function starRotate(isPause) {
      if (equipmentData.data.length <= 1) return;
      let part = 360 / equipmentData.data.length;
      let PortableEquipmentStyle = PortableEquipment.value.style.transform;
      let UavStyle = Uav.value.style.transform;
      let UnmannedShipStyle = UnmannedShip.value.style.transform;
      let MassSpectrometerStyle = MassSpectrometer.value.style.transform;
      let OzoneRadarStyle = OzoneRadar.value.style.transform;
      let FiveInOneStyle = FiveInOne.value.style.transform;

      equipmentData.data.forEach((item, index) => {
        switch (item) {
          case "便携设备":
            //获取角度
            let PortableEquipmentAngle = isPause
              ? PortableEquipmentStyle.split("deg")[0].split("(")[1]
              : part * index;
            //判断是否是暂停
            PortableEquipmentStyle = isPause
              ? PortableEquipmentStyle
              : `rotateY(${PortableEquipmentAngle}deg) translateZ(210px)`;
            timers.push(
              rotate(PortableEquipment, PortableEquipmentAngle, part)
            );
            break;

          case "无人机":
            //获取角度
            let UAVAngle = isPause
              ? UavStyle.split("deg")[0].split("(")[1]
              : part * index;
            //判断是否是暂停
            UavStyle = isPause
              ? UavStyle
              : `rotateY(${UAVAngle}deg) translateZ(210px)`;
            timers.push(rotate(Uav, UAVAngle, part));
            break;
          case "无人船":
            //获取角度
            let UnmannedShipAngle = isPause
              ? UnmannedShipStyle.split("deg")[0].split("(")[1]
              : part * index;
            //判断是否是暂停
            UnmannedShipStyle = isPause
              ? UnmannedShipStyle
              : `rotateY(${UnmannedShipAngle}deg) translateZ(210px)`;
            timers.push(rotate(UnmannedShip, UnmannedShipAngle, part));
            break;
          case "质谱仪":
            //获取角度
            let MassSpectrometerAngle = isPause
              ? MassSpectrometerStyle.split("deg")[0].split("(")[1]
              : part * index;
            //判断是否是暂停
            MassSpectrometerStyle = isPause
              ? MassSpectrometerStyle
              : `rotateY(${MassSpectrometerAngle}deg) translateZ(210px)`;
            timers.push(rotate(MassSpectrometer, MassSpectrometerAngle, part));
            break;
          case "雷达":
            //获取角度
            let OzoneRadarAngle = isPause
              ? OzoneRadarStyle.split("deg")[0].split("(")[1]
              : part * index;
            //判断是否是暂停
            OzoneRadarStyle = isPause
              ? OzoneRadarStyle
              : `rotateY(${OzoneRadarAngle}deg) translateZ(210px)`;
            timers.push(rotate(OzoneRadar, OzoneRadarAngle, part));
            break;
          case "五合一":
            //获取角度
            let FiveInOneAngle = isPause
              ? FiveInOneStyle.split("deg")[0].split("(")[1]
              : part * index;
            //判断是否是暂停
            FiveInOneStyle = isPause
              ? FiveInOneStyle
              : `rotateY(${FiveInOneAngle}deg) translateZ(210px)`;
            timers.push(rotate(FiveInOne, FiveInOneAngle, part));
            break;
          default:
            break;
        }
      });
    }

    function rotate(dom, angle, part) {
      if (!dom.value) return;
      return setInterval(() => {
        //减去每个步长即每块div所占的角度
        angle -= part;
        dom.value.style.transform = `rotateY(${angle}deg) translateZ(210px)`;
      }, 2000);
    }

    return {
      currentComponent,
      toggleComponent,
      equipmentData,
      FiveInOne,
      OzoneRadar,
      MassSpectrometer,
      UnmannedShip,
      PortableEquipment,
      Uav,
    };
  },
};
</script>

<style lang="scss" scoped>
.mobile-unit {
  margin-top: 20px;
  width: 100%;
  height: 100%;
  background: rgba(12, 12, 57, 0.2);

  .mobile-unit-container {
    position: relative;
    width: 420px;
    height: 350px;
    margin: 3px auto;
    perspective: 10000px;
    background: url(~@/assets/img/dark/round.png) no-repeat center center;
    // transform-style: preserve-3d;
    .items {
      width: 112px;
      height: 124px;
      transition: transform 1s;
      transform-style: preserve-3d;
      position: absolute;
      left: 37%;
      top: 30%;
      transform: rotateX(340deg);
    }

    .navigation-vehicle {
      position: relative;

      margin: 0 auto;
      width: 276px;
      height: 248px;

      background: url(~@/assets/img/dark/round.png) no-repeat;
      background-size: contain;
      background-position-y: 70px;

      cursor: pointer;

      > canvas {
        position: absolute;
        top: 0;
        left: calc(50% - 150px);

        width: 300px;
        height: 200px;

        outline: none;
      }
    }
    .mobile-unit-item {
      position: absolute;
      bottom: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: space-between;
      width: 112px;
      height: 124px;
      padding: 10px 0px 25px 0;
      background: url(~@/assets/img/dark/equipment.png) no-repeat;
      transition: all 1s;
      i {
        width: 45px;
        height: 45px;
        background-color: rgba(0, 244, 255, 0.1);
        background-position: center;
        background-repeat: no-repeat;
        // border: 1px dashed #00f4ff;
        border-radius: 50%;
        cursor: pointer;
      }
      span {
        font-size: 14px;

        color: #fff;
        cursor: pointer;
      }
    }
    .mobile-unit-item.is-active {
      i {
        border-color: #ff8104;
      }

      span {
        color: #ff8104;
      }
    }
    .is-active {
      background-image: url(~@/assets/img/dark/equipment-active.png);
    }
    .five-in-one {
      //transform: rotateY(0) translateZ(210px);
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-five-in-one.png);
      }
    }
    .five-in-one.is-active {
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-five-in-one-active.png);
      }
    }

    .ozone-radar {
      //transform: rotateY(60deg) translateZ(210px);
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-ozone-radar.png);
      }
    }
    .ozone-radar.is-active {
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-ozone-radar-active.png);
      }
    }

    .mass-spectrometer {
      //transform: rotateY(120deg) translateZ(210px);
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-mass-spectrometer.png);
      }
    }
    .mass-spectrometer.is-active {
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-mass-spectrometer-active.png);
      }
    }

    .ship {
      //transform: rotateY(180deg) translateZ(210px);
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-ship.png);
      }
    }
    .ship.is-active {
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-ship-active.png);
      }
    }

    .portable-equipment {
      //transform: rotateY(240deg) translateZ(210px);
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-portable-equipment.png);
      }
    }
    .portable-equipment.is-active {
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-portable-equipment-active.png);
      }
    }

    .uav {
      //transform: rotateY(300deg) translateZ(210px);
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-uav.png);
      }
    }
    .uav.is-active {
      i {
        background-image: url(~@/assets/img/home/mobileUnit/icon-uav-active.png);
      }
    }
  }
}
@keyframes rotate {
}
</style>

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值