267 lines
6.3 KiB
Vue
267 lines
6.3 KiB
Vue
<template>
|
|
<div class="summary7">
|
|
<div class="left">
|
|
<div class="el-progress-circle" :style="{height: width + 'px', width: width + 'px'}">
|
|
<svg viewBox="0 0 100 100">
|
|
<defs>
|
|
<linearGradient id="blue" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
<stop offset="0%" style="stop-color:#243D93;stop-opacity:1" />
|
|
<stop offset="100%" style="stop-color:#4EFFDC;stop-opacity:1" />
|
|
</linearGradient>
|
|
</defs>
|
|
<path
|
|
class="el-progress-circle__track"
|
|
:d="trackPath"
|
|
stroke="#464C63"
|
|
:stroke-width="relativeStrokeWidth"
|
|
fill="none"
|
|
:style="trailPathStyle"></path>
|
|
<path
|
|
class="el-progress-circle__path"
|
|
:d="trackPath"
|
|
:stroke="stroke"
|
|
fill="none"
|
|
stroke-linecap="butt"
|
|
:stroke-width="percentage ? relativeStrokeWidth : 0"
|
|
:style="circlePathStyle"></path>
|
|
</svg>
|
|
<div class="pointer">
|
|
<div class="pointer-round"></div>
|
|
<div class="pointer-circle"></div>
|
|
<div class="pointer-line" :style="{transform: `rotate(${rotateDeg}deg)`}"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="middle">
|
|
<p><span>{{ data[0][value] }}</span></p>
|
|
<h2>{{ data[0][keys] }}</h2>
|
|
</div>
|
|
<div class="right">
|
|
<div class="summary7-item" v-for="(item, index) in data" :key="index" v-if="index < 4 && index !== 0">
|
|
<h2>{{ item[keys] }}</h2>
|
|
<p>{{ item[value] }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'Summary7',
|
|
|
|
props: {
|
|
data: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
|
|
keys: {
|
|
type: String,
|
|
default: 'key'
|
|
},
|
|
|
|
value: {
|
|
type: String,
|
|
default: 'value'
|
|
},
|
|
},
|
|
|
|
data () {
|
|
return {
|
|
width: 70,
|
|
strokeWidth: 8
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
rotateDeg () {
|
|
return this.percentage / 100 * 270 + (360 * 0.25) / 2 + 90
|
|
},
|
|
|
|
relativeStrokeWidth() {
|
|
return (this.strokeWidth / this.width * 100).toFixed(1);
|
|
},
|
|
|
|
percentage () {
|
|
if (this.data.length) {
|
|
return typeof this.data[0][this.value] === 'string' ? Number(this.data[0][this.value].replace('%', '')) : this.data[0][this.value]
|
|
}
|
|
|
|
return 0
|
|
},
|
|
|
|
radius() {
|
|
return parseInt(50 - parseFloat(this.relativeStrokeWidth) / 2, 10);
|
|
},
|
|
perimeter() {
|
|
return 2 * Math.PI * this.radius;
|
|
},
|
|
trackPath() {
|
|
const radius = this.radius;
|
|
const isDashboard = true
|
|
return `
|
|
M 50 50
|
|
m 0 ${isDashboard ? '' : '-'}${radius}
|
|
a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '-' : ''}${radius * 2}
|
|
a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '' : '-'}${radius * 2}
|
|
`;
|
|
},
|
|
strokeDashoffset() {
|
|
const offset = -1 * this.perimeter * (1 - this.rate) / 2;
|
|
return `${offset}px`;
|
|
},
|
|
trailPathStyle() {
|
|
return {
|
|
strokeDasharray: `${(this.perimeter * this.rate)}px, ${this.perimeter}px`,
|
|
strokeDashoffset: this.strokeDashoffset
|
|
};
|
|
},
|
|
circlePathStyle() {
|
|
return {
|
|
strokeDasharray: `${this.perimeter * this.rate * (this.percentage / 100) }px, ${this.perimeter}px`,
|
|
strokeDashoffset: this.strokeDashoffset,
|
|
transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease'
|
|
};
|
|
},
|
|
stroke() {
|
|
return 'url(#blue)';
|
|
},
|
|
rate() {
|
|
return 0.75
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
getCurrentColor(percentage) {
|
|
if (typeof this.color === 'function') {
|
|
return this.color(percentage);
|
|
} else if (typeof this.color === 'string') {
|
|
return this.color;
|
|
} else {
|
|
return this.getLevelColor(percentage);
|
|
}
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.summary7 {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
width: 380px;
|
|
height: 124px;
|
|
padding: 0 44px;
|
|
background: url(./../asset/summary6-bg.svg);
|
|
background-size: 100% 100%;
|
|
|
|
.el-progress-circle {
|
|
position: relative;
|
|
|
|
.pointer-round {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
z-index: 1;
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 1px solid #2E69FF;
|
|
border-radius: 50%;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.pointer-circle {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
z-index: 1;
|
|
width: 8px;
|
|
height: 8px;
|
|
background: #FDDD60;
|
|
border-radius: 50%;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.pointer-line {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
z-index: 1;
|
|
width: 35px;
|
|
height: 1px;
|
|
background: #FDDD60;
|
|
transform: rotate(90deg);
|
|
transform-origin: 0 0 0;
|
|
}
|
|
}
|
|
|
|
div {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.left {
|
|
position: relative;
|
|
top: 5px;
|
|
}
|
|
|
|
.middle {
|
|
margin: 0 16px;
|
|
p {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: center;
|
|
font-size: 36px;
|
|
font-weight: bold;
|
|
color: #FFFFFF;
|
|
line-height: 32px;
|
|
text-align: center;
|
|
background-image: linear-gradient(180deg, #FFFFFF 0%, #FFDD8C 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
|
|
i {
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
|
|
h2 {
|
|
display: flex;
|
|
align-items: baseline;
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
color: #FFFFFF;
|
|
text-align: center;
|
|
background-image: linear-gradient(180deg, #FFFFFF 0%, #C7C7C7 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
}
|
|
}
|
|
|
|
.right {
|
|
}
|
|
|
|
.summary7-item {
|
|
display: flex;
|
|
position: relative;
|
|
align-items: center;
|
|
|
|
h2 {
|
|
flex: 1;
|
|
line-height: 24px;
|
|
margin-right: 8px;
|
|
color: #A8D7F3;
|
|
font-size: 12px;
|
|
font-weight: normal;
|
|
text-align: right;
|
|
}
|
|
|
|
p {
|
|
font-weight: 700;
|
|
font-size: 15px;
|
|
color: #fff;
|
|
}
|
|
}
|
|
}
|
|
</style>
|