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!