341 lines
8.8 KiB
Vue
341 lines
8.8 KiB
Vue
<template>
|
||
<view class="chart-box" :style="allStyle">
|
||
<view class="cont-box">
|
||
<view v-for="width in 7" :class="'total-line total-line' + width"></view>
|
||
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
|
||
<view class="data-box">
|
||
<view class="line-box">
|
||
<view v-for="width in 3" :class="`percent-${width * 25}`"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="title" v-if="fromType === 'crs'">
|
||
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
|
||
改进建议:
|
||
</view>
|
||
<view class="title" v-if="fromType === 'tra'">
|
||
<image class="title-icon icon-tra" src="@/static/images/sparring/den-icon.png" alt=""> </image>
|
||
维度分析:
|
||
</view>
|
||
<view class="total-score" v-if="fromType === 'crs'">
|
||
<view class="score-num">{{ score }}</view>分
|
||
<image class="total-score-icon" src="@/static/images/course/score.png" alt=""></image>
|
||
</view>
|
||
<view v-for="(item,index) in dataList" :class="['score-item', 'score-item'+(index+1)]">
|
||
<view class="score-item-name">{{ item.gradeDimensName || item.gradeDimens }}</view>
|
||
<view class="score-item-score">{{ item.anlyGrade }}</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
<script>
|
||
export default{
|
||
props:{
|
||
dataList:{
|
||
default:() => [],
|
||
type: Array
|
||
},
|
||
score:{
|
||
default: 0,
|
||
type: [Number,String]
|
||
},
|
||
size:{
|
||
default: 262,
|
||
type: [Number,String]
|
||
},
|
||
fromType:{
|
||
default: 'crs',
|
||
type: String
|
||
}
|
||
},
|
||
data(){
|
||
return {
|
||
|
||
}
|
||
},
|
||
computed:{
|
||
dataValue(){
|
||
return this.dataList.map(t=>t.anlyGrade)
|
||
},
|
||
chartWidth(){
|
||
return this.size + 'rpx'
|
||
},
|
||
chartHeight(){
|
||
return this.size + 'rpx'
|
||
},
|
||
styleFive(){
|
||
return this.generateHeptagonClipPath()
|
||
},
|
||
styleFiveResult(){
|
||
return this.generateHeptagonDataClipPath()
|
||
},
|
||
verticesList(){
|
||
return this.calculateHeptagonVertices()
|
||
},
|
||
allStyle(){
|
||
let _obj = {
|
||
'--styleFive': this.styleFive,
|
||
'--styleFiveResult': this.styleFiveResult,
|
||
'--chartWidth': this.chartWidth,
|
||
'--chartHeight': this.chartHeight,
|
||
'--boxSize': this.size + 'rpx'
|
||
}
|
||
this.verticesList.forEach((t,index)=>{
|
||
_obj[`--pointX${index+1}`] = t.x/100
|
||
_obj[`--pointY${index+1}`] = t.y/100
|
||
// _obj[`--pointX${index+1}`] = t.cssX
|
||
// _obj[`--pointY${index+1}`] = t.cssY
|
||
})
|
||
return _obj
|
||
}
|
||
},
|
||
methods:{
|
||
// 正七边形顶点计算函数
|
||
calculateHeptagonVertices(radius = 50, angleOffset = 0) {
|
||
const sides = 6;
|
||
const vertices = [];
|
||
const centerX = 50;
|
||
const centerY = 50;
|
||
|
||
// 将角度偏移转换为弧度
|
||
const offsetRad = (angleOffset * Math.PI) / 180;
|
||
|
||
for (let i = 0; i < sides; i++) {
|
||
// 计算每个顶点的角度(弧度)
|
||
const angle = (2 * Math.PI * i) / sides + offsetRad;
|
||
|
||
// 计算顶点坐标(百分比)
|
||
const x = centerX + radius * Math.cos(angle);
|
||
const y = centerY + radius * Math.sin(angle);
|
||
// 计算顶点坐标(百分比)
|
||
const dataX = centerX + radius * Math.cos(angle) * this.dataValue[i] / 100;
|
||
const dataY = centerY + radius * Math.sin(angle) * this.dataValue[i] / 100;
|
||
|
||
vertices.push({
|
||
x: x,
|
||
y: y,
|
||
cssX: x + '%',
|
||
cssY: y + '%',
|
||
dataX: dataX + '%',
|
||
dataY: dataY + '%'
|
||
});
|
||
}
|
||
return vertices;
|
||
},
|
||
|
||
// 生成CSS clip-path多边形值
|
||
generateHeptagonClipPath(radius = 50, angleOffset = 0) {
|
||
const vertices = this.calculateHeptagonVertices(radius, angleOffset);
|
||
const polygonPoints = vertices.map(v => `${v.cssX} ${v.cssY}`).join(', ');
|
||
return `polygon(${polygonPoints})`;
|
||
},
|
||
// 生成CSS clip-path多边形值
|
||
generateHeptagonDataClipPath(radius = 50, angleOffset = 0) {
|
||
const vertices = this.calculateHeptagonVertices(radius, angleOffset);
|
||
const polygonPoints = vertices.map(v => `${v.dataX} ${v.dataY}`).join(', ');
|
||
return `polygon(${polygonPoints})`;
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.chart-box{
|
||
width: 100%;
|
||
height: 580rpx;
|
||
background:linear-gradient( 270deg, #4a74ff 0%, #6fa7fe 100%);
|
||
overflow: hidden;
|
||
position: relative;
|
||
border-radius: 16rpx;
|
||
margin-bottom: 20rpx;
|
||
.cont-box{
|
||
background-color: #87abfe;
|
||
width: var(--chartWidth);
|
||
height: var(--chartHeight);
|
||
clip-path: var(--styleFive);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
margin-top: 25rpx;
|
||
|
||
.total-line{
|
||
width: 100%;
|
||
height: 3rpx;
|
||
background: linear-gradient(90deg, #00000000 0% 50%, rgba(255, 255, 255, .3) 50% 100%);
|
||
position: absolute;
|
||
overflow: hidden;
|
||
z-index: 20;
|
||
top: 50%;
|
||
left: 0%;
|
||
&.total-line1{
|
||
transform: rotateZ(calc(360deg * 1 / 6));
|
||
}
|
||
&.total-line2{
|
||
transform: rotateZ(calc(360deg * 2 / 6));
|
||
}
|
||
&.total-line3{
|
||
transform: rotateZ(calc(360deg * 3 / 6));
|
||
}
|
||
&.total-line4{
|
||
transform: rotateZ(calc(360deg * 4 / 6));
|
||
}
|
||
&.total-line5{
|
||
transform: rotateZ(calc(360deg * 5 / 6));
|
||
}
|
||
&.total-line6{
|
||
transform: rotateZ(calc(360deg * 6 / 6));
|
||
}
|
||
}
|
||
@for $i from 1 through 3 {
|
||
.percent-#{$i*25}{
|
||
width: $i * 25%;
|
||
height: $i * 25%;
|
||
clip-path: var(--styleFive);
|
||
background-color: rgba(255, 255, 255, .3);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: (4 - $i) * 2;
|
||
&::before{
|
||
content: '';
|
||
display: block;
|
||
width: calc(100% - 10rpx);
|
||
height: calc(100% - 10rpx);
|
||
background-color: #87abfe;
|
||
clip-path: var(--styleFive);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
}
|
||
}
|
||
.data-box{
|
||
width: 100%;
|
||
height: 100%;
|
||
clip-path: var(--styleFiveResult);
|
||
position: absolute;
|
||
background-color: #fff;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 12;
|
||
overflow: hidden;
|
||
.line-box{
|
||
display: block;
|
||
width: calc(100% - 24rpx);
|
||
height: calc(100% - 24rpx);
|
||
// background-color: #6691fe;
|
||
background-color: #6691fe;
|
||
clip-path: var(--styleFiveResult);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 14;
|
||
}
|
||
|
||
@for $i from 1 through 3 {
|
||
.percent-#{$i*25}{
|
||
background-color: rgba(255, 255, 255, .1);
|
||
z-index: (4 - $i) * 2 + 10;
|
||
&::before{
|
||
background-color: #6692ff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.title{
|
||
padding: 24rpx;
|
||
line-height: 46rpx;
|
||
font-size: 32rpx;
|
||
color: #fff;
|
||
position: relative;
|
||
.title-icon {
|
||
width: 27rpx;
|
||
height: 27rpx;
|
||
|
||
&.icon-tra{
|
||
position: relative;
|
||
top: 4rpx;
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
}
|
||
}
|
||
.total-score{
|
||
position: absolute;
|
||
right: 30rpx;
|
||
top:30rpx;
|
||
width: 100rpx;
|
||
height: 80rpx;
|
||
line-height: 70rpx;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
white-space: nowrap;
|
||
text-shadow: 0 4px 12px rgba(0, 0, 0, .33);
|
||
.score-num{
|
||
display: inline-block;
|
||
font-size: 60rpx;
|
||
line-height: 70rpx;
|
||
font-weight: bold;
|
||
}
|
||
.total-score-icon{
|
||
width: 100%;
|
||
height: 16rpx;
|
||
position: absolute;
|
||
bottom:0;
|
||
left:0;
|
||
}
|
||
}
|
||
.score-item{
|
||
position: absolute;
|
||
color: #fff;
|
||
width: 120rpx;
|
||
text-align: center;
|
||
.score-item-name{
|
||
font-size: 28rpx;
|
||
line-height: 36rpx;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
.score-item-score{
|
||
font-size: 38rpx;
|
||
line-height: 46rpx;
|
||
font-weight: bold;
|
||
}
|
||
&.score-item1{
|
||
left: 50%;
|
||
top: 50%;
|
||
transform: translate(calc(-50% + var(--boxSize)/2 + 60rpx), -50%);
|
||
margin-top: 25rpx;
|
||
}
|
||
&.score-item2{
|
||
left: calc(var(--pointX2) * var(--boxSize));
|
||
top: calc(50% + (var(--pointY2) * var(--boxSize) / 2));
|
||
transform: translate(calc(-50% + var(--boxSize)/2 + 80rpx), 30rpx);
|
||
}
|
||
&.score-item3{
|
||
left: calc(var(--pointX3) * var(--boxSize));
|
||
top: calc(50% + (var(--pointY3) * var(--boxSize) / 2));
|
||
transform: translate(calc(-50% + var(--boxSize)/2 + 50rpx), 30rpx);
|
||
}
|
||
&.score-item4{
|
||
left: calc(var(--pointX4) * var(--boxSize));
|
||
top: 50% ;
|
||
transform: translate(calc(-50% + var(--boxSize)/2 - 10rpx), -50%);
|
||
margin-top: 25rpx;
|
||
}
|
||
&.score-item5{
|
||
left: calc(var(--pointX5) * var(--boxSize));
|
||
top: calc(50% + (var(--pointY5) * var(--boxSize) / 2));
|
||
transform: translate(calc(-50% + var(--boxSize)/2 + 50rpx), calc(-160rpx - 50%));
|
||
}
|
||
&.score-item6{
|
||
left: calc(var(--pointX6) * var(--boxSize));
|
||
top: calc(50% + (var(--pointY6) * var(--boxSize) / 2));
|
||
transform: translate(calc(-50% + var(--boxSize)/2 + 80rpx), calc(-160rpx - 50%));
|
||
}
|
||
}
|
||
}
|
||
</style> |