|
@ -1,6 +1,5 @@ |
|
|
<template> |
|
|
<template> |
|
|
<view class="box"> |
|
|
<view class="box"> |
|
|
<canvas class="radar-bg" :canvas-id="`cpbg${code}`" type="2d"></canvas> |
|
|
|
|
|
<canvas class="radar-fg" :canvas-id="`cpfg${code}`" type="2d"></canvas> |
|
|
<canvas class="radar-fg" :canvas-id="`cpfg${code}`" type="2d"></canvas> |
|
|
<div |
|
|
<div |
|
|
v-for="(item, index) in score" |
|
|
v-for="(item, index) in score" |
|
@ -39,15 +38,12 @@ |
|
|
handler(val) { |
|
|
handler(val) { |
|
|
console.log('watch score', val) |
|
|
console.log('watch score', val) |
|
|
this.$nextTick(() => { |
|
|
this.$nextTick(() => { |
|
|
this.drawFg(val) |
|
|
|
|
|
|
|
|
this.drawChart(val) |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
deep: true |
|
|
deep: true |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
mounted() { |
|
|
|
|
|
this.drawBg(); |
|
|
|
|
|
}, |
|
|
|
|
|
methods: { |
|
|
methods: { |
|
|
drawRing(ctx, x, y, startAngle, r) { |
|
|
drawRing(ctx, x, y, startAngle, r) { |
|
|
|
|
|
|
|
@ -110,66 +106,47 @@ |
|
|
|
|
|
|
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
drawBg() { |
|
|
|
|
|
|
|
|
createFgPath(ctx, x, y, startAngle, R, arr) { |
|
|
|
|
|
|
|
|
uni.createSelectorQuery().in(this) |
|
|
|
|
|
.select('.radar-bg') |
|
|
|
|
|
.fields({ |
|
|
|
|
|
node: true, |
|
|
|
|
|
size: true |
|
|
|
|
|
|
|
|
let points = arr.map((score, i) => { |
|
|
|
|
|
let r = R * score / 100 |
|
|
|
|
|
let angle = startAngle - Math.PI * 2 * i / 5 |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
x: x + r * Math.cos(angle), |
|
|
|
|
|
y: y - r * Math.sin(angle) |
|
|
|
|
|
} |
|
|
}) |
|
|
}) |
|
|
.exec(async (res) => { |
|
|
|
|
|
const canvas = res[0].node |
|
|
|
|
|
// Canvas 画布的实际绘制宽高 |
|
|
|
|
|
const width = res[0].width |
|
|
|
|
|
const height = res[0].height |
|
|
|
|
|
//根据dpr调整 |
|
|
|
|
|
const dpr = wx.getWindowInfo().pixelRatio |
|
|
|
|
|
canvas.width = width * dpr |
|
|
|
|
|
canvas.height = height * dpr |
|
|
|
|
|
|
|
|
|
|
|
let Ratio = width / 526 |
|
|
|
|
|
|
|
|
|
|
|
// 渲染上下文 |
|
|
|
|
|
const ctx = canvas.getContext('2d') |
|
|
|
|
|
|
|
|
|
|
|
ctx.scale(dpr, dpr) |
|
|
|
|
|
ctx.clearRect(0, 0, width, height) |
|
|
|
|
|
|
|
|
let lineStartX = points[0].x |
|
|
|
|
|
let lineStartY = points[0].y |
|
|
|
|
|
let lineEndX = null |
|
|
|
|
|
let lineEndY = null |
|
|
|
|
|
|
|
|
let x = width / 2 |
|
|
|
|
|
let y = height / 2 |
|
|
|
|
|
let startAngle = Math.PI / 2 |
|
|
|
|
|
|
|
|
ctx.beginPath(); //开始一个新的路径 |
|
|
|
|
|
ctx.moveTo(lineStartX, lineStartY); |
|
|
|
|
|
|
|
|
ctx.lineWidth = 2 * Ratio; |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
|
|
|
|
|
|
ctx.lineWidth = 3 * Ratio; |
|
|
|
|
|
ctx.strokeStyle = '#DACEFE'; |
|
|
|
|
|
ctx.shadowOffsetX = 0; |
|
|
|
|
|
ctx.shadowOffsetY = 0; |
|
|
|
|
|
ctx.shadowBlur = 6; |
|
|
|
|
|
ctx.shadowColor = "rgba(211, 210, 229, 0.6)"; |
|
|
|
|
|
this.drawRing(ctx, x, y, startAngle, 132 * Ratio) |
|
|
|
|
|
ctx.fillStyle = '#F9F7FF' |
|
|
|
|
|
ctx.fill() |
|
|
|
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
ctx.setLineDash([2]); |
|
|
|
|
|
ctx.strokeStyle = '#E1E0E6'; |
|
|
|
|
|
let dividers = [100, 68, 36, 8] |
|
|
|
|
|
dividers.forEach(r => { |
|
|
|
|
|
this.drawRing(ctx, x, y, startAngle, r * Ratio) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
for (let i = 1; i < 5; i++) { |
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
// ctx.setLineDash([]); |
|
|
|
|
|
ctx.strokeStyle = '#E1E0E6'; |
|
|
|
|
|
this.drawLine(ctx, x, y, startAngle, 132 * Ratio, 8 * Ratio) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
lineEndX = points[i].x |
|
|
|
|
|
lineEndY = points[i].y |
|
|
|
|
|
|
|
|
|
|
|
ctx.lineTo(lineEndX, lineEndY); |
|
|
|
|
|
// ctx.stroke(); |
|
|
|
|
|
|
|
|
|
|
|
lineStartX = lineEndX |
|
|
|
|
|
lineStartY = lineEndY |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lineEndX = points[0].x |
|
|
|
|
|
lineEndY = points[0].y |
|
|
|
|
|
ctx.moveTo(lineStartX, lineStartY); |
|
|
|
|
|
ctx.lineTo(lineEndX, lineEndY); |
|
|
|
|
|
ctx.closePath(); |
|
|
|
|
|
|
|
|
|
|
|
return points |
|
|
}, |
|
|
}, |
|
|
drawFg(arr) { |
|
|
|
|
|
|
|
|
drawChart(arr) { |
|
|
uni.createSelectorQuery().in(this) |
|
|
uni.createSelectorQuery().in(this) |
|
|
.select('.radar-fg') |
|
|
.select('.radar-fg') |
|
|
.fields({ |
|
|
.fields({ |
|
@ -201,6 +178,74 @@ |
|
|
console.log('R', R) |
|
|
console.log('R', R) |
|
|
let startAngle = Math.PI / 2 |
|
|
let startAngle = Math.PI / 2 |
|
|
|
|
|
|
|
|
|
|
|
ctx.save() |
|
|
|
|
|
|
|
|
|
|
|
ctx.lineWidth = 3 * Ratio; |
|
|
|
|
|
ctx.strokeStyle = '#DACEFE'; |
|
|
|
|
|
this.drawRing(ctx, x, y, startAngle, 132 * Ratio) |
|
|
|
|
|
ctx.fillStyle = '#F9F7FF' |
|
|
|
|
|
ctx.fill() |
|
|
|
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
this.createFgPath(ctx, x, y, startAngle, R, arr) |
|
|
|
|
|
ctx.fillStyle = '#F9F7FF'; |
|
|
|
|
|
ctx.fill() |
|
|
|
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
ctx.lineWidth = 2 * Ratio; |
|
|
|
|
|
ctx.setLineDash([2]); |
|
|
|
|
|
ctx.strokeStyle = '#E1E0E6'; |
|
|
|
|
|
let dividers = [100, 68, 36, 8] |
|
|
|
|
|
dividers.forEach(r => { |
|
|
|
|
|
this.drawRing(ctx, x, y, startAngle, r * Ratio) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
ctx.lineWidth = 2 * Ratio; |
|
|
|
|
|
ctx.strokeStyle = '#E1E0E6'; |
|
|
|
|
|
this.drawLine(ctx, x, y, startAngle, 132 * Ratio, 8 * Ratio) |
|
|
|
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
let x0 = width, y0 = height, x1 = 0, y1 = 0 |
|
|
|
|
|
let points = this.createFgPath(ctx, x, y, startAngle, R, arr) |
|
|
|
|
|
points.forEach(point => { |
|
|
|
|
|
const { x, y } = point |
|
|
|
|
|
|
|
|
|
|
|
if (x < x0) { |
|
|
|
|
|
x0 = x |
|
|
|
|
|
} |
|
|
|
|
|
if (y < y0) { |
|
|
|
|
|
y0 = y |
|
|
|
|
|
} |
|
|
|
|
|
if (x > x1) { |
|
|
|
|
|
x1 = x |
|
|
|
|
|
} |
|
|
|
|
|
if (y > y1) { |
|
|
|
|
|
y1 = y |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
}) |
|
|
|
|
|
console.log('points', points) |
|
|
|
|
|
console.log([x0, y0], [x1, y1]) |
|
|
|
|
|
let _x = (x0 + x1) / 2 |
|
|
|
|
|
let _y = (y0 + y1) / 2 |
|
|
|
|
|
let _r_arr = [Math.abs(x0 - _x), Math.abs(x1 - _x), Math.abs(y0 - _y), Math.abs(y1 - _y)] |
|
|
|
|
|
let _r_max = Math.max(..._r_arr) |
|
|
|
|
|
let _r_min = Math.min(..._r_arr) - 40 * Ratio || 0 |
|
|
|
|
|
console.log('_x', _x, '_y', _y, '_r', _r_max, _r_min) |
|
|
|
|
|
let radialGradient = ctx.createRadialGradient(_x, _y, 0, _x, _y, _r_max); |
|
|
|
|
|
radialGradient.addColorStop(0, 'rgba(188, 167, 255, 0.1)'); |
|
|
|
|
|
radialGradient.addColorStop(1, 'rgba(99, 52, 238, 0.2)') |
|
|
|
|
|
ctx.fillStyle = radialGradient; |
|
|
|
|
|
ctx.fill() |
|
|
|
|
|
|
|
|
|
|
|
ctx.restore() |
|
|
|
|
|
ctx.save() |
|
|
|
|
|
this.createFgPath(ctx, x, y, startAngle, R, arr) |
|
|
ctx.lineWidth = 3 * Ratio; |
|
|
ctx.lineWidth = 3 * Ratio; |
|
|
let gradient = ctx.createLinearGradient(x - R, y, x + R, y); |
|
|
let gradient = ctx.createLinearGradient(x - R, y, x + R, y); |
|
|
gradient.addColorStop('0', '#7451DE'); |
|
|
gradient.addColorStop('0', '#7451DE'); |
|
@ -208,49 +253,9 @@ |
|
|
ctx.strokeStyle = gradient; |
|
|
ctx.strokeStyle = gradient; |
|
|
ctx.shadowOffsetX = 0; |
|
|
ctx.shadowOffsetX = 0; |
|
|
ctx.shadowOffsetY = 0; |
|
|
ctx.shadowOffsetY = 0; |
|
|
ctx.shadowBlur = 23.9; |
|
|
|
|
|
|
|
|
ctx.shadowBlur = 13.9 * Ratio; |
|
|
ctx.shadowColor = "rgba(99, 52, 238, 0.4)"; |
|
|
ctx.shadowColor = "rgba(99, 52, 238, 0.4)"; |
|
|
|
|
|
|
|
|
let points = arr.map((score, i) => { |
|
|
|
|
|
let r = R * score / 100 |
|
|
|
|
|
let angle = startAngle - Math.PI * 2 * i / 5 |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
x: x + r * Math.cos(angle), |
|
|
|
|
|
y: y - r * Math.sin(angle) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
let lineStartX = points[0].x |
|
|
|
|
|
let lineStartY = points[0].y |
|
|
|
|
|
let lineEndX = null |
|
|
|
|
|
let lineEndY = null |
|
|
|
|
|
|
|
|
|
|
|
ctx.beginPath(); //开始一个新的路径 |
|
|
|
|
|
ctx.moveTo(lineStartX, lineStartY); |
|
|
|
|
|
|
|
|
|
|
|
for (let i = 1; i < 5; i++) { |
|
|
|
|
|
|
|
|
|
|
|
lineEndX = points[i].x |
|
|
|
|
|
lineEndY = points[i].y |
|
|
|
|
|
|
|
|
|
|
|
ctx.lineTo(lineEndX, lineEndY); |
|
|
|
|
|
ctx.stroke(); |
|
|
|
|
|
|
|
|
|
|
|
lineStartX = lineEndX |
|
|
|
|
|
lineStartY = lineEndY |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lineEndX = points[0].x |
|
|
|
|
|
lineEndY = points[0].y |
|
|
|
|
|
ctx.moveTo(lineStartX, lineStartY); |
|
|
|
|
|
ctx.lineTo(lineEndX, lineEndY); |
|
|
|
|
|
ctx.stroke(); |
|
|
ctx.stroke(); |
|
|
ctx.closePath(); |
|
|
|
|
|
|
|
|
|
|
|
ctx.fillStyle = 'rgba(188, 167, 255, 0.2)' |
|
|
|
|
|
ctx.fill() |
|
|
|
|
|
|
|
|
|
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}, |
|
@ -266,7 +271,6 @@ $size: 526rpx; |
|
|
width: $size; |
|
|
width: $size; |
|
|
height: $size; |
|
|
height: $size; |
|
|
|
|
|
|
|
|
.radar-bg, |
|
|
|
|
|
.radar-fg { |
|
|
.radar-fg { |
|
|
position: absolute; |
|
|
position: absolute; |
|
|
top: 0; |
|
|
top: 0; |
|
|