dom:
<div class="module-content">
<div class="title">
<span>[</span>
<p>鱼骨图</p>
<span>]</span>
</div>
<div class="line-mian"></div>
<div :ref="'module' + i" v-for="(item,i) in list" :key="i" class="module-pub">
<div :ref="'line' + i" class="line-pub"></div>
<div :ref="'lineOne' + i + j" v-for="(k,j) in item.children" class="module-pub-one">
<div class="line-pub_"></div>
<p>{{k.name}}</p>
</div>
<div :ref="'text' + i" class="module-pub-text">
<p>{{(item.value).toFixed(0)}}%</p>
<p>{{item.name}}</p>
</div>
</div>
</div>
js:
mounted() {
list = [
{
name: '标题1',
value: 15,
children: [
{
name: '内容1-1',
value: 40,
},
{
name: '内容1-2',
value: 20,
},
{
name: '内容1-3',
value: 40,
},
]
},
{
name: '标题2',
value: 15,
children: [
{
name: '内容2-1',
value: 40,
},
{
name: '内容2-2',
value: 20,
},
{
name: '内容2-3',
value: 40,
},
]
},
{
name: '标题3',
value: 25,
children: [
{
name: '内容3-1',
value: 20,
},
{
name: '内容3-2',
value: 20,
},
]
},
{
name: '标题4',
value: 25,
children: [
{
name: '内容4-1',
value: 0,
},
{
name: '内容4-2',
value: 0,
},
{
name: '内容4-3',
value: 0,
},
]
},
{
name: '标题5',
value: 20,
children: [
{
name: '内容5-1',
value: 0,
},
{
name: '内容5-2',
value: 0,
},
{
name: '内容5-3',
value: 0,
},
{
name: '内容5-4',
value: 0,
},
{
name: '内容5-5',
value: 0,
},
]
},
];
this.setStyle();
},
methods: {
setStyle() {
this.$nextTick(()=> {
this.list.forEach((item,i) => {
let left = (i + 1) * 100;
this.$refs['module'+i][0].style.left = left +'px';
let length = (item.children.length + 1) * 40;
this.$refs['line'+i][0].style.width = length +'px';
if (i % 2 === 0) {
this.$refs['line'+i][0].style.transform = 'rotate(' + -30 +'deg)';
} else {
this.$refs['line'+i][0].style.transform = 'rotate(' + 30 +'deg)';
}
let top = 0;
let left2 = 0;
item.children.forEach((k,j)=>{
top = (j + 1) * 20;
if (i % 2 === 0) {
top = -top;
}
left2 = Math.abs(top) / Math.tan(30 * Math.PI / 180) - 13;
if (i % 2 === 1) { // 下斜线
left2 = left2 + 26
}
this.$refs['lineOne'+i+j][0].style.left = left2 +'px';
this.$refs['lineOne'+i+j][0].style.top = top +'px';
});
if (i % 2 === 1) {
top = top + 24;
left2 = left2 - 10;
} else {
top = top - 58;
left2 = left2 + 4;
}
this.$refs['text'+i][0].style.left = left2 +'px';
this.$refs['text'+i][0].style.top = top +'px';
})
})
},
},
css:
.module-content {
position: relative;
margin: 24px 30px 0;
height: calc(18vh);
margin-bottom: 0;
height: calc(33vh);
.line-mian {
width: 84%;
height: 3px;
background: #00CCFF;
position: absolute;
left: 90px;
top: calc(50% - 1px);
}
.module-pub {
position: absolute;
left: 0;
width: 100px;
bottom: calc(50% + 1px);
color: #fff;
.module-pub-one {
position: absolute;
top: 10px;
width: 9vw;
.line-pub_ {
width: 40px;
/*height: 1px;*/
border-bottom: 1.5px solid #00CCFF;
/*background: #00CCFF;*/
position: absolute;
left: 0;
top: 7px;
}
p {
font-size: 12px;
position: absolute;
left: 42px;
}
}
.module-pub-text {
position: absolute;
right: 0;
bottom: 0;
p {
width: 80px;
font-size: 14px;
font-weight: bold;
text-align: center;
&:nth-child(1) {
color: #EF822F;
line-height: 16px;
}
&:nth-child(2) {
color: #5AD6FC;
cursor: pointer;
border-radius: 8px;
padding: 1px 0;
&.active {
background: #4594F9;
color: #fff;
}
&:hover {
background: #4594F9;
color: #fff;
}
}
}
}
}
.line-pub {
width: 80%;
height: 2px;
background: #00CCFF;
position: absolute;
left: 0;
bottom: -2px;
transform-origin: left bottom;
}
.title {
position: absolute;
left: 10px;
top: calc(50% - 8px);
display: flex;
align-items: center;
justify-content: center;
p {
font-weight: 700;
font-size: 16px;
line-height: 16px;
color: #C7F805;
margin: 0 4px;
}
span {
font-weight: 700;
line-height: 16px;
font-size: 16px;
color: #00CCFF
}
}
}