vue+antdesign 实现九宫格加弓字形左右下箭头

设计效果:

需求:

图片是九宫格布局,第一排图片之间的箭头为右箭头,第二排箭头为左箭头,以此类推,下箭头需求是以弓字形显示,卡片右侧内容Hover的时候要出现tip

注意最后一排不足三个的时候要隐藏横向箭头,并隐藏下箭头

子组件 

html:

<template>
  <div class="visitor-track-container">
    <div
      v-for="(item,i) in list"
      :key="i+Math.random()"
      class="visitor-track-content"
    >
      <div
        :key="i+ Math.random()"
        class="visitor-track-info"
      >
        <!-- 左箭头 -->
        <div class="visitor-track-arrow-left">
          <p class="visitor-track-arrow-desc">
            <!-- 耗时x天x时x分x秒 -->
            {
   
   {item.differenceTime}}
          </p>
          <p class="arrow-left">
          </p>
        </div>
        <!-- 照片卡片 -->
        <div class="visitor-track-box">
          <a-avatar
            class="visitor-track-img"
            shape="square"
            :src="item.snapUrl"
            @click="handlerImg(item)"
          />
          <div class="visitor-track-right">
            <p>
              <a-tooltip>
                <template slot="title">
                  <!-- 区域信息 -->
                  {
   
   {item.cameraRegion}}
                </template>
                {
   
   {item.cameraRegion}}
              </a-tooltip>
            </p>
            <p>
              <a-tooltip>
                <!-- 摄像头名称 -->
                <template slot="title">
                  {
   
   {item.cameraName}}
                </template>
                {
   
   {item.cameraName}}
              </a-tooltip>
            </p>
            <p :class="['visitor-track-similarity',item.similarity<=50?'similarity':'']">
              <a-tooltip>
                <template slot="title">
                  相似度:{
   
   {item.similarity||0}}%
                </template>
                相似度:{
   
   {item.similarity||0}}%
              </a-tooltip>
            </p>
            <p>
              <a-tooltip>
                <template slot="title">
                  <!-- 时间 -->
                  {
   
   {item.eventTime}}
                </template>
                {
   
   {item.eventTime}}
              </a-tooltip>
            </p>
          </div>
          <div>
          </div>
        </div>
        <!-- 右箭头 -->
        <div class="visitor-track-arrow-right">
          <p class="visitor-track-arrow-desc">
            <!-- 耗时x天x时x分x秒 -->
            {
   
   {item.differenceTime}}
          </p>
          <p class="arrow-right">
          </p>
        </div>

      </div>
      <!-- 下箭头 -->
      <div :class="{visitorTrackArrowBottom:true, showRightArrowBottom:(i + 1)%3==0&&(i + 1)%6!=0?true:false, showLeftArrowBottom:i %3==0&&(i)%2!=0?true:false,hideBottomArrowLast:setArrow(i)}">
        <i class="arrow-bottom"></i>
        <p class="visitor-track-arrow-desc"> {
   
   {item.differenceTime}}</p>
      </div>
    </div>
  </div>
</template>

js:

<script>
export default {
  name: 'TrajectoryChart',
  props: {
    list: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {}
  },
  computed: {},
  methods: {
    // 当最后一行不足3个或刚好三个时去掉最后一行的(左)下箭头
    setArrow(i) {
      if (this.list.length % 3 == 0) {
        if (
          i == this.list.length - 1 ||
          i == this.list.length - 2 ||
          i == this.list.length - 3
        ) {
          return true
        }
        console.log('余', 0)
      } else if (this.list.length % 3 == 1) {
        if (i == this.list.length - 1) {
          return true
        }
        console.log('余', 1)
      } else if (this.list.length % 3 == 2) {
        if (i == this.list.length - 1 || i == this.list.length - 2) {
          return true
        }
        console.log('余', 2)
      }
    },
    // 查看大图
    handlerImg(item) {
      this.$emit('onImg', item)
    }
  }
}
</script>

 css


 .visitor-track-container {
  display: flex;
  flex-wrap: wrap;
  .visitor-track-content {
    width: 40%;
    display: flex;
    flex-direction: column;

    // TODO:删除
    // 选中1,4,7,10...之间的偶数,2,5,8..之间的偶数,3,6,9...之前的偶数
    &:nth-child(3n + 1):nth-child(2n),
    &:nth-child(3n + 2):nth-child(odd),
    &:nth-child(3n):nth-child(2n) {
      color: red;
    }
    .visitor-track-info {
      display: flex;
      // align-items: center;
      justify-content: space-around;
      flex-wrap: wrap;
      flex-direction: row;
    }
    //   照片卡片
    .visitor-track-box {
      display: flex;
      padding: 17px 24px;
      background: #f4f4f4;
      .visitor-track-img {
        width: 120px;
        height: 90px;
        margin-right: 24px;
        &:hover {
          cursor: pointer;
        }
      }
      .visitor-track-right {
        font-family: 'PingFang SC';
        font-style: normal;
        font-weight: 400;
        font-size: 14px;
        line-height: 20px;
        color: $second-color-text-1;
        p {
          margin-bottom: 4px;
          span {
            max-width: 126px;
            display: block;
            //   width: 200px;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
          }
        }
        .visitor-track-similarity {
          color: $main-color;
          &.similarity {
            color: $second-color-text-4;
          }
        }
      }
    }
    // 右箭头box
    .visitor-track-arrow-right {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      padding: 0 16px;
      .visitor-track-arrow-desc {
        margin-bottom: 16px;
      }
      .arrow-right {
        position: relative;
        width: 140px;
        min-width: 100%;
        height: 0px;
        border: 2px solid #dddddd;
      }
      .arrow-right::before {
        content: '';
        position: absolute;
        right: -16px;
        top: -10px;
        border: 10px solid transparent;
        border-left: 20px solid #dddddd;
        width: 0;
        height: 0px;
      }
    }
    // 左箭头
    .visitor-track-arrow-left {
      display: flex;
      flex: 1;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      padding: 0 16px;
      .visitor-track-arrow-desc {
        margin-bottom: 16px;
      }
      .arrow-left {
        position: relative;
        width: 140px;
        min-width: 100%;
        height: 0px;
        border: 2px solid #dddddd;
      }
      .arrow-left::before {
        content: '';
        position: absolute;
        right: -16px;
        top: -10px;
        width: 0;
        height: 0px;
        left: -16px !important;
        border: 10px solid transparent;
        border-right: 20px solid #dddddd;
      }
    }
    // 下箭头
    .visitorTrackArrowBottom {
      display: none;
      align-items: center;
      margin: 15px 0 15px 162px;
      .arrow-bottom {
        position: relative;
        height: 50px;
        border: 2px solid #dddddd;
        &::before {
          content: '';
          position: absolute;
          right: -10px;
          bottom: -15px;
          border: 10px solid transparent;
          border-top: 20px solid #dddddd;
          width: 0;
          height: 0px;
        }
      }
      .visitor-track-arrow-desc {
        margin-left: 16px;
        font-family: 'PingFang SC';
        font-style: normal;
        font-weight: 400;
        font-size: 14px;
        line-height: 20px;
        text-align: left;
        color: $second-color-text-1;
      }
      &.showRightArrowBottom {
        display: flex;
      }
      &.showLeftArrowBottom {
        display: flex;
      }
    }
    //   3的倍数下隐藏横向箭头
    &:nth-child(3n + 3) {
      .visitor-track-arrow-right {
        display: none;
      }
    }
    // 隐藏奇排倍数的右箭头
    &:nth-child(3n + 1):nth-child(2n),
    &:nth-child(3n + 2):nth-child(odd),
    &:nth-child(3n):nth-child(2n) {
      .visitor-track-arrow-right {
        display: none;
      }
    }
    // 隐藏偶排的左箭头
    &:not(
        :nth-child(3n + 1):nth-child(2n),
        :nth-child(3n + 2):nth-child(odd),
        :nth-child(3n):nth-child(2n)
      ) {
      color: green;
      .visitor-track-arrow-left {
        display: none;
      }
    }
    //显示右箭头 3的倍数中visitor-track-content占20%宽,选择奇数
    &:nth-child(3n):nth-child(odd) {
      width: 20%;
    }
    //显示左箭头 1,4,7,倍数中占宽20%选择奇数,并隐藏左箭头
    &:nth-child(3n + 1):nth-child(2n) {
      width: 20%;
      .visitor-track-arrow-left {
        display: none;
      }
    }

    // 最后一排隐藏下箭头,清除最后一个卡片的居中布局
    &:last-child {
      .visitor-track-info {
        justify-content: initial;
      }
      .visitor-track-arrow-right {
        display: none;
      }
    }
    .hideBottomArrowLast {
      display: none !important;
    }
  }

  @media screen and (max-width: 1840px) {
    .visitor-track-content {
      width: 38.5%;
      &:nth-child(3n):nth-child(odd) {//为3的倍数下的奇数
      width: 21.5%;
    }
    // //显示左箭头 1,4,7,倍数中占宽20%选择奇数,并隐藏左箭头
    &:nth-child(3n + 1):nth-child(2n) {
      width: 21.5%;
    }
    }
  }
    @media screen and (max-width: 1730px) {
    .visitor-track-content {
      width: 38.5%;
      &:nth-child(3n):nth-child(odd) {//为3的倍数下的奇数
      width: 22.5%;
    }
    // //显示左箭头 1,4,7,倍数中占宽20%选择奇数,并隐藏左箭头
    &:nth-child(3n + 1):nth-child(2n) {
      width: 22.5%;
    }
    }
  }
    @media screen and (max-width: 1670px) {
    .visitor-track-content {
      width: 38.5%;
      &:nth-child(3n):nth-child(odd) {//为3的倍数下的奇数
      width: 23%;
    }
    // //显示左箭头 1,4,7,倍数中占宽20%选择奇数,并隐藏左箭头
    &:nth-child(3n + 1):nth-child(2n) {
      width: 23%;
    }
    }
  }
  @media screen and (max-width: 1600px) {
    .visitor-track-content {
      width: 37%;
         //显示右箭头3的倍数中visitor-track-content占20%宽,选择奇数
    &:nth-child(3n):nth-child(odd) {
      width: 24.5%;
    }
    //显示左箭头 1,4,7,倍数中占宽20%选择奇数
    &:nth-child(3n + 1):nth-child(2n) {
      width: 24.5%;

    }
      .arrow-right,.arrow-left {
        min-width: 100px !important;
        width: 100px !important;
      }
    }
  }
  @media screen and (max-width: 1510px) {
    .visitor-track-box {
      padding: 17px 18px !important;
      .visitor-track-right {
        p {
          span {
            max-width: 108px !important;
            display: block;
          }
        }
      }
    }
    .visitor-track-img {
      width: 110px !important;
      margin-right: 16px !important;
    }
  }
}

