Commit 8ec065fa authored by xinzhedeai's avatar xinzhedeai

add:canvas绘制方法封装rev1

parent c3989c8e
......@@ -156,6 +156,19 @@ export default {
bgImage: null, // 背景图对象
waterImage: null, // 新增:water.png 图片对象
poImage: null, // 新增:po.png 图片对象
// Canvas绘制配置(支持批量扩展)
poConfigs: [
{ x: 0, y: null, width: 879, height: 150 }, // 第一张po.png配置
{ x: 0, y: null, width: 879 - 250, height: 150 } // 第二张po.png配置(宽度减少250px)
],
guanConfigs: [
{ x: null, y: null, width: 6, height: 121, image: 'guanImage' }, // 第一张guan0.png
{ x: null, y: null, width: 6, height: 200, image: 'guanImage' } // 第二张guan0.png(高度调整)
],
lineConfigs: [
{ points: [], color: 'red', lineWidth: 2 }, // 红色连接线配置
{ points: [], color: 'yellow', lineWidth: 2 } // 黄色连接线配置
]
};
},
created() {
......@@ -208,12 +221,144 @@ export default {
this.ctx.translate(0, this.canvas.height); // 向下移动画布高度
this.ctx.scale(1, -1); // 翻转 Y 轴方向(上为正)
// 加载背景图并绘制
this.loadBackgroundImage();
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
this.loadAllImages();
},
// 绘制单个po.png(支持配置参数)
drawPoImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// 动态计算y坐标(若未指定则默认画布底部-高度)
const y = config.y ? config.y : (this.canvas.height - config.height);
this.ctx.drawImage(
this.poImage,
config.x,
y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制单个guan.png(支持不同图片类型)
drawGuanImage(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
const targetImage = this[config.image]; // 根据配置获取具体图片对象(如guanImage/guanImage1)
this.ctx.drawImage(
targetImage,
config.x,
config.y,
config.width,
config.height
);
this.ctx.restore();
},
// 绘制连接线(支持多坐标点)
drawLine(config) {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.strokeStyle = config.color;
this.ctx.lineWidth = config.lineWidth;
this.ctx.beginPath();
config.points.forEach((point, index) => {
index === 0 ? this.ctx.moveTo(point.x, point.y) : this.ctx.lineTo(point.x, point.y);
});
this.ctx.stroke();
this.ctx.restore();
},
// 绘制背景图(独立方法)
drawBackground() {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.bgImage,
0,
0,
this.canvas.width,
this.canvas.height
);
this.ctx.restore();
},
// 绘制water.png(独立方法)
drawWaterImage() {
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.waterImage,
0,
this.canvas.height - 255,
485,
255
);
this.ctx.restore();
},
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages() {
const canvasHeight = this.canvas.height;
// 1. 绘制背景图
this.drawBackground();
// 2. 绘制po.png(遍历配置数组)
this.poConfigs.forEach((config, index) => {
// 第二张po.png的y坐标需要基于第一张计算(顶部对齐)
if (index === 1) {
const prevPo = this.poConfigs[0];
config.y = (canvasHeight - prevPo.height) - config.height; // 第一张顶部位置 - 自身高度
}
this.drawPoImage(config);
});
// 3. 绘制guan.png(遍历配置数组)
this.guanConfigs.forEach((config, index) => {
const firstPo = this.poConfigs[0];
const secondPo = this.poConfigs[1];
// 第一张guan.png坐标计算(基于第一张po.png)
if (index === 0) {
config.x = firstPo.width - 150; // 879 - 150
config.y = canvasHeight - 135.5; // 原计算逻辑
}
// 第二张guan.png坐标计算(基于第二张po.png)
if (index === 1) {
config.x = secondPo.width - 150; // secondPoWidth - 150
config.y = secondPo.y + 30; // secondPoY + 30
}
this.drawGuanImage(config);
});
// 4. 绘制连接线(遍历配置数组)
this.lineConfigs.forEach((config, index) => {
const firstGuan = this.guanConfigs[0];
const secondGuan = this.guanConfigs[1];
// 红色连接线坐标(原逻辑)
if (index === 0) {
config.points = [
{ x: firstGuan.x, y: firstGuan.y + 100 },
{ x: secondGuan.x, y: secondGuan.y + 50 },
{ x: secondGuan.x - 100, y: secondGuan.y - 10 } // 扩展第三点
];
}
// 黄色连接线坐标(原逻辑)
if (index === 1) {
config.points = [
{ x: firstGuan.x, y: firstGuan.y + 80 }, // 调整偏移量
{ x: secondGuan.x, y: secondGuan.y + 30 }
];
}
this.drawLine(config);
});
// 5. 绘制water.png
this.drawWaterImage();
},
/** 加载所有图片并绘制 */
loadAllImages() {
// 加载背景图(原有)
......@@ -231,12 +376,6 @@ export default {
// 加载 guan.png
this.guanImage = new Image();
this.guanImage.src = require("@/assets/images/jrx/guan0.png");
// 加载 guan1.png
this.guanImage1 = new Image();
this.guanImage1.src = require("@/assets/images/jrx/guan1.png");
// 加载 guan2.png
this.guanImage2 = new Image();
this.guanImage2.src = require("@/assets/images/jrx/guan2.png");
// 等待所有图片加载完成
Promise.all([
......@@ -244,8 +383,6 @@ export default {
new Promise((resolve) => (this.waterImage.onload = resolve)),
new Promise((resolve) => (this.poImage.onload = resolve)),
new Promise((resolve) => (this.guanImage.onload = resolve)),
new Promise((resolve) => (this.guanImage1.onload = resolve)),
new Promise((resolve) => (this.guanImage2.onload = resolve)),
])
.then(() => {
......@@ -267,164 +404,166 @@ export default {
* 6.超过4个po,要动态变换画布高度。
*/
drawAllImages() {
// 1. 绘制背景图(原有逻辑)
this.ctx.save(); // 保存当前变换状态
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认变换(不翻转)
this.ctx.drawImage(
this.bgImage,
0,
0,
this.canvas.width,
this.canvas.height
);
this.ctx.restore(); // 恢复之前的变换
// 3. 绘制 po.png(同样临时恢复默认坐标系)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.drawImage(
this.poImage,
0,
this.canvas.height - 150, // Y坐标调整为画布高度 - 图片高度
879,
150 // 绘制尺寸(与原尺寸一致)
);
this.ctx.restore();
// 新增:第二张po.png(在第一张上方叠加)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
const secondPoWidth = 879 - 250; // 宽度减少100px
const secondPoHeight = 150; // 高度保持不变
const secondPoY = (this.canvas.height - 150) - secondPoHeight; // Y坐标:第一张顶部位置(原Y坐标 - 自身高度)
this.ctx.drawImage(
this.poImage,
0, // X轴保持0
secondPoY, // Y轴为第一张顶部位置
secondPoWidth, // 新宽度
secondPoHeight // 保持高度
);
this.ctx.restore();
// 3. 绘制 guan0.png(po.png 右侧中间,上层)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// 计算位置:
// po.png 右侧 x 坐标 = po.png x + po.png 宽度 = 0 + 879 = 879
// po.png 垂直中间 y 坐标 = po.png y + po.png 高度/2 = (canvas.height - 150) + 75 = canvas.height - 75
// guan0.png 垂直居中需要 y = po.png中间y - guan0.png高度/2 = (canvas.height - 75) - (121/2) = canvas.height - 135.5
const guanX = 879 - 150;
const guanY = this.canvas.height - 135.5;
this.ctx.drawImage(
this.guanImage,
guanX,
guanY, // 目标位置(右侧中间)
6,
121 // 目标尺寸(宽6px,高121px)
);
this.ctx.restore();
/**
* canvas绘画原则。坐标轴从左上角开始画,y轴要从上往下找y轴的起始原点。
* canvasWidth:this.canvas.height // 画布的宽度(目前为600)
* poHeight:150px // 每个坡的高度
* guanPaddingTop:30px // 每个管孔距离对应层级坡顶部的距离
drawImage:(imgsrc, 起始x,起始y,绘画宽度距离, 绘画高度距离)
*/
// 新增:第二张guanImage(在第一张基础上叠加)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
const canvasHeight = this.canvas.height
const secondGuanX = secondPoWidth - 150; // x轴:原宽度值(6px)-250px
const secondGuanY = this.canvas.height - 135.5; // y轴:原高度值(121px)
this.ctx.drawImage(
this.guanImage,
secondGuanX, // 新x坐标
secondPoY + 30, // 新y坐标
6, // 保持宽度6px
200 // secondPoY/1.5 // 保持高度121px
);
console.log((secondPoY/2), '(secondPoY/2) ')
this.ctx.restore();
// 新增:绘制红色连接线(关键修改)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(原点在左上角)
this.ctx.strokeStyle = "red"; // 设置线颜色为红色
this.ctx.lineWidth = 2; // 设置线宽
this.ctx.beginPath(); // 开始路径
// 第一坐标点:第一个guanImage的x,y=guanY+30
this.ctx.moveTo(guanX, (guanY + 100));
// 第二坐标点:第二个guanImage的x,y=secondGuanY+30+150
this.ctx.lineTo(secondGuanX, secondGuanY+50);
// 新增:第三坐标点(示例坐标,需根据实际业务调整)
const thirdX = secondGuanX - 100; // 假设第三个点x坐标在第二个点基础上右移100px
const thirdY = secondGuanY - 10; // 假设第三个点y坐标在第二个点基础上下移80px(根据实际需求调整)
this.ctx.lineTo(thirdX, thirdY);
this.ctx.stroke(); // 描边绘制
this.ctx.restore();
// 新增:绘制红色连接线(关键修改)
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(原点在左上角)
this.ctx.strokeStyle = "yellow"; // 设置线颜色为红色
this.ctx.lineWidth = 2; // 设置线宽
this.ctx.beginPath(); // 开始路径
// 第一坐标点:第一个guanImage的x,y=guanY+30
this.ctx.moveTo(guanX, (guanY + 100 - 20));
// 第二坐标点:第二个guanImage的x,y=secondGuanY+30+150
this.ctx.lineTo(secondGuanX, secondGuanY+50 -20);
this.ctx.stroke(); // 描边绘制
this.ctx.restore();
// 2. 绘制 water.png(临时恢复默认坐标系,避免翻转)
this.ctx.save(); // 保存当前变换状态
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认变换(不翻转)
this.ctx.drawImage(
this.waterImage,
0,
this.canvas.height - 255, // Y坐标调整为画布高度 - 图片高度(原点在左下角)
485,
255 // 绘制尺寸(与原尺寸一致)
);
this.ctx.restore(); // 恢复之前的变换
},
/** 加载背景图并绘制 */
loadBackgroundImage() {
this.bgImage = new Image();
this.bgImage.src = require("@/assets/images/jrx/bg.png"); // 路径根据项目实际结构调整
// 图片加载完成后绘制
this.bgImage.onload = () => {
// 绘制背景图(注意:坐标系已变换,Y轴向上)
// 原点在左下角,直接从 (0,0) 开始绘制,高度方向需适配翻转后的坐标系
this.ctx.drawImage(
this.bgImage,
0,
0, // 图片在画布上的起始坐标(左下角原点)
this.canvas.width, // 绘制宽度
this.canvas.height // 绘制高度
);
};
// 处理图片加载错误
this.bgImage.onerror = () => {
console.error("背景图加载失败");
this.ctx.fillStyle = "#f0f0f0";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
};
},
// drawAllImages() {
// const canvasWidth = this.canvas.width
// const canvasHeight = this.canvas.height
// // 1. 绘制背景图(原有逻辑)
// this.ctx.save(); // 保存当前变换状态
// this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认变换(不翻转)
// this.ctx.drawImage(
// this.bgImage,
// 0,
// 0,
// this.canvas.width,
// this.canvas.height
// );
// this.ctx.restore(); // 恢复之前的变换
// // 3. 绘制 po.png(同样临时恢复默认坐标系)
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// this.ctx.drawImage(
// this.poImage,
// 0,
// this.canvas.height - 150, // Y坐标调整为画布高度 - 图片高度
// 879,
// 150 // 绘制尺寸(与原尺寸一致)
// );
// this.ctx.restore();
// // 新增:第二张po.png(在第一张上方叠加)
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// const secondPoWidth = 879 - 250; // 宽度减少100px
// const secondPoHeight = 150; // 高度保持不变
// const secondPoY = (this.canvas.height - 150) - secondPoHeight; // Y坐标:第一张顶部位置(原Y坐标 - 自身高度)
// this.ctx.drawImage(
// this.poImage,
// 0, // X轴保持0
// secondPoY, // Y轴为第一张顶部位置
// secondPoWidth, // 新宽度
// secondPoHeight // 保持高度
// );
// this.ctx.restore();
// // 3. 绘制 guan0.png(po.png 右侧中间,上层)
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// // 计算位置:
// // po.png 右侧 x 坐标 = po.png x + po.png 宽度 = 0 + 879 = 879
// // po.png 垂直中间 y 坐标 = po.png y + po.png 高度/2 = (canvas.height - 150) + 75 = canvas.height - 75
// // guan0.png 垂直居中需要 y = po.png中间y - guan0.png高度/2 = (canvas.height - 75) - (121/2) = canvas.height - 135.5
// const guanX = 879 - 150;
// const guanY = this.canvas.height - 135.5;
// this.ctx.drawImage(
// this.guanImage,
// guanX,
// guanY, // 目标位置(右侧中间)
// 6,
// 121 // 目标尺寸(宽6px,高121px)
// );
// this.ctx.restore();
// /**
// * canvas绘画原则。坐标轴从左上角开始画,y轴要从上往下找y轴的起始原点。
// * canvasWidth:this.canvas.height // 画布的宽度(目前为600)
// * poHeight:150px // 每个坡的高度
// * guanPaddingTop:30px // 每个管孔距离对应层级坡顶部的距离
// drawImage:(imgsrc, 起始x,起始y,绘画宽度距离, 绘画高度距离)
// */
// // 新增:第二张guanImage(在第一张基础上叠加)
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// const secondGuanX = secondPoWidth - 150; // x轴:原宽度值(6px)-250px
// const secondGuanY = this.canvas.height - 135.5; // y轴:原高度值(121px)
// this.ctx.drawImage(
// this.guanImage,
// secondGuanX, // 新x坐标
// secondPoY + 30, // 新y坐标
// 6, // 保持宽度6px
// 200 // secondPoY/1.5 // 保持高度121px
// );
// console.log((secondPoY/2), '(secondPoY/2) ')
// this.ctx.restore();
// // 新增:绘制红色连接线(关键修改)
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(原点在左上角)
// this.ctx.strokeStyle = "red"; // 设置线颜色为红色
// this.ctx.lineWidth = 2; // 设置线宽
// this.ctx.beginPath(); // 开始路径
// // 第一坐标点:第一个guanImage的x,y=guanY+30
// this.ctx.moveTo(guanX, (guanY + 100));
// // 第二坐标点:第二个guanImage的x,y=secondGuanY+30+150
// this.ctx.lineTo(secondGuanX, secondGuanY+50);
// // 新增:第三坐标点(示例坐标,需根据实际业务调整)
// const thirdX = secondGuanX - 100; // 假设第三个点x坐标在第二个点基础上右移100px
// const thirdY = secondGuanY - 10; // 假设第三个点y坐标在第二个点基础上下移80px(根据实际需求调整)
// this.ctx.lineTo(thirdX, thirdY);
// this.ctx.stroke(); // 描边绘制
// this.ctx.restore();
// // 新增:绘制红色连接线(关键修改)
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认坐标系(原点在左上角)
// this.ctx.strokeStyle = "yellow"; // 设置线颜色为红色
// this.ctx.lineWidth = 2; // 设置线宽
// this.ctx.beginPath(); // 开始路径
// // 第一坐标点:第一个guanImage的x,y=guanY+30
// this.ctx.moveTo(guanX, (guanY + 100 - 20));
// // 第二坐标点:第二个guanImage的x,y=secondGuanY+30+150
// this.ctx.lineTo(secondGuanX, secondGuanY+50 -20);
// this.ctx.stroke(); // 描边绘制
// this.ctx.restore();
// // 2. 绘制 water.png(临时恢复默认坐标系,避免翻转)
// this.ctx.save(); // 保存当前变换状态
// this.ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认变换(不翻转)
// this.ctx.drawImage(
// this.waterImage,
// 0,
// this.canvas.height - 255, // Y坐标调整为画布高度 - 图片高度(原点在左下角)
// 485,
// 255 // 绘制尺寸(与原尺寸一致)
// );
// this.ctx.restore(); // 恢复之前的变换
// },
// /** 加载背景图并绘制 */
// loadBackgroundImage() {
// this.bgImage = new Image();
// this.bgImage.src = require("@/assets/images/jrx/bg.png"); // 路径根据项目实际结构调整
// // 图片加载完成后绘制
// this.bgImage.onload = () => {
// // 绘制背景图(注意:坐标系已变换,Y轴向上)
// // 原点在左下角,直接从 (0,0) 开始绘制,高度方向需适配翻转后的坐标系
// this.ctx.drawImage(
// this.bgImage,
// 0,
// 0, // 图片在画布上的起始坐标(左下角原点)
// this.canvas.width, // 绘制宽度
// this.canvas.height // 绘制高度
// );
// };
// // 处理图片加载错误
// this.bgImage.onerror = () => {
// console.error("背景图加载失败");
// this.ctx.fillStyle = "#f0f0f0";
// this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// };
// },
/** 初始化图表(关键修改:调整图例位置) */
initChart() {
return;
......
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