效果:

 该时间轴每页最多默认展示三条数据,根据后台数据而定,超过三条前端分页处理;

注:

该时间轴展示的是每条工程数据的鸟瞰图,照片可多张,利用el-carousel、el-image-viewer插件,走马灯效果,可图片预览;

组件代码:

<template>
  <div class="m-timeline-wrap">
    <div class="m-time-dot">
      <!-- 左 箭头图标 -->
      <button
        class="timeLine_left_arrow"
        @click="leftShiftFn"
        :disabled="imgIndex == 0"
      >
        <img src="../../../assets/images/homePage/arrow-l-b.png" alt="" />
      </button>
      <div
        :class="['m-dot-box', { active: active === index }]"
        @click="onClickYear(index)"
        v-for="(item, index) in yeardata && yeardata.length
          ? yeardata[this.imgIndex]
          : []"
        :key="index"
      >
        <!-- 主轴 -->
        <div class="u-img" v-if="active === index" @click="imageItemFun(item)">
          <el-carousel height="126px">
            <el-carousel-item
              v-for="itemImg in item.viewUrl.split(',')"
              :key="itemImg"
            >
              <h3 class="small"><img :src="itemImg" alt="" /></h3>
            </el-carousel-item>
          </el-carousel>
        </div>
        <p class="u-year">{{ item.viewTime }}</p>
        <div class="m-dot">
          <div class="u-dot"></div>
        </div>
      </div>
      <!-- 右 箭头图标 -->
      <button
        class="timeLine_right_arrow"
        @click="rightShiftFn"
        :disabled="imgIndex == yeardata.length - 1 || yeardata.length == 0"
      >
        <img src="../../../assets/images/homePage/arrow-r-b.png" alt="" />
      </button>
    </div>
    <div class="wrap">
      <!-- <div class="content" @click="showImgViewer"></div> -->
      <el-image-viewer
        v-if="imgViewerVisible"
        :on-close="closeImgViewer"
        :url-list="imgList"
      />
    </div>
  </div>
</template>
<script>
export default {
  name: "HorizonTimeLine",
  props: {
    timelineData: {
      // 时间轴数据
      type: Array,
      required: true,
      default: () => {
        return [];
      },
    },
  },
  watch: {
    timelineData: {
      handler(newVal, oldVal) {
        this.setTime(); // 延时1秒调用方法,等待父组件的传参返回
        //默认选中第一条数据
        this.active = 0;
        this.imgIndex=0
      },
      deep: true,
      immediate: true,
    },
  },
  components: {
    "el-image-viewer": () =>
      import("element-ui/packages/image/src/image-viewer"),
  },
  data() {
    return {
      imgViewerVisible: false,
      imgList: [
        "https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg",
        "https://fuss10.elemecdn.com/1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg",
      ],
      active: 0,
      yeardata: [],
      imgIndex: 0,
    };
  },
  created() {
    this.setTime(); // 延时1秒调用方法,等待父组件的传参返回
  },
  mounted() {},
  methods: {
    getData() {
      // 使用父组件传过来的数据,进行新的请求
      //三等分  取余
      const result = this.timelineData.reduce((acc, curr, index) => {
        if (index % 3 === 0) acc.push([]);
        acc[Math.floor(index / 3)].push(curr);
        return acc;
      }, []);
      this.yeardata = result; //默认选中每一组的第一条数据
    },
    setTime() {
      // 定时器,延时调用方法
      let win = this;
      setTimeout(function () {
        win.getData(); // 获取数据
      });
    },
    imageItemFun(e) {
      // 数据处理
      this.imgList = e.viewUrl.split(",");
      this.imgViewerVisible = true;
    },
    // showImgViewer() {
    //   this.imgViewerVisible = true;
    //   const m = (e) => {
    //     e.preventDefault();
    //   };
    //   document.body.style.overflow = "hidden";
    //   document.addEventListener("touchmove", m, false); // 禁止页面滑动
    // },
    closeImgViewer() {
      this.imgViewerVisible = false;
      const m = (e) => {
        e.preventDefault(); //取消默认事件
      };
      document.body.style.overflow = "auto";
      document.removeEventListener("touchmove", m, true);
    },
    onClickYear(index) {
      if (this.active !== index) {
        this.active = index;
      }
    },
    // 左右切换页码
    leftShiftFn() {
      this.imgIndex--;
      this.active = 0;
      this.$emit("changeYearFun", this.active);
    },
    rightShiftFn() {
      this.imgIndex++;
      this.active = 0;
      this.$emit("changeYearFun", this.active);
    },
  },
};
</script>
<style lang="less" scoped>
@themeColor: #1890ff;
@onicon:url ("../../../assets/images/homePage/dot-b-on.png");
@noicon:url ("../../../assets/images/homePage/dot-b.png");
button[disabled] {
  color: white !important;
  cursor: not-allowed !important;
}
.el-image-viewer__wrapper {
  z-index: 99999 !important;
}
.content {
  width: 100%;
  height: 1500px;
  background: pink;
}

.m-timeline-wrap {
  width: 60%;
  height: 10px;
  background: url("../../../assets/images/homePage/bg-line-b.png") no-repeat;
  background-size: 100%;
  position: absolute;
  bottom: 30px;
  left: 20%;
  z-index: 9990;
  .m-time-dot {
    display: flex;
    justify-content: space-between;
    margin-top: 30px;
    .timeLine_left_arrow {
      position: relative;
      bottom: 53px;
      cursor: pointer;
      background: rgba(0, 0, 0, 0);
      border: none;
    }
    .timeLine_right_arrow {
      position: relative;
      bottom: 53px;
      cursor: pointer;
      background: rgba(0, 0, 0, 0);
      border: none;
    }
    .m-dot-box {
      cursor: pointer;
      text-align: center;
      transform: translateY(-56px);
      // position: relative;
      .u-year {
        font-size: 16px;
        font-weight: 500;
        color: #77a4c7;
        transform: translateY(35px);
        transition: all 0.3s ease;
      }
      ::v-deep .u-img {
        width: 193px;
        // height: auto;
        min-height: 126px;
        position: absolute;
        bottom: 25px;
        left: -55px;
        // border: 1px solid #fff;
        transform: translateY(-35px);
        transition: all 1s ease;

        .el-carousel .el-carousel--horizontal {
          width: 100%;
          height: 100% !important;
          overflow: hidden;
          .el-carousel__container{
            height: 100% !important;
          }
          .el-carousel__item .is-active .is-animating{
            width: 100%;
            height: auto;
          }
        }
        .el-carousel__item h3 {
          color: #475669;
          font-size: 14px;
          opacity: 0.75;
          line-height: 62px;
          margin: 0;
        }

        .el-carousel__item:nth-child(2n) {
          background-color: #99a9bf;
        }

        .el-carousel__item:nth-child(2n + 1) {
          background-color: #d3dce6;
        }
        img {
          width: 100%;
          height: 100%;

          display: block;
        }
      }
      .m-dot {
        margin: 0 auto;
        width: 14px;
        height: 14px;
        // background: #8dc6f5;
        background: url("../../../assets/images/homePage/dot-b.png");
        background-size: 100%;
        border-radius: 50%;
        transition: all 0.3s ease;
        .u-dot {
          width: 14px;
          height: 14px;
          background: url("../../../assets/images/homePage/dot-b.png");
          border-radius: 50%;
          transition: all 0.3s ease;
        }
      }
    }
    .m-dot-box:hover {
      .u-year {
        color: @themeColor;
      }
      .m-dot {
        .u-dot {
          //   background: @themeColor;
          background: url("../../../assets/images/homePage/dot-b-on.png");
          background-size: 100%;
        }
      }
    }
    .active {
      .u-year {
        transform: scale(1) translateY(45px); // 同时设置多个transform属性只需用空格间隔,执行时从后往前执行!
        color: @themeColor;
      }
      .m-dot {
        transform: scale(3);
        .u-dot {
          transform: scale(0.67);
          background: url("../../../assets/images/homePage/dot-b-on.png");
          background-size: 100%;
        }
      }
    }
  }
}
</style>

 

注意:多张图片是以字符串形式传过来的,需对其进行二次处理,如上

页面 调用:

<body>
    <HorizonTimeLine
      :timelineData="timelineData"
    >
</body>

<script>
     //时间节点获取
    getTimeNodeList() {
      let params = {
        keyProjectId: this.projectInfolist?.id,
        businessCode: this.$bus.businessCode,
      };
      $get(getKeyProjectTimeNodeListUrl, params).then((res) => {
        this.timelineData = res.data.data;
      });
    },

</script>

希望对大家有所帮助,如有不妥,多多包涵。。。

Logo

前往低代码交流专区

更多推荐