vue实现仿阿里云官网的ace-view-fullColumn模块

15 篇文章 1 订阅
7 篇文章 0 订阅

ace-view-fullColumn

案例:阿里云官网(https://www.aliyun.com)下方的“全面、专业、智能的解决方案”模块
在这里插入图片描述
自己实现出来的效果:

在这里插入图片描述
2021.11.17优化更新:
在这里插入图片描述

在项目中封装成模块使用:
在这里插入图片描述

gitee仓库:https://gitee.com/Yuzaki-Nasa/aliyun-ace-view-fullColumn


vue实现:

<template>
  <div class="common-fadein">
    <div class="bg">
      <div class="view-center">
        <div
          class="core-container"
          @mouseenter="textOpacity = 0"
          @mouseleave="textOpacity = 1"
        >
          <div
            class="col"
            :class="colFocus == item.id ? 'defaultHover-col' : ''"
            v-for="item of coreCol"
            :key="item.id"
            @mouseenter="colFocus = item.id"
          >
            <div
              class="item"
              :class="
                colFocus == item.id
                  ? isBottom == 0
                    ? 'isFocus'
                    : 'isnotFocus'
                  : ''
              "
              @mouseenter="focusItem(0)"
              @mouseleave="outItem()"
            >
              <div
                class="showCore"
                v-if="colFocus == item.id && isBottom == 0"
                :style="
                  colFocus == item.id
                    ? `background:url(${item.children.topImg}) no-repeat;backgroundSize: cover;`
                    : ''
                "
              >
                <h3 class="focus-title">
                  {{ item.children.topTitle }}
                </h3>
                <p class="focus-content" :style="`opacity:${textOpacity}`">
                  {{ item.children.topContent }}
                </p>
              </div>
              <div v-else class="commonCore">
                <h5>{{ item.children.topTitle }}</h5>
                <img :src="item.children.topLogo" alt="" />
              </div>
            </div>
            <div
              class="item"
              :class="
                colFocus == item.id
                  ? isBottom == 1
                    ? 'isFocus'
                    : 'isnotFocus'
                  : ''
              "
              @mouseenter="focusItem(1)"
              @mouseleave="outItem()"
            >
              <div
                class="showCore"
                v-if="colFocus == item.id && isBottom == 1"
                :style="
                  colFocus == item.id
                    ? `background:url(${item.children.bottomImg}) no-repeat;backgroundSize: cover;`
                    : ''
                "
              >
                <h3 class="focus-title">
                  {{ item.children.bottomTitle }}
                </h3>
                <p class="focus-content" :style="`opacity:${textOpacity}`">
                  {{ item.children.bottomContent }}
                </p>
              </div>
              <div v-else class="commonCore">
                <h5>{{ item.children.bottomTitle }}</h5>
                <img :src="item.children.bottomLogo" alt="" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
let timer = null
export default {
  data() {
    return {
      coreCol: [
        // 遍历每个item里的内容
        {
          id: 0,
          children: {
            topTitle: '跨平台开发框架',
            topContent: 'DolphinWeex, MiniX等跨平台开发框架',
            topLogo: require('../assets/ui_img/CoreProducts/kptkfkj_logo@3x.png'),
            bottomTitle: '移动测试',
            bottomContent:
              '7x24小时不间断的云测服务,UI自动化测试、兼容测试、性能测试等,保证APP质量',
            bottomLogo: require('../assets/ui_img/CoreProducts/ydcs_logo@3x.png'),
            topImg: require('../assets/ui_img/CoreProducts/kptkfkj@2x.png'),
            bottomImg: require('../assets/ui_img/CoreProducts/ydcs@2x.png')
          }
        },
        {
          id: 1,
          children: {
            topTitle: 'UI组件库',
            topContent: '前端组件库、原生组件库',
            topLogo: require('../assets/ui_img/CoreProducts/uizjk_logo@3x.png'),
            bottomTitle: '安全',
            bottomContent:
              '自动化加固APP,防止黑客通过反编译获取美居APP的源码,同时支持安全扫描APP漏洞',
            bottomLogo: require('../assets/ui_img/CoreProducts/aq_logo@3x.png'),
            topImg: require('../assets/ui_img/CoreProducts/uizjk@2x.png'),
            bottomImg: require('../assets/ui_img/CoreProducts/aq@2x.png')
          }
        },
        {
          id: 2,
          children: {
            topTitle: '配网SDK',
            topContent: '智能支持AP、蓝牙等配网的SDK',
            topLogo: require('../assets/ui_img/CoreProducts/pwsdk_logo@3x.png'),
            bottomTitle: '版本发布',
            bottomContent:
              '支持App灰度发布,A/B Test等,保证App无风险上线,再发布到对应的渠道',
            bottomLogo: require('../assets/ui_img/CoreProducts/bbfb_logo@3x.png'),
            topImg: require('../assets/ui_img/CoreProducts/pwsdk@2x.png'),
            bottomImg: require('../assets/ui_img/CoreProducts/bbfb@2x.png')
          }
        },
        {
          id: 3,
          children: {
            topTitle: '项目构建',
            topContent:
              '支持研发、测试、发布、运维等阶段自动化构建,实现交付流程化、自动化、数字化',
            topLogo: require('../assets/ui_img/CoreProducts/xmgj_logo@3x.png'),
            bottomTitle: '质量监控',
            bottomContent:
              '实时采集监控App线上问题,及时报警反馈,帮助开发人员快速定位问题原因,减少Bug',
            bottomLogo: require('../assets/ui_img/CoreProducts/zljk_logo@3x.png'),
            topImg: require('../assets/ui_img/CoreProducts/xmgj@2x.png'),
            bottomImg: require('../assets/ui_img/CoreProducts/zljk@2x.png')
          }
        },
        {
          id: 4,
          children: {
            topTitle: '代码质量',
            topContent:
              '支持Android, iOS等多语言代码质量检查,提前预警代码中可能的错误,减少线上Bug',
            topLogo: require('../assets/ui_img/CoreProducts/dmzl_logo@3x.png'),
            bottomTitle: '远程日志捞取',
            bottomContent:
              '远程捞取用户日志(不包括用户隐私数据),助力开发解决线上疑难杂症,提升App质量',
            bottomLogo: require('../assets/ui_img/CoreProducts/ycrzlq_logo@3x.png'),
            topImg: require('../assets/ui_img/CoreProducts/dmzl@2x.png'),
            bottomImg: require('../assets/ui_img/CoreProducts/ycrzlq@2x.png')
          }
        },
        {
          id: 5,
          children: {
            topTitle: '包体扫描',
            topContent:
              '包体积“健康体检”,发现无用资源,冗余文件等,动态横向对比新增内容,减少包体积大小',
            topLogo: require('../assets/ui_img/CoreProducts/btsm_logo@3x.png'),
            bottomTitle: '移动热修复',
            bottomContent:
              '自研Hotfix技术,提供细粒度热修复能力,无需发的APP版本等待,实时修复应用线上问题',
            bottomLogo: require('../assets/ui_img/CoreProducts/ydrxf_logo@3x.png'),
            topImg: require('../assets/ui_img/CoreProducts/btsm@2x.png'),
            bottomImg: require('../assets/ui_img/CoreProducts/ydrxf@2x.png')
          }
        }
      ],
      colFocus: 0, // 判断鼠标当前悬浮在第几个col
      isBottom: 0, // 判断是item是上层or下层,0为上,1为下
      textOpacity: 1 //  用透明度来平滑变化focus-content的显示隐藏
    }
  },
  methods: {
    // 鼠标移入时让内容渐显(控制透明度)
    focusItem(val) {
      this.isBottom = val
      if (timer) {
        clearTimeout(timer)
      }
      timer = setInterval(() => {
        this.textOpacity = this.textOpacity + 0.2
        if (this.textOpacity >= 1) {
          clearTimeout(timer)
        }
      }, 50)
    },
    outItem() {
      this.textOpacity = 0
    }
  }
}
</script>

<style lang="scss">
.common-fadein {
  .bg {
    width: 100%;
    background: #0f1633;

    .view-center {
      width: 1160px;
      margin: 0 auto;

      .core-container {
        height: 289px;
        display: flex;
        overflow: hidden;

        .col {
          flex: 1;
          transition: all 0.4s;

          height: 100%;
          display: flex;
          flex-direction: column;

          .item {
            flex: 1;
            height: 100%;
            transition: all 0.4s;
            box-sizing: border-box;
            border-left: 1px solid rgba($color: #fff, $alpha: 0.2);
            border-top: 1px solid rgba($color: #fff, $alpha: 0.2);

            .showCore {
              height: 100%;
              padding-top: 20px;
              position: relative;
              .focus-title {
                margin: 0px 20px 25px;
                font-size: 16px;
                color: #ffffff;
                text-align: left;
              }

              .focus-content {
                width: 356px;
                transition: all 0.4s;
                margin: 0px 20px 0px;
                font-size: 14px;
                color: #ffffff;
                text-align: left;
                position: absolute;
                top: 61px;
              }
            }

            .commonCore {
              h5 {
                margin: 20px;
                font-size: 14px;
                color: #ffffff;
                text-align: left;
              }
              img {
                float: left;
                margin-left: 20px;
                width: 46px;
                height: 46px;
                // background: #696d7f; 
              }
            }
          }

          .item:nth-child(1) {
            border-top: 0;
          }

          .isFocus {
            background: #064dcb;
            border-top: 0px !important;
            border-left: 0px !important;
          }
          .isnotFocus {
            height: 0%;
            flex: 0;
          }
        }
        .col:nth-last-child(1) {
          border-right: 0;
        }

        .col:nth-child(1) .item {
          border-left: 0 !important;
        }

        .defaultHover-col {
          flex: 2.63 !important;
          background-size: cover;
        }
      }
    }
  }
}
</style>

一些感想:

每一列是一个col,横向flex布局,鼠标没移入时flex:1,鼠标悬停时flex:2.63(该数值为具体设计稿“放大时的宽 / 原来的宽”)。
每一列内有上下两个item,纵向flex布局,鼠标没移入时flex:1,鼠标移入后,未被选中的item的flex:0、height:0,再给最外层的元素加个overflow:hidden即可。

用colFocus判断当前选中的是第几个col,再用isBottom判断是上/下item,给满足选中条件的格子加类名isFocus,没选中的加类名isnotFocus。

样式的过渡(flex数值)使用transition: all 0.4s;实现平滑变化。

遇到的问题:选中元素的内容文本,若根据flex的变大而展开宽度,文变量多的时候交互体验就会很差(因为宽度不足的时候会换行,宽度渐渐变大则使得文本从竖长条变成横长条),于是给内容文本加了个透明度的过渡,即:style="opacity:${textOpacity}",然后让textOpacity在350毫秒后随循环计时器每50毫秒+0.2,直到完全不透明(opacity: 1)。
但这个方法说实话是比较low的,后来想到v-if似乎也可以实现平滑展示效果,等之后有时间再改进吧。

2021.11.17更新:解决上诉问题只需把选中元素加个相对定位、其内容文本设成绝对定位再设个固定的宽就可以了,也不用多等350毫秒了,体验相对会好一些。


End:

如果该组件有帮助到您,请给我的gitee点亮星星~
thx!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值