数据大屏 项目开发中,需要实现一个占比效果,并且鼠标移上去后可以显示详细信息,这里将实现代码整理出来,方便复用。
组件代码
<template>
<div class="itemBodys">
<div class="itemBodysl">
<listCom :data="data"></listCom>
</div>
<div class="itemBodysr">
<div class="listItem cur" v-for="(item,index) in list" :key="index">
<div class="listIteml">
<div class="dot" :class="{disabled:!item.checked}"
:style="'background: linear-gradient(0deg,'+item.color1+' 0%, '+item.color2+' 100%);'"></div>
<span :class="{disabled:!item.checked}">{{ item.name }}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import listCom from './components/index.vue'
export default {
name: "title",
data() {
return {
data: [
{
"id": 2992646325070226000,
"用印名称": "苏米图苏木苏米图嘎查村委会各类证明、介绍、文件",
"已完成": 36,
"流程中": 6,
"已失效": 34
},
{
"id": 2993072901188510000,
"用印名称": "苏米图苏木马什亥嘎查村委会各类证明、介绍、文件",
"已完成": 11,
"流程中": 0,
"已失效": 1
},
{
"id": 2993073155543687700,
"用印名称": "苏米图苏木哈达图嘎查村委会各类证明、介绍、文件",
"已完成": 36,
"流程中": 1,
"已失效": 3
},
{
"id": 2993073445462369300,
"用印名称": "苏米图苏木巴嘎额尔和图嘎查村委会各类证明、介绍、文件",
"已完成": 7,
"流程中": 0,
"已失效": 3
},
{
"id": 2993081299757982700,
"用印名称": "苏米图苏木查汗敖包嘎查村委会各类证明、介绍、文件",
"已完成": 5,
"流程中": 0,
"已失效": 3
}
],
list: [
{
name: '已完成',
value: 80,
color1: 'rgba(93, 145, 250, 1)',
color2: 'rgba(122, 92, 250, 1)',
checked: true
},
{
name: '流程中',
value: 100,
color1: 'rgba(49, 197, 222, 1)',
color2: 'rgba(75, 122, 250, 1)',
checked: true
},
{
name: '已失效',
value: 70,
color1: '#52617e',
color2: '#52617e',
checked: true
}]
}
},
components: {listCom},
}
</script>
<style lang="scss" scoped>
.itemBodys {
position: relative;
width: calc(100% - 35px - 20px);
margin: 0 auto;
margin-left: 35px;
height: calc(100% - 0px);
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
.itemBodysl {
width: calc(100% - 120px);
position: relative;
height: calc(100% - 10px);
}
.itemBodysr {
width: 120px;
}
}
.itemBodysr {
position: relative;
height: calc(100% - 10px);
//background: url("./assets/jiaobiaobg.png") no-repeat;
//background-size: 100% 100%;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
.listItem {
font-size: 14px;
display: flex;
width: calc(100% - 0px);
justify-content: center;
margin-bottom: 8px;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
.listIteml {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
font-size: 13px;
font-family: MicrosoftYaHei;
font-weight: 400;
color: rgba(152, 191, 251, 1);
}
span {
font-size: 14px;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: rgba(152, 191, 251, 1);
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
}
.dot {
width: 8px;
height: 8px;
margin-right: 10px;
flex-shrink: 0;
}
.dot.disabled {
background: rgba(#999, 0.8) !important;
}
.disabled span, span.disabled {
color: rgba(#999, 0.8) !important;
}
}
}
</style>
进度条列表
<template>
<div class="list">
<Vue3SeamlessScroll :step="0.5" :wheel="true" :hover="true" :list="data" class="tableBody">
<div class="listItem wow fadeInLeft" :data-wow-delay="0+0.3*index+'s'"
v-for="(item,index) in data"
:key="index">
<jindu :index2="(index+1)" :item="item"></jindu>
</div>
</Vue3SeamlessScroll>
</div>
</template>
<script>
import WOW from "wow.js";
import jindu from './jindu.vue'
import {Vue3SeamlessScroll} from "vue3-seamless-scroll";
export default {
data() {
return {}
},
components: {Vue3SeamlessScroll, jindu},
props: {
data: {
type: Array,
default() {
return [];
}
},
},
computed: {},
mounted() {
var that = this;
var wow = new WOW({
boxClass: "wow", // animated element css class (default is wow)
animateClass: "animated", // animation css class (default is animated)
offset: 0, // distance to the element when triggering the animation (default is 0)
mobile: true, // trigger animations on mobile devices (default is true)
live: true, // act on asynchronously loaded content (default is true)
callback: function (box) {
// the callback is fired every time an animation is started
// the argument that is passed in is the DOM node being animated
},
scrollContainer: null, // optional scroll container selector, otherwise use window,
resetAnimation: true, // reset animation on end (default is true)
});
wow.init();
},
methods: {},
filters: {},
watch: {}
}
</script>
<style lang="scss" scoped>
.list {
width: calc(100% - 0px);
height: 100%;
overflow: hidden;
position: relative;
.listItem {
font-size: 14px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
width: 100%;
}
}
</style>
进度条实现代码
<template>
<div class="jinduMain">
<div class="jinduTitleTop">
<div class="jinduTitle">
<span>TOP.{{ index2 }}</span>
</div>
<div class="jinduTitle2">
<span>{{ item['用印名称'] }}</span>
</div>
</div>
<div class="jindoBody">
<div class="jindu" :style="{background:item.bg,width:item.percentage+'%'}" v-for="(item,index) in list2"
:key="index">
<el-tooltip :popper-class="'tooltipitem'+index" effect="dark"
:content="item.label+' '+item.percentage +'%'"
placement="top">
<p>
<!-- <span>({{ item.percentage }}%)</span>-->
</p>
</el-tooltip>
</div>
</div>
</div>
</template>
<script>
export default {
name: "jindu",
props: {
item: {
type: Object,
default() {
return {};
}
},
index2: {
type: Number,
default() {
return 0;
}
},
},
data() {
return {
list: [
{
label: '已完成',
value: 0,
bg: 'linear-gradient(90deg, rgba(93, 145, 250, 1) 0%, rgba(122, 92, 250, 1) 100%)'
},
{
label: '流程中',
value: 0,
bg: 'linear-gradient(90deg, rgba(49, 197, 222, 1) 0%, rgba(75, 122, 250, 1) 100%)'
},
{label: '已失效', value: 0, bg: 'linear-gradient(90deg, #52617e 0%, #52617e 100%)'},
],
}
},
watch: {},
computed: {
list2: function () {
let total = 0
this.list.forEach((type) => {
type.value = this.item[type.label]
total += type.value
});
var list2 = this.list;
var list = []
list2.forEach((type) => {
var data = {
value: type.value,
percentage: Number((type.value / total) * 100).toFixed(2),
label: type.label,
bg: type.bg,
}
list.push(data)
});
console.log(list)
return list
}
},
mounted() {
},
methods: {}
}
</script>
<style lang="scss" scoped>
.jinduTitleTop {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
margin-bottom: 5px;
}
.jinduTitle {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
margin-right: 10px;
span {
font-size: 16px;
font-family: DIN-Bold;
font-weight: 500;
color: #FFFFFF;
text-shadow: 0 0 10px #3873ad;
}
}
.jinduTitle2 {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
span {
font-size: 14px;
font-family: MicrosoftYaHei;
font-weight: 400;
color: #D6EEFF;
}
}
.jindoBody {
width: calc(100% - 0px);
margin: auto;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
flex-direction: row;
height: 10px;
border-radius: 5px;
}
.jinduMain {
width: 100%;
height: 50px;
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
p {
color: #fff;
font-size: 14px;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
height: 10px;
}
p:first-child {
border-radius: 5px 0 0 5px;
}
p:last-child {
border-radius: 0 5px 5px 0;
}
}
</style>
<style lang="scss">
.tooltipitem0 {
font-size: 16px;
background: linear-gradient(90deg, rgba(93, 145, 250, 1) 0%, rgba(122, 92, 250, 1) 100%) !important;
}
.tooltipitem1 {
font-size: 16px;
background: linear-gradient(90deg, rgba(49, 197, 222, 1) 0%, rgba(75, 122, 250, 1) 100%) !important;
}
.tooltipitem2 {
font-size: 16px;
background: linear-gradient(90deg, #52617e 0%, #52617e 100%) !important;
}
</style>