父组件内容 

引入子组件并使用,我这里在弓字的时候因为后台没有对2倍数的排数倒序所以这里要处理一下让2倍的数据倒过来


    <!--访客轨迹  -->
<template>
  <div class="xk-container">
 
    <trajectory-chart :list="trajectoryList" @onImg="handlerImg" />
     
  </div>
</template>

<script>

import TrajectoryChart from '@/components/TrajectoryChart'
import test from './../test.json'

export default {
  name: 'VisitorTrack',
  components: { 
    TrajectoryChart
  },
  data() {
    return {
      trajectoryList: [],
         }
  },
  mounted() {
//调用接口,这里是模拟数据
    const doubleArr = []
    for (var i = 0; i < test.data.snapInfoList.length; i += 3) { // 3个为一组转为二维数组
      doubleArr.push(test.data.snapInfoList.slice(i, i + 3))
    }
    // 对奇数组进行倒序
    const doubleArrReverse = doubleArr.map((item, i) => i % 2 !== 0 ? item.reverse() : item)
    console.log('对二的倍数数组进行倒序', doubleArrReverse)
    const linearArr = doubleArrReverse.reduce((a, b) => { return a.concat(b) })// 转一维数组
    this.trajectoryList = linearArr.map((item, i) => {
      return {
        ...item
      }
    })
  
  },
 
  }
}
</script>


json数据 test.json

