需求
多个按钮根据弧度,延边均匀排列。
实现
HTML
- 分两级;
- 第一级,外层定义按钮的
compose-container
宽度; - 第二级,按钮集合,使用方法
styleBtn(index)
,根据索引计算;
html
<div class="compose-container flex-style-01">
<div class="btn" v-for="(item, index) in btnNum" :key="index" :style="styleBtn(index)">
{{ index }}
</div>
</div>
CSS
compose-container
:容器样式,使用flex
布局,且设置width
;btn
:按钮样式,无需设置display
;
scss
.compose-container {
display: flex;
width: 600px;
height: 80px;
margin: 50px 0;
background: #409eff;
.btn {
width: 50px;
height: 50px;
line-height: 50px;
background: #aec0d1;
border-radius: 50%;
text-align: center;
vertical-align: middle;
}
}
JavaScript
- 如下方法是计算按钮
translateY
值; - 代码第
2
行,传参是按钮的索引值,从0
开始; - 代码第
4
行,按钮的总个数; - 代码第
6
行,按钮垂直高度间隔,单位px
; - 代码第
8
行,整体抬高,也可不设置; - 代码第
12 - 27
行,区分偶数和奇数,中心点计算; - 代码第
29
行,设置属性translateY
;
js
// 按钮弧度高度
function styleBtn(index) {
// 总个数
const totalNum = 8;
// 间隔高度,单位 px
const gap = 8;
// 整体抬高
const raiseHeight = 28;
let translateY = ''
if(totalNum%2 === 0) { // 偶数
const centerIdx = totalNum / 2;
const n = centerIdx - index;
// > 0 左侧,<= 右侧
translateY = (n > 0) ? n * gap : (Math.abs(n)+1) * gap;
}
else { // 奇数
const centerIdx = Math.floor(totalNum / 2);
const n = centerIdx - index;
if(centerIdx === index) {// 中心点
translateY = gap;
}
else {
translateY = (Math.abs(n)+1) * gap;
}
}
return { transform: `translateY(${(translateY - raiseHeight)}px)` }
}
效果
偶数
- 按钮个数为偶数,中间两个按钮在同一条水平线上;
- 样式一,
justify-content: center
,根据按钮的 margin 属性设置间隔; - 样式二:
justify-content: space-between
,两端对齐,按钮之间的空间平均分配; - 样式三:
justify-content: space-around
,按钮两侧空间相等,但首尾按钮与容器边缘的空间是按钮之间空间的一半; - 样式四:
justify-content: space-evenly
,所有间距(包括首尾按钮与容器边缘的间距)都相等;
奇数
- 按钮个数为奇数,中间一个按钮最高,其它左右两侧在同一条水平线上;
justify-content
设置同上;
完整代码
vue
<template>
<div>
<h4>样式一:justify-content: center, 且设置btn margin </h4>
<div class="compose-container flex-style-01">
<div class="btn" v-for="(item, index) in btnNum" :key="index" :style="styleBtn(index)">
{{ index }}
</div>
</div>
<h4>样式二:justify-content: space-between</h4>
<div class="compose-container flex-style-02">
<div class="btn" v-for="(item, index) in btnNum" :key="index" :style="styleBtn(index)">
{{ index }}
</div>
</div>
<h4>样式三:justify-content: space-around</h4>
<div class="compose-container flex-style-03">
<div class="btn" v-for="(item, index) in btnNum" :key="index" :style="styleBtn(index)">
{{ index }}
</div>
</div>
<h4>样式四:justify-content: space-evenly</h4>
<div class="compose-container flex-style-04">
<div class="btn" v-for="(item, index) in btnNum" :key="index" :style="styleBtn(index)">
{{ index }}
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const btnNum = ref(7);
// 按钮弧度高度
function styleBtn(index) {
// 总个数
const totalNum = btnNum.value;
// 间隔高度,单位 px
const gap = 8;
// 整体抬高
const raiseHeight = 28;
let translateY = ''
if(totalNum%2 === 0) { // 偶数
const centerIdx = totalNum / 2;
const n = centerIdx - index;
// > 0 左侧,<= 右侧
translateY = (n > 0) ? n * gap : (Math.abs(n)+1) * gap;
}
else { // 奇数
const centerIdx = Math.floor(totalNum / 2);
const n = centerIdx - index;
if(centerIdx === index) {// 中心点
translateY = gap;
}
else {
translateY = (Math.abs(n)+1) * gap;
}
}
return { transform: `translateY(${(translateY - raiseHeight)}px)` }
}
</script>
<style lang="scss" scoped>
.compose-container {
display: flex;
width: 600px;
height: 80px;
margin: 50px 0;
background: #409eff;
.btn {
width: 50px;
height: 50px;
line-height: 50px;
background: #aec0d1;
border-radius: 50%;
text-align: center;
vertical-align: middle;
}
}
.flex-style-01 {
justify-content: center;
.btn {
margin: 0 6px;
}
}
.flex-style-02 {
justify-content: space-between;
}
.flex-style-03 {
justify-content: space-around;
}
.flex-style-04 {
justify-content: space-evenly;
}
</style>