|
@@ -75,6 +75,28 @@ export default {
|
|
|
height: {
|
|
height: {
|
|
|
type: Number,
|
|
type: Number,
|
|
|
default: 600
|
|
default: 600
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 平均值分数 0-100,与 dimensions 顺序一一对应(可选,显示为灰色虚线) */
|
|
|
|
|
+ avgScores: {
|
|
|
|
|
+ type: Array,
|
|
|
|
|
+ default: function() {
|
|
|
|
|
+ return []
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 平均值填充颜色(可选,默认灰色) */
|
|
|
|
|
+ avgFillColor: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: '#CBD5E1'
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 平均值网格颜色(可选,默认浅灰) */
|
|
|
|
|
+ avgGridColor: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: '#E2E8F0'
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 平均值标签颜色(可选,默认浅灰) */
|
|
|
|
|
+ avgLabelColor: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: '#94A3B8'
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
data: function() {
|
|
data: function() {
|
|
@@ -123,6 +145,14 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
deep: true
|
|
deep: true
|
|
|
|
|
+ },
|
|
|
|
|
+ avgScores: {
|
|
|
|
|
+ handler: function() {
|
|
|
|
|
+ if (this.canvasReady) {
|
|
|
|
|
+ this._doRender()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ deep: true
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
mounted: function() {
|
|
mounted: function() {
|
|
@@ -206,19 +236,24 @@ export default {
|
|
|
// 1. 绘制背景网格
|
|
// 1. 绘制背景网格
|
|
|
this._drawGrid(ctx, cx, cy, outerR, angles, n)
|
|
this._drawGrid(ctx, cx, cy, outerR, angles, n)
|
|
|
|
|
|
|
|
- // 2. 绘制分数区域
|
|
|
|
|
|
|
+ // 2. 如果有平均值,先画平均值(灰色虚线)
|
|
|
|
|
+ if (this.avgScores && this.avgScores.length >= n && n >= 3) {
|
|
|
|
|
+ this._drawAvgScoreArea(ctx, cx, cy, outerR, angles, n)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 绘制用户分数区域
|
|
|
this._drawScoreArea(ctx, cx, cy, outerR, angles, n)
|
|
this._drawScoreArea(ctx, cx, cy, outerR, angles, n)
|
|
|
|
|
|
|
|
- // 3. 绘制顶点标记
|
|
|
|
|
|
|
+ // 4. 绘制顶点标记
|
|
|
this._drawVertices(ctx, cx, cy, outerR, angles, n)
|
|
this._drawVertices(ctx, cx, cy, outerR, angles, n)
|
|
|
|
|
|
|
|
- // 4. 绘制分数文字
|
|
|
|
|
|
|
+ // 5. 绘制分数文字
|
|
|
this._drawScoreText(ctx, cx, cy, outerR, angles, n)
|
|
this._drawScoreText(ctx, cx, cy, outerR, angles, n)
|
|
|
|
|
|
|
|
- // 5. 绘制维度标签
|
|
|
|
|
|
|
+ // 6. 绘制维度标签
|
|
|
this._drawLabels(ctx, cx, cy, outerR, angles, n)
|
|
this._drawLabels(ctx, cx, cy, outerR, angles, n)
|
|
|
|
|
|
|
|
- // 6. 绘制中心标题
|
|
|
|
|
|
|
+ // 7. 绘制中心标题
|
|
|
this._drawCenterText(ctx, cx, cy)
|
|
this._drawCenterText(ctx, cx, cy)
|
|
|
},
|
|
},
|
|
|
|
|
|
|
@@ -310,6 +345,48 @@ export default {
|
|
|
ctx.stroke()
|
|
ctx.stroke()
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 绘制平均值填充多边形(灰色虚线)
|
|
|
|
|
+ */
|
|
|
|
|
+ _drawAvgScoreArea: function(ctx, cx, cy, outerR, angles, n) {
|
|
|
|
|
+ var scores = this.avgScores
|
|
|
|
|
+ if (!scores || scores.length < n) { return }
|
|
|
|
|
+
|
|
|
|
|
+ // 构建顶点数据
|
|
|
|
|
+ var points = []
|
|
|
|
|
+ for (var i = 0; i < n; i++) {
|
|
|
|
|
+ var score = scores[i] || 0
|
|
|
|
|
+ var r = outerR * Math.max(0, Math.min(1, score / 100))
|
|
|
|
|
+ points.push({
|
|
|
|
|
+ x: cx + r * Math.cos(angles[i]),
|
|
|
|
|
+ y: cy + r * Math.sin(angles[i])
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 填充多边形(半透明灰色)
|
|
|
|
|
+ ctx.beginPath()
|
|
|
|
|
+ for (var pi = 0; pi < points.length; pi++) {
|
|
|
|
|
+ if (pi === 0) {
|
|
|
|
|
+ ctx.moveTo(points[pi].x, points[pi].y)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ctx.lineTo(points[pi].x, points[pi].y)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ctx.closePath()
|
|
|
|
|
+
|
|
|
|
|
+ var baseColor = this.avgFillColor || '#CBD5E1'
|
|
|
|
|
+ ctx.fillStyle = 'rgba(203,213,225,0.15)'
|
|
|
|
|
+ ctx.fill()
|
|
|
|
|
+
|
|
|
|
|
+ // 描边(灰色虚线)
|
|
|
|
|
+ ctx.save()
|
|
|
|
|
+ ctx.setLineDash([6, 4])
|
|
|
|
|
+ ctx.strokeStyle = baseColor
|
|
|
|
|
+ ctx.lineWidth = 2
|
|
|
|
|
+ ctx.stroke()
|
|
|
|
|
+ ctx.restore()
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 在各顶点绘制小圆点
|
|
* 在各顶点绘制小圆点
|
|
|
*/
|
|
*/
|