{
    "respCode": "200",
    "respMsg": "操作成功",
    "data": {
        "guestId": "20221031d1fed47d519f4a68a4e18b02",
        "guestName": "唐兰溪",
        "visitedUserName": "黄小访",
        "avatar": "/gzcss-boot/zhfkfksq/20221203ebrza6t1.jpg",
        "reson": "拜访领导",
        "startTime": "2022-12-04 08:00:00",
        "endTime": "2022-12-04 10:00:00",
        "visitDepart": "总务部",
        "company": "广州xx",
        "snapInfoList": [
            {
                "cameraCode": "5dea797fc94e44e0a528aad02fc36e70",
                "bkgUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDQ3MzIxNjAwMDAxMzExNTAmc2l6ZT0xMzExNTA=&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6RDhsSkZTYVFrVGNFZ0VrMFA3NFVDbDdpMStoSzFNSSsrN3g1SXBJdDJ0ND06MTY4MDA4MDE5NzY3Ng==&urlType=1",
                "snapUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDQ3MzAxMTIwMDAwMTc4Nzgmc2l6ZT0xNzg3OA==&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6ckpnVEtJOXNQTW13QTlrWmlLQW55MmtZejFIQmNLOCtjUXVqWHM5bzY2RT06MTY4MDA4MDE5NzY4Mw==&urlType=1",
                "eventTime": "2023/01/04 08:41:01",
                "locLng": null,
                "locLat": null,
                "locAltitude": null,
                "cameraName": null,
                "similarity": "88%",
                "differenceTime": "耗时:6小时53分钟44秒。"
            },
            {
                "cameraCode": "5dea797fc94e44e0a528aad02fc36e70",
                "bkgUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDc2MzAwODAwMDAxNjUzOTkmc2l6ZT0xNjUzOTk=&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6dVZrYjFvOW1GOVo2K3NjMS9KaGIwb1d5dzJvU3BObDhkMEk0UXR3bHBnaz06MTY4MDA4MDE5NzYwNw==&urlType=1",
                "snapUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDc2Mjc2MjI0MDAwMjM2ODYmc2l6ZT0yMzY4Ng==&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6U253QVpVT0xiakFHTUNyM1ZLUVlFeEdTeXZseHA4TFJFWDJieFJUZ093Yz06MTY4MDA4MDE5NzYxOQ==&urlType=1",
                "eventTime": "2023/01/04 15:34:45",
                "locLng": null,
                "locLat": null,
                "locAltitude": null,
                "cameraName": null,
                "similarity": "90%",
                "differenceTime": "耗时:19秒。"
            },
            {
                "cameraCode": "5dea797fc94e44e0a528aad02fc36e70",
                "bkgUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDc2NTE3ODg4MDAxNjc5MzMmc2l6ZT0xNjc5MzM=&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6QU5uRkwrNnRGN1lYOEU2SkpkSG5PVE9OS3Y2YXpaNHRaUndURXVXKzE4UT06MTY4MDA4MDE5NzM3Nw==&urlType=1",
                "snapUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDc2NDY4NzM2MDAwNDYxMDUmc2l6ZT00NjEwNQ==&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6OXBUWjZ2ZVlVQTh5TU5SNkErMEtvWlRwWnBVd21oR083ckVWSEFhTE9saz06MTY4MDA4MDE5NzM4Ng==&urlType=1",
                "eventTime": "2023/01/04 15:35:04",
                "locLng": null,
                "locLat": null,
                "locAltitude": null,
                "cameraName": null,
                "similarity": "94%",
                "differenceTime": "耗时:27分钟14秒。"
            },

            
            {
                "cameraCode": "5dea797fc94e44e0a528aad02fc36e70",
                "bkgUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDc2ODkwNjI0MDAxNTczOTQmc2l6ZT0xNTczOTQ=&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6Nm85TW05ZkVVVXBKd0RSOGdUU2RNNFFQTmVvV0lCZ0pLeUVYUUF0bVJsaz06MTY4MDA4MDE5NzMyMQ==&urlType=1",
                "snapUrl": "https://192.168.8.36:8376/uis/service/v1/picture/stream/fetch?imgSrc=aHR0cDovLzE5Mi4xNjguOC40MDo4MC9waWN0dXJlL1N0cmVhbWluZy90cmFja3MvMTAzLz9uYW1lPWNoMDAwMDFfMDAwMDAwMDAwMTcwMDc2ODY2MDQ4MDAwMjA4MTMmc2l6ZT0yMDgxMw==&signature=SElLIDZFT1MvZTBqWXI5N3ViWlo6NVpYbzZKNzFsYlVJeGl4elZ2dVZFaS9VbVY3OGExMWp5WjAwRXRSaUVZOD06MTY4MDA4MDE5NzM2OQ==&urlType=1",
                "eventTime": "2023/01/04 16:02:18",
                "locLng": null,
                "locLat": null,
                "locAltitude": null,
                "cameraName": null,
                "similarity": "94%",
                "differenceTime": "耗时:10秒。"
            },
          
          
        ]
    },
    "success": true
}

效果图

猜你喜欢

转载自blog.csdn.net/qq_40190624/article/details/128255053