Commit 80da33e1 authored by xinzhedeai's avatar xinzhedeai

add:canvas charts circle

parent 62a1c35f
<template>
<!-- 图表容器 Canvas -->
<div class="chart-container wrapper">
<h2 class="card-title">设备状态总览</h2>
<canvas
ref="chartCanvasRef"
width="430"
height="290"
class="chart-canvas"
></canvas>
<h2 class="card-title">AI预警分析</h2>
<div class="chart-wrapper">
<canvas
ref="chartCanvasRef"
width="250"
height="250"
class="chart-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>
</template>
......@@ -26,7 +37,7 @@ interface RingLayer {
inner: number;
}
// 2. 核心配置与数据(可通过 props 透传扩展
// 2. 核心配置与数据(5个类别
const chartData: ChartDataItem[] = [
{ name: '疲劳驾驶', value: 10, color: '#409EFF' },
{ name: '违规打电话', value: 15, color: '#52C41A' },
......@@ -35,13 +46,13 @@ const chartData: ChartDataItem[] = [
{ name: '人脸丢失', value: 0, color: '#F5222D' },
];
// 调整环形图层尺寸以适应新的 canvas 尺寸
// 调整环形图层尺寸以适应新的 canvas 尺寸,增大环间距离
const ringLayers: RingLayer[] = [
{ outer: 110, inner: 100 }, // 第1层:疲劳闭眼
{ outer: 90, inner: 80 }, // 第3层:违规打电话
{ outer: 80, inner: 70 }, // 第4层:违规抽烟
{ outer: 70, inner: 60 }, // 第5层:左顾右盼
{ outer: 60, inner: 50 }, // 第6层:人脸丢失
{ outer: 100, inner: 85 }, // 第1层:疲劳驾驶
{ outer: 80, inner: 65 }, // 第2层:违规打电话
{ outer: 60, inner: 45 }, // 第3层:违规抽烟
{ outer: 40, inner: 25 }, // 第4层:左顾右盼
{ outer: 20, inner: 5 }, // 第5层:人脸丢失
];
// 3. 获取 Canvas 元素 Ref
......@@ -66,10 +77,10 @@ const drawChart = () => {
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const bgColor = '#E5E6EB'; // 每层独立背景色
const bgColor = '#2B4D79'; // 每层独立背景色
const startAngle = -Math.PI / 2; // 12点钟方向起始
// 步骤1:绘制每层独立的深灰色背景
// 步骤1:绘制每层独立的背景
const drawBackground = () => {
ringLayers.forEach((layer) => {
ctx.beginPath();
......@@ -78,10 +89,6 @@ const drawChart = () => {
ctx.closePath();
ctx.fillStyle = bgColor;
ctx.fill();
// 层间白色描边区分
ctx.strokeStyle = '#fff';
ctx.lineWidth = 1;
ctx.stroke();
});
};
......@@ -91,9 +98,8 @@ const drawChart = () => {
const total = validData.reduce((sum, item) => sum + item.value, 0);
if (total === 0) {
console.warn('No valid data to draw');
// 即使没有有效数据也绘制背景和图例
// 即使没有有效数据也绘制背景
drawBackground();
drawLegend();
return;
}
......@@ -122,41 +128,11 @@ const drawChart = () => {
ctx.fillStyle = item.color;
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();
drawLegend();
};
// 5. 挂载后初始化图表(DOM 渲染完成后执行)
......@@ -183,27 +159,66 @@ defineExpose({
.chart-container {
width: 100%;
overflow: auto;
background-image: url("@/assets/jinrun/module-bg.png");
background-repeat: no-repeat;
background-image: url("@/assets/jinrun/module-bg.png");
background-repeat: no-repeat;
}
.chart-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.chart-canvas {
// background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
// margin: 20px 0;
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{
overflow: visible;
width: 4.6rem;
overflow: visible;
width: 4.6rem;
height: 3rem;
position: relative;
padding: 0.15rem;
padding-top: 0.45rem;
.card-title {
.card-title {
position: absolute;
left: 0.25rem;
top: -0.15rem;
......
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