Commit 80da33e1 authored by xinzhedeai's avatar xinzhedeai

add:canvas charts circle

parent 62a1c35f
<template> <template>
<!-- 图表容器 Canvas --> <!-- 图表容器 Canvas -->
<div class="chart-container wrapper"> <div class="chart-container wrapper">
<h2 class="card-title">设备状态总览</h2> <h2 class="card-title">AI预警分析</h2>
<div class="chart-wrapper">
<canvas <canvas
ref="chartCanvasRef" ref="chartCanvasRef"
width="430" width="250"
height="290" height="250"
class="chart-canvas" class="chart-canvas"
></canvas> ></canvas>
<div class="legend-container">
<div v-for="(item, index) in chartData" :key="index" class="legend-item">
<div class="color-block" :style="{ backgroundColor: item.color }"></div>
<div class="legend-text">
<span class="legend-name">{{ item.name }}</span>
<span class="legend-value">{{ item.value }}</span>
</div>
</div>
</div>
</div>
</div> </div>
</template> </template>
...@@ -26,7 +37,7 @@ interface RingLayer { ...@@ -26,7 +37,7 @@ interface RingLayer {
inner: number; inner: number;
} }
// 2. 核心配置与数据(可通过 props 透传扩展 // 2. 核心配置与数据(5个类别
const chartData: ChartDataItem[] = [ const chartData: ChartDataItem[] = [
{ name: '疲劳驾驶', value: 10, color: '#409EFF' }, { name: '疲劳驾驶', value: 10, color: '#409EFF' },
{ name: '违规打电话', value: 15, color: '#52C41A' }, { name: '违规打电话', value: 15, color: '#52C41A' },
...@@ -35,13 +46,13 @@ const chartData: ChartDataItem[] = [ ...@@ -35,13 +46,13 @@ const chartData: ChartDataItem[] = [
{ name: '人脸丢失', value: 0, color: '#F5222D' }, { name: '人脸丢失', value: 0, color: '#F5222D' },
]; ];
// 调整环形图层尺寸以适应新的 canvas 尺寸 // 调整环形图层尺寸以适应新的 canvas 尺寸,增大环间距离
const ringLayers: RingLayer[] = [ const ringLayers: RingLayer[] = [
{ outer: 110, inner: 100 }, // 第1层:疲劳闭眼 { outer: 100, inner: 85 }, // 第1层:疲劳驾驶
{ outer: 90, inner: 80 }, // 第3层:违规打电话 { outer: 80, inner: 65 }, // 第2层:违规打电话
{ outer: 80, inner: 70 }, // 第4层:违规抽烟 { outer: 60, inner: 45 }, // 第3层:违规抽烟
{ outer: 70, inner: 60 }, // 第5层:左顾右盼 { outer: 40, inner: 25 }, // 第4层:左顾右盼
{ outer: 60, inner: 50 }, // 第6层:人脸丢失 { outer: 20, inner: 5 }, // 第5层:人脸丢失
]; ];
// 3. 获取 Canvas 元素 Ref // 3. 获取 Canvas 元素 Ref
...@@ -66,10 +77,10 @@ const drawChart = () => { ...@@ -66,10 +77,10 @@ const drawChart = () => {
const centerX = canvas.width / 2; const centerX = canvas.width / 2;
const centerY = canvas.height / 2; const centerY = canvas.height / 2;
const bgColor = '#E5E6EB'; // 每层独立背景色 const bgColor = '#2B4D79'; // 每层独立背景色
const startAngle = -Math.PI / 2; // 12点钟方向起始 const startAngle = -Math.PI / 2; // 12点钟方向起始
// 步骤1:绘制每层独立的深灰色背景 // 步骤1:绘制每层独立的背景
const drawBackground = () => { const drawBackground = () => {
ringLayers.forEach((layer) => { ringLayers.forEach((layer) => {
ctx.beginPath(); ctx.beginPath();
...@@ -78,10 +89,6 @@ const drawChart = () => { ...@@ -78,10 +89,6 @@ const drawChart = () => {
ctx.closePath(); ctx.closePath();
ctx.fillStyle = bgColor; ctx.fillStyle = bgColor;
ctx.fill(); ctx.fill();
// 层间白色描边区分
ctx.strokeStyle = '#fff';
ctx.lineWidth = 1;
ctx.stroke();
}); });
}; };
...@@ -91,9 +98,8 @@ const drawChart = () => { ...@@ -91,9 +98,8 @@ const drawChart = () => {
const total = validData.reduce((sum, item) => sum + item.value, 0); const total = validData.reduce((sum, item) => sum + item.value, 0);
if (total === 0) { if (total === 0) {
console.warn('No valid data to draw'); console.warn('No valid data to draw');
// 即使没有有效数据也绘制背景和图例 // 即使没有有效数据也绘制背景
drawBackground(); drawBackground();
drawLegend();
return; return;
} }
...@@ -122,41 +128,11 @@ const drawChart = () => { ...@@ -122,41 +128,11 @@ const drawChart = () => {
ctx.fillStyle = item.color; ctx.fillStyle = item.color;
ctx.fill(); ctx.fill();
ctx.strokeStyle = '#fff';
ctx.lineWidth = 1;
ctx.stroke();
});
};
// 步骤3:绘制右侧图例
const drawLegend = () => {
const legendX = centerX + 120; // 调整图例位置以适应新尺寸
const legendYStart = 60;
const itemGap = 25;
chartData.forEach((item, index) => {
const legendY = legendYStart + index * itemGap;
// 绘制颜色方块
ctx.fillStyle = item.color;
ctx.fillRect(legendX, legendY, 15, 15);
ctx.strokeStyle = '#e0e0e0';
ctx.strokeRect(legendX, legendY, 15, 15);
// 绘制类别名称
ctx.fillStyle = '#333';
ctx.font = '12px Microsoft YaHei';
ctx.fillText(item.name, legendX + 25, legendY + 12);
// 绘制数值
ctx.fillStyle = '#666';
ctx.fillText(item.value.toString(), legendX + 100, legendY + 12);
}); });
}; };
// 执行绘制流程 // 执行绘制流程
drawSectors(); drawSectors();
drawLegend();
}; };
// 5. 挂载后初始化图表(DOM 渲染完成后执行) // 5. 挂载后初始化图表(DOM 渲染完成后执行)
...@@ -187,14 +163,52 @@ defineExpose({ ...@@ -187,14 +163,52 @@ defineExpose({
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.chart-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.chart-canvas { .chart-canvas {
// background: #fff; // background: #fff;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
// margin: 20px 0;
display: block; display: block;
} }
.legend-container {
flex: 1;
margin-left: 20px;
}
.legend-item {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.color-block {
width: 15px;
height: 15px;
border: 1px solid #e0e0e0;
margin-right: 10px;
}
.legend-text {
display: flex;
flex-direction: column;
}
.legend-name {
font-size: 12px;
color: #333;
margin-bottom: 2px;
}
.legend-value {
font-size: 12px;
color: #666;
}
.wrapper{ .wrapper{
overflow: visible; overflow: visible;
...@@ -203,6 +217,7 @@ defineExpose({ ...@@ -203,6 +217,7 @@ defineExpose({
position: relative; position: relative;
padding: 0.15rem; padding: 0.15rem;
padding-top: 0.45rem; padding-top: 0.45rem;
.card-title { .card-title {
position: absolute; position: absolute;
left: 0.25rem; left: 0.25rem;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment