function Diagram() {
|
this.stc = ""; // 静态层canvas
|
this.flush = ""; // 刷新层canvas
|
this.s_ctx = ""; // 静态层上下文
|
this.f_ctx = ""; // 刷新层上下文
|
this.width = 1500; // 默认宽度
|
this.height = 750; // 默认高度
|
this.options = []; // 所有配置对象
|
this.flushOptions = []; // 需要刷新的对象
|
this.handleObj = []; // 可以触发事件的对象
|
this.opts = { // 默认配置
|
lineWidth: 3, // 线宽
|
onOffBase: { // 开关的基础配置
|
radius: 4,
|
width: 28,
|
lineWidth: 2,
|
},
|
moveDot: {
|
radius: 6,
|
step: 2.2,
|
gravity: 0.08
|
}
|
};
|
// 显示线条的id
|
this.showLineId = false;
|
}
|
|
// 设置canvas
|
Diagram.prototype.setCanvas = function (stc, flush) {
|
// 设置静态canvas
|
this.stc = document.createElement('canvas');
|
stc.appendChild(this.stc);
|
this.stc.width = this.width;
|
this.stc.height = this.height;
|
this.s_ctx = this.stc.getContext('2d');
|
|
// 设置动态canvas
|
this.flush = document.createElement('canvas');
|
flush.appendChild(this.flush);
|
this.flush.width = this.width;
|
this.flush.height = this.height;
|
this.f_ctx = this.flush.getContext('2d');
|
|
this.startState = false;
|
|
// 启动更新
|
this.start(true);
|
};
|
|
|
// 启动更新
|
Diagram.prototype.start = function (start) {
|
if (start) {
|
console.log('已经启动持续更新');
|
this.startState = true;
|
}
|
|
// 停止更新
|
if (!this.startState) {
|
return;
|
}
|
// 更新所有的配置项
|
this._update();
|
// 持续更新函数
|
requestAnimationFrame(() => {
|
this.start();
|
});
|
this.f_ctx.save();
|
this.f_ctx.fillStyle = "rgba(0, 0, 0, 0.9)";
|
this.f_ctx.globalCompositeOperation = 'destination-in';
|
this.f_ctx.fillRect(0, 0, this.width, this.height);
|
this.f_ctx.restore();
|
|
}
|
|
// 停止更新
|
Diagram.prototype.stop = function () {
|
this.startState = false;
|
console.log('已经停止持续更新');
|
};
|
|
// 更新整个图表
|
Diagram.prototype._update = function () {
|
// 清空图表
|
//this.f_ctx.clearRect(0, 0, this.width, this.height);
|
let options = this.flushOptions;
|
options.forEach(option => {
|
this.update(option);
|
});
|
};
|
// 根据配置项更新图表
|
Diagram.prototype.update = function (option) {
|
if (option && option.method && typeof this[option.method] == 'function') {
|
this[option.method](option);
|
}
|
}
|
|
/**
|
* 检测对象是否在数组中
|
*
|
* @param {[object]} option 需要检测的对象
|
*
|
* @param {[Array]} options 对象数组
|
*
|
* @return {[Boolean]} 返回对象是否在对象数组中
|
*/
|
Diagram.prototype.checkObjInArr = function (option, options) {
|
// 如果未设置id
|
if (!option.id) {
|
return true;
|
}
|
|
// 根据id判断
|
let isIn = false;
|
for (let i = 0; i < options.length; i++) {
|
let _option = options[i];
|
if (option.id == _option.id) {
|
isIn = true;
|
break;
|
}
|
}
|
// 返回结果
|
return isIn;
|
}
|
|
// 添加配置项
|
Diagram.prototype.addOptions = function (option) {
|
// 检测配置项是否在配置项中
|
let options = this.options;
|
// 检测对象不在对象中
|
if (!this.checkObjInArr(option, options)) {
|
options.push(option);
|
// 可刷新,添加到刷新配置项
|
if (option.flush) {
|
this.flushOptions.push(option);
|
}
|
}
|
};
|
|
// 修改配置信息
|
Diagram.prototype.changeOption = function (id, attr, value, options) {
|
for (let i = 0; i < options.length; i++) {
|
let _option = options[i];
|
if (id == _option.id) {
|
_option[attr] = value;
|
break;
|
}
|
}
|
};
|
|
// 设置配置的值(仅可以设置刷新层的内容)
|
Diagram.prototype.setOption = function (id, attr, value) {
|
let options = this.flushOptions;
|
this.changeOption(id, attr, value, options);
|
};
|
|
// 获取option
|
Diagram.prototype.getOption = function (id) {
|
let options = this.options;
|
let result = false;
|
for (let i = 0; i < options.length; i++) {
|
let option = options[i];
|
if (option.id == id) {
|
result = option;
|
}
|
}
|
return result;
|
}
|
|
// 绘制线
|
Diagram.prototype.line = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
|
let points = option.points;
|
let opts = this.opts;
|
ctx.beginPath();
|
ctx.lineWidth = option.lineWidth ? option.lineWidth : opts.lineWidth;
|
ctx.strokeStyle = option.strokeStyle ? option.strokeStyle : "#b370fe";
|
points.forEach((point, index) => {
|
if (index != 0) {
|
ctx.lineTo(point[0], point[1]);
|
} else {
|
ctx.moveTo(point[0], point[1]);
|
}
|
});
|
if (!option.hide) {
|
ctx.stroke();
|
}
|
// 控制线条id显示
|
if (this.showLineId) {
|
let point = [];
|
if (points[0][0] == points[1][0]) {
|
// 设置x轴坐标
|
point[0] = points[0][0];
|
// 设置y轴坐标
|
if (points[0][1] > points[1][1]) {
|
point[1] = points[1][1] + (points[0][1] - points[1][1]) / 2;
|
} else {
|
point[1] = points[1][1] + (points[0][1] - points[1][1]) / 2;
|
}
|
} else {
|
// 设置y轴坐标
|
point[1] = points[0][1];
|
// 设置x轴坐标
|
if (points[0][0] > points[1][0]) {
|
point[0] = points[1][0] + (points[0][0] - points[1][0]) / 2;
|
} else {
|
point[0] = points[1][0] + (points[0][0] - points[1][0]) / 2;
|
}
|
|
}
|
this.text({
|
text: option.id ? option.id : '',
|
point: point,
|
hide: option.hide,
|
});
|
}
|
// 设置执行的方法
|
option.method = "line";
|
// 添加配置项
|
this.addOptions(option);
|
return points;
|
};
|
|
// 绘制点线
|
Diagram.prototype.dashLine = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
|
let opts = this.opts;
|
let points = option.points;
|
ctx.beginPath();
|
// 设置间距(参数为无限数组,虚线的样式会随数组循环)
|
ctx.setLineDash([2, 4]);
|
ctx.lineWidth = option.lineWidth ? option.lineWidth : opts.lineWidth;
|
ctx.strokeStyle = option.strokeStyle ? option.strokeStyle : "#b370fe";
|
points.forEach((point, index) => {
|
if (index != 0) {
|
ctx.lineTo(point[0], point[1]);
|
} else {
|
ctx.moveTo(point[0], point[1]);
|
}
|
});
|
ctx.stroke();
|
// 切回实线
|
ctx.setLineDash([]);
|
return points;
|
};
|
|
// 绘制充放电单元
|
Diagram.prototype.chargeAndDischarge = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
|
let defaultOption = {
|
width: 120,
|
};
|
let point = option.point;
|
let strokeStyle = '#FFFFFF';
|
let lineWidth = option.lineWidth ? option.lineWidth : 2;
|
let leftHide = (option.hide || option.leftHide) ? true : false;
|
let rightHide = (option.hide || option.rightHide) ? true : false;
|
// 线条1
|
let line1 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: leftHide,
|
points: [
|
point,
|
[point[0], point[1] - defaultOption.width / 2]
|
],
|
});
|
|
// 线条2
|
let line2 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: leftHide,
|
points: [
|
line1[1],
|
[line1[1][0] + defaultOption.width, line1[1][1]]
|
],
|
});
|
|
// 线条3
|
let line3 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: rightHide,
|
points: [
|
line2[1],
|
[line2[1][0] + defaultOption.width, line2[1][1]]
|
],
|
});
|
|
// 线条4
|
let line4 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: rightHide,
|
points: [
|
line3[1],
|
[line3[1][0], line3[1][1] + defaultOption.width]
|
],
|
});
|
|
// 线条5
|
let line5 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: rightHide,
|
points: [
|
line4[1],
|
[line4[1][0] - defaultOption.width, line1[1][1] + defaultOption.width]
|
],
|
});
|
|
// 线条6
|
let line6 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: leftHide,
|
points: [
|
line5[1],
|
[line1[1][0], line1[1][1] + defaultOption.width]
|
],
|
});
|
|
// 线条7
|
let line7 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
line6[1],
|
[line1[0][0], line1[0][1]]
|
],
|
});
|
|
// 线条8
|
let line8 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
[line1[1][0] + defaultOption.width, line1[1][1]],
|
[line1[1][0] + defaultOption.width, line1[1][1] + defaultOption.width]
|
],
|
});
|
|
return [
|
[line1[1][0] + defaultOption.width / 2, line1[1][1]],
|
[line1[1][0] + defaultOption.width * 3 / 2, line1[1][1]],
|
[line1[1][0] + defaultOption.width * 3 / 2, line1[1][1] + defaultOption.width],
|
[line1[1][0] + defaultOption.width / 2, line1[1][1] + defaultOption.width],
|
]
|
};
|
|
// 绘制圆
|
Diagram.prototype.arc = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
|
let point = option.point; //圆心坐标
|
// 不隐藏绘制圆圈
|
if (!option.hide) {
|
ctx.beginPath();
|
ctx.lineWidth = option.lineWidth ? option.lineWidth : 1;
|
ctx.strokeStyle = option.strokeStyle;
|
ctx.fillStyle = option.fillStyle;
|
ctx.arc(point[0], point[1], option.radius, 0, 2 * Math.PI);
|
switch (option.type) {
|
case 'stroke':
|
ctx.stroke();
|
break;
|
case 'fill':
|
ctx.fill();
|
break;
|
default:
|
ctx.stroke();
|
ctx.fill();
|
break;
|
}
|
}
|
|
let info = {
|
center: [point[0], point[1]],
|
left: [point[0] - option.radius, point[1]],
|
right: [point[0] + option.radius, point[1]],
|
top: [point[0], point[1] - option.radius],
|
bottom: [point[0], point[1] + option.radius],
|
tl: [point[0] - option.radius / 2, point[1] - option.radius / 2],
|
tr: [point[0] + option.radius / 2, point[1] - option.radius / 2],
|
bl: [point[0] - option.radius / 2, point[1] + option.radius / 2],
|
br: [point[0] + option.radius / 2, point[1] + option.radius / 2],
|
strokeStyle: option.strokeStyle,
|
fillStyle: option.fillStyle,
|
radius: option.radius
|
};
|
// 添加配置项
|
option.method = "arc";
|
|
this.addOptions(option);
|
return info;
|
};
|
|
// 绘制开关
|
Diagram.prototype.onOff = function (option) {
|
let result;
|
switch (option.direction) {
|
case 'top':
|
case 'bottom':
|
result = this.onOff_h(option);
|
break;
|
default:
|
result = this.onOff_v(option);
|
break;
|
}
|
// 添加配置项
|
option.method = "onOff";
|
this.addOptions(option);
|
// 返回开关的信息
|
return result;
|
};
|
|
// 水平方向
|
Diagram.prototype.onOff_v = function (option) {
|
let point = option.point;
|
let state = option.state ? true : false;
|
let onOffBase = this.opts.onOffBase;
|
|
// 开关的第一个圆
|
let arc1 = this.arc({
|
point: [point[0] + onOffBase.radius / 2, point[1]],
|
flush: option.flush,
|
fillStyle: '#50cef5',
|
strokeStyle: '#50cef5',
|
radius: onOffBase.radius,
|
type: 'stroke'
|
});
|
|
// 开关的第二个圆
|
let arc2 = this.arc({
|
point: [arc1.right[0] + onOffBase.width * 4 / 3, arc1.right[1]],
|
flush: option.flush,
|
fillStyle: arc1.fillStyle,
|
strokeStyle: arc1.fillStyle,
|
radius: arc1.radius,
|
type: 'stroke'
|
});
|
let line1;
|
switch (option.direction) {
|
case 'right':
|
// 绘制线条
|
line1 = this.line({
|
points: [
|
arc2.left,
|
[
|
state ? arc1.top[0] : arc1.center[0],
|
state ? arc1.top[1] : arc1.center[1] - (arc1.radius + onOffBase.width * 3 / 4)
|
],
|
],
|
flush: option.flush,
|
strokeStyle: state ? '#b370fe' : '#50cef5',
|
lineWidth: onOffBase.lineWidth
|
});
|
break;
|
default:
|
// 绘制线条
|
line1 = this.line({
|
points: [
|
arc1.right,
|
[
|
state ? arc2.top[0] : arc2.center[0],
|
state ? arc2.top[1] : arc2.center[1] - (arc2.radius + onOffBase.width * 3 / 4)
|
],
|
],
|
flush: option.flush,
|
strokeStyle: state ? '#b370fe' : '#50cef5',
|
lineWidth: onOffBase.lineWidth
|
});
|
break;
|
}
|
return {
|
arc1: arc1,
|
arc2: arc2,
|
line1: line1
|
}
|
};
|
// 竖直方向
|
Diagram.prototype.onOff_h = function (option) {
|
let point = option.point;
|
let state = option.state ? true : false;
|
let onOffBase = this.opts.onOffBase;
|
|
// 开关的第一个圆
|
let arc1 = this.arc({
|
point: [point[0], point[1] + onOffBase.radius],
|
flush: option.flush,
|
fillStyle: '#50cef5',
|
strokeStyle: '#50cef5',
|
radius: onOffBase.radius,
|
type: 'stroke'
|
});
|
|
// 开关的第二个圆
|
let arc2 = this.arc({
|
point: [arc1.bottom[0], arc1.right[1] + onOffBase.width * 4 / 3],
|
flush: option.flush,
|
fillStyle: arc1.fillStyle,
|
strokeStyle: arc1.fillStyle,
|
radius: arc1.radius,
|
type: 'stroke'
|
});
|
|
let line1;
|
switch (option.direction) {
|
case 'top':
|
// 绘制线条
|
line1 = this.line({
|
points: [
|
arc1.bottom,
|
[
|
state ? arc2.right[0] : arc2.center[0] + (arc1.radius + onOffBase.width * 3 / 4),
|
state ? arc2.right[1] : arc2.center[1]
|
],
|
],
|
flush: option.flush,
|
strokeStyle: state ? '#b370fe' : '#50cef5',
|
lineWidth: onOffBase.lineWidth
|
});
|
break;
|
default:
|
// 绘制线条
|
line1 = this.line({
|
points: [
|
arc2.top,
|
[
|
state ? arc1.right[0] : arc1.center[0] + (arc2.radius + onOffBase.width * 3 / 4),
|
state ? arc1.right[1] : arc1.center[1]
|
],
|
],
|
flush: option.flush,
|
strokeStyle: state ? '#b370fe' : '#50cef5',
|
lineWidth: onOffBase.lineWidth
|
});
|
break;
|
}
|
return {
|
arc1: arc1,
|
arc2: arc2,
|
line1: line1
|
}
|
};
|
|
// BAT
|
Diagram.prototype.bat = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
let bat = {
|
width: 14
|
};
|
ctx.fillStyle = option.fillStyle ? option.fillStyle : "#b370fe";
|
ctx.strokeStyle = option.strokeStyle;
|
ctx.lineWidth = option.lineWidth ? option.lineWidth : 3;
|
|
ctx.fillRect(point[0] - bat.width / 2, point[1] - bat.width / 2, bat.width, bat.width);
|
|
ctx.strokeRect(point[0] - bat.width / 2, point[1] - bat.width / 2, bat.width, bat.width)
|
return {
|
top: [point[0], point[1] - bat.width / 2],
|
bottom: [point[0], point[1] + bat.width / 2],
|
left: [point[0] - bat.width / 2 - ctx.lineWidth / 2, point[1]],
|
right: [point[0] + bat.width / 2 + ctx.lineWidth / 2, point[1]]
|
}
|
};
|
|
// 绘制图片
|
Diagram.prototype.drawImage = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
// 绘制内容
|
if (!option.hide) {
|
let img = new Image();
|
img.src = option.url;
|
if (option.flush) {
|
ctx.drawImage(img, point[0], point[1], option.width, option.height);
|
} else {
|
img.onload = function () {
|
ctx.drawImage(img, point[0], point[1], option.width, option.height);
|
}
|
}
|
|
}
|
|
// 返回图片信息
|
let info = {
|
tl: [point[0], point[1]],
|
tr: [point[0] + option.width, point[1]],
|
bl: [point[0], point[1] + option.height],
|
br: [point[0] + option.width, point[1] + option.height],
|
left: [point[0], point[1] + option.height / 2],
|
right: [point[0] + option.width, point[1] + option.height / 2],
|
top: [point[0] + option.width / 2, point[1]],
|
bottom: [point[0] + option.width / 2, point[1] + option.height],
|
width: option.width,
|
height: option.height,
|
};
|
|
// 设置执行的方法
|
option.method = "drawImage";
|
// 添加配置项
|
this.addOptions(option);
|
return info;
|
};
|
|
// 绘制字体
|
Diagram.prototype.text = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
let fontSize = option.fontSize ? option.fontSize : 12;
|
let texts = option.text.split('&');
|
ctx.beginPath();
|
ctx.fillStyle = option.fillStyle ? option.fillStyle : '#FFFFFF';
|
ctx.lineWidth = option.lineWidth ? option.lineWidth : 1;
|
ctx.font = fontSize + 'px Arial';
|
ctx.textAlign = option.align ? option.align : 'start';
|
ctx.textBaseline = option.baseline ? option.baseline : 'top';
|
if (!option.hide) {
|
texts.forEach((text, index) => {
|
if (index == 0) {
|
ctx.fillText(text, point[0], point[1] + fontSize * index);
|
} else {
|
ctx.fillText(text, point[0], point[1] + (fontSize + 4) * index);
|
}
|
|
});
|
}
|
|
|
// 设置执行的方法
|
option.method = "text";
|
// 添加配置项
|
this.addOptions(option);
|
};
|
|
// 绘制可移动的点
|
Diagram.prototype.moveDot = function (option) {
|
let ctx = this.f_ctx;
|
let opts = this.opts.moveDot;
|
let points = option.points;
|
let start = option.start ? option.start : [points[0][0], points[0][1]];
|
let fillStyle = option.fillStyle ? option.fillStyle : "#b370fe";
|
let strokeStyle = option.strokeStyle ? option.strokeStyle : "#b370fe";
|
let radius = option.radius ? option.radius : opts.radius;
|
if (this.getOption(option.id)) {
|
switch (option.type) {
|
case 'up':
|
start[1] -= opts.step;
|
// 约束限制
|
if (start[1] < points[1][1]) {
|
start[1] = points[0][1];
|
}
|
break;
|
case 'down':
|
start[1] += opts.step;
|
// 约束限制
|
if (start[1] > points[1][1]) {
|
start[1] = points[0][1];
|
}
|
break;
|
case 'left':
|
start[0] += opts.step;
|
// 约束限制
|
if (start[0] > points[1][0]) {
|
start[0] = points[0][0];
|
}
|
break;
|
case 'right':
|
start[0] -= opts.step;
|
// 约束限制
|
if (start[0] < points[1][0]) {
|
start[0] = points[0][0];
|
}
|
}
|
// 设置值
|
this.setOption(option.id, 'start', start);
|
} else {
|
// 竖直运动
|
if (points[0][0] == points[1][0]) {
|
// 向上运动
|
if (points[0][1] > points[1][1]) {
|
option.type = 'up';
|
} else {
|
option.type = 'down';
|
}
|
} else {
|
// 向左运动
|
if (points[0][0] < points[1][0]) {
|
option.type = 'left';
|
} else {
|
option.type = 'right';
|
}
|
}
|
option.start = start;
|
}
|
this.arc({
|
flush: true,
|
point: start,
|
fillStyle: fillStyle,
|
strokeStyle: strokeStyle,
|
radius: radius
|
});
|
// 添加配置项
|
option.method = "moveDot";
|
this.addOptions(option);
|
};
|
|
// 绘制二极管
|
Diagram.prototype.diode = function (option) {
|
let result = {};
|
switch (option.direction) {
|
case 'down':
|
result = this.diodeDown(option);
|
break;
|
case 'right':
|
result = this.diodeRight(option);
|
break;
|
default:
|
result = this.diodeUp(option);
|
break;
|
}
|
return result;
|
};
|
|
// 向右的
|
Diagram.prototype.diodeRight = function(option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
let width = 40;
|
let height = width * 2 / 3;
|
let lineWidth = 2;
|
|
// line1
|
let line1 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
point,
|
[point[0]+ width / 2, point[1]]
|
]
|
});
|
ctx.beginPath();
|
ctx.moveTo(line1[1][0], line1[1][1] - width / 2);
|
ctx.lineTo(line1[1][0], line1[1][1] + width / 2);
|
ctx.lineTo(line1[1][0] + height, line1[1][1]);
|
ctx.closePath();
|
ctx.fillStyle = "#b370fe";
|
ctx.fill();
|
|
// line2
|
let line2 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
[line1[1][0]+ height, line1[1][1] - width / 2],
|
[line1[1][0] + height, line1[1][1] + width / 2 ]
|
]
|
});
|
|
// line3
|
let line3 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
[line1[1][0]+ height, line1[1][1]],
|
[line1[1][0]+ height + width / 2, line1[1][1]]
|
]
|
});
|
|
return {
|
left: line1[0],
|
right: line3[1]
|
}
|
};
|
|
// 向上的
|
Diagram.prototype.diodeUp = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
let width = 40;
|
let height = width * 2 / 3;
|
let lineWidth = 2;
|
// line1
|
let line1 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
point,
|
[point[0], point[1] + width / 2]
|
]
|
});
|
// line2
|
let line2 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
[line1[1][0] - width / 2, line1[1][1]],
|
[line1[1][0] + width / 2, line1[1][1]]
|
]
|
});
|
ctx.beginPath();
|
ctx.moveTo(line1[1][0], line1[1][1]);
|
ctx.lineTo(line2[0][0], line2[0][1] + height);
|
ctx.lineTo(line2[1][0], line2[1][1] + height);
|
ctx.closePath();
|
ctx.fillStyle = "#b370fe";
|
ctx.fill();
|
|
// line3
|
let line3 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
[line1[1][0], line1[1][1] + height],
|
[line1[1][0], line1[1][1] + height + width / 2]
|
]
|
});
|
|
// 添加配置项
|
option.method = "diode";
|
this.addOptions(option);
|
return {
|
top: line1[0],
|
bottom: line3[1]
|
}
|
};
|
// 向下的
|
Diagram.prototype.diodeDown = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
let width = 40;
|
let height = width * 2 / 3;
|
let lineWidth = 2;
|
// line1
|
let line1 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
point,
|
[point[0], point[1] + width / 2]
|
]
|
});
|
// line2
|
// let line2 = this.line({
|
// strokeStyle: "#b370fe",
|
// lineWidth: lineWidth,
|
// points: [
|
// [line1[1][0] - width / 2, line1[1][1]],
|
// [line1[1][0] + width / 2, line1[1][1]]
|
// ]
|
// });
|
ctx.beginPath();
|
ctx.moveTo(line1[1][0] - width / 2, line1[1][1]);
|
ctx.lineTo(line1[1][0] + width / 2, line1[1][1]);
|
ctx.lineTo(line1[1][0], line1[1][1] + height);
|
ctx.closePath();
|
ctx.fillStyle = "#b370fe";
|
ctx.fill();
|
// line2
|
let line2 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
[line1[1][0] - width / 2, line1[1][1] + height],
|
[line1[1][0] + width / 2, line1[1][1] + height]
|
]
|
});
|
// line3
|
let line3 = this.line({
|
strokeStyle: "#b370fe",
|
lineWidth: lineWidth,
|
points: [
|
[line1[1][0], line1[1][1] + height],
|
[line1[1][0], line1[1][1] + height + width / 2]
|
]
|
});
|
|
// 添加配置项
|
option.method = "diode";
|
this.addOptions(option);
|
return {
|
top: line1[0],
|
bottom: line3[1]
|
}
|
};
|
// 绘制矩形
|
Diagram.prototype.drawRect = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
|
let defaultOption = option.size?option.size:{
|
width: 120,
|
height: 120,
|
};
|
let point = option.point;
|
let strokeStyle = option.strokeStyle?option.strokeStyle:'#FFFFFF';
|
let lineWidth = option.lineWidth ? option.lineWidth : 2;
|
// 线条1
|
let line1 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
point,
|
[point[0], point[1] + defaultOption.height]
|
],
|
});
|
|
// 线条2
|
let line2 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
line1[1],
|
[line1[1][0] + defaultOption.width, line1[1][1]]
|
],
|
});
|
|
// 线条3
|
let line3 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
line2[1],
|
[line2[1][0], line2[1][1] - defaultOption.height]
|
],
|
});
|
|
// 线条4
|
let line4 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
line3[1],
|
line1[0]
|
],
|
});
|
|
return {
|
left: [line1[0][0], line1[0][1] + defaultOption.height / 2],
|
bottom: [line2[0][0] + defaultOption.width / 2, line2[0][1]],
|
right: [line3[0][0], line3[0][1] - defaultOption.height / 2],
|
top: [line1[0][0] + defaultOption.width / 2, line1[0][1]]
|
};
|
|
};
|
|
// 绘制电池
|
Diagram.prototype.battery = function (option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx;
|
let point = option.point;
|
let width = option.width ? option.width : 80;
|
let height = width * 0.08;
|
|
// 电池第一层
|
let l1Width = width * 0.3;
|
let l1Height = height;
|
let l1point = [point[0] + width / 2 - l1Width / 2, point[1]];
|
let g1 = ctx.createLinearGradient(l1point[0], l1point[1], l1point[0] + l1Width, l1point[1]);
|
g1.addColorStop(0, "#acacac");
|
g1.addColorStop(0.3, "#f4f4f4");
|
g1.addColorStop(1, "#231806");
|
ctx.fillStyle = g1;
|
ctx.fillRect(l1point[0], l1point[1], l1Width, l1Height);
|
|
// 电池第二层
|
let l2Point = [point[0], l1point[1] + height];
|
let l2Height = height;
|
let g2 = ctx.createLinearGradient(l2Point[0], l2Point[1], l2Point[0] + width, l2Point[1]);
|
g2.addColorStop(0, "#a2a19f");
|
g2.addColorStop(0.1, "#dedcdd");
|
g2.addColorStop(0.5, "#51504c");
|
g2.addColorStop(0.75, "#9fa4a8");
|
g2.addColorStop(1, "#3c3230");
|
ctx.fillStyle = g2;
|
ctx.fillRect(l2Point[0], l2Point[1], width, l2Height);
|
|
// 电池第三层
|
let l3Point = [point[0], l2Point[1] + height];
|
let l3Height = width * 3 / 2 + height;
|
let g3 = ctx.createLinearGradient(l3Point[0], l3Point[1], l3Point[0] + width, l3Point[1]);
|
g3.addColorStop(0, "#6a6e9150");
|
g3.addColorStop(0.1, "#69749480");
|
g3.addColorStop(0.11, "#a8adc380");
|
g3.addColorStop(0.3, "#454d7b80");
|
g3.addColorStop(0.31, "#454d7b10");
|
g3.addColorStop(1, "#454d7b80");
|
ctx.fillStyle = g3;
|
ctx.fillRect(l3Point[0], l3Point[1], width, l3Height);
|
|
// 电池第四层
|
let l4Point = [point[0], l3Point[1] + l3Height];
|
let l4Height = height;
|
let g4 = ctx.createLinearGradient(l4Point[0], l4Point[1], l4Point[0] + width, l4Point[1]);
|
g4.addColorStop(0, "#a2a19f");
|
g4.addColorStop(0.1, "#dedcdd");
|
g4.addColorStop(0.5, "#51504c");
|
g4.addColorStop(0.75, "#9fa4a8");
|
g4.addColorStop(1, "#3c3230");
|
ctx.fillStyle = g4;
|
ctx.fillRect(l4Point[0], l4Point[1], width, l4Height);
|
|
let step = 1;
|
let percent = option.percent ? option.percent : 0;
|
|
// 更新percent
|
if (option.moveType == "charge") {
|
if (percent >= 100) {
|
percent = 0;
|
}
|
|
percent += step;
|
} else if (option.moveType == "discharge") {
|
if (percent <= 0) {
|
percent = 100;
|
}
|
percent -= step;
|
} else {
|
percent = 0;
|
}
|
option.percent = percent;
|
|
// 绘制第5层
|
let l5Height = percent / 100 * l3Height;
|
let l5Point = [l4Point[0], l4Point[1] - l5Height];
|
let g5 = ctx.createLinearGradient(l5Point[0], l5Point[1], l5Point[0] + width, l5Point[1]);
|
|
if (option.moveType == "charge") {
|
g5.addColorStop(0, "#00a7ff");
|
g5.addColorStop(0.5, "#0041dd");
|
g5.addColorStop(0.75, "#0145ce");
|
g5.addColorStop(0.95, "#038afd");
|
g5.addColorStop(1, "#01247e");
|
} else if (option.moveType == "discharge") {
|
g5.addColorStop(0, "#f93122");
|
g5.addColorStop(0.25, "#fb8f87");
|
g5.addColorStop(0.5, "#f93122");
|
g5.addColorStop(0.95, "#fa1301");
|
g5.addColorStop(1, "#fa1301");
|
}
|
ctx.fillStyle = g5;
|
ctx.fillRect(l5Point[0], l5Point[1], width, l5Height);
|
|
// 设置执行的方法
|
option.method = "battery";
|
// 添加配置项
|
this.addOptions(option);
|
let fullHeight = l1Height + l2Height + l3Height + l4Height;
|
return {
|
tl: point,
|
top: [point[0] + width / 2, point[1]],
|
tr: [point[0] + width, point[1]],
|
bl: [point[0], point[1] + fullHeight],
|
bottom: [point[0] + width / 2, point[1] + fullHeight],
|
br: [point[0] + width, point[1] + fullHeight],
|
left: [point[0], point[1] + fullHeight / 2],
|
right: [point[0] + width, point[1] + fullHeight / 2],
|
width: width,
|
};
|
};
|
|
Diagram.prototype.lineBattery = function(option) {
|
let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
|
let point = option.point;
|
let size = 40;
|
let strokeStyle = option.strokeStyle?option.strokeStyle:'#FFFFFF';
|
let lineWidth = option.lineWidth ? option.lineWidth : 2;
|
|
// 线条1
|
let line1 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
[point[0], point[1]-size/2],
|
[point[0], point[1] + size/2]
|
],
|
});
|
|
// 线条2
|
let line2 = this.line({
|
strokeStyle: strokeStyle,
|
lineWidth: lineWidth,
|
hide: option.hide,
|
points: [
|
[line1[0][0]+12, point[1]-size/3],
|
[line1[0][0]+12, point[1] + size/3]
|
],
|
});
|
|
return {
|
left: point,
|
right: [line2[0][0], point[1]]
|
}
|
};
|
|
// 根据id正则删除内容
|
Diagram.prototype.del = function (pattern) {
|
// 清空options配置项
|
this.options = this.options.filter(item => {
|
if (!pattern.test(item.id)) {
|
return item;
|
}
|
});
|
|
// 清空刷新对象
|
this.flushOptions = this.flushOptions.filter(item => {
|
if (!pattern.test(item.id)) {
|
return item;
|
}
|
});
|
};
|
|
Diagram.prototype.getCenter = function () {
|
let cvs = this.flush;
|
return {
|
x: cvs.width / 2,
|
y: cvs.height / 2,
|
};
|
};
|
Diagram.prototype.getEleCenter = function () {
|
let cvs = this.flush;
|
let offsetWidth = cvs.offsetWidth;
|
let offsetHeight = cvs.offsetHeight;
|
return {
|
x: offsetWidth / 2,
|
y: offsetHeight / 2,
|
};
|
};
|
Diagram.prototype.getScale = function () {
|
let cvs = this.flush;
|
let widthScale = cvs.offsetWidth / cvs.width;
|
let heightScale = cvs.offsetHeight / cvs.height;
|
return widthScale > heightScale ? heightScale : widthScale;
|
};
|
|
Diagram.prototype.getPoint = function (point) {
|
let center = this.getCenter();
|
let eleCenter = this.getEleCenter();
|
let scale = this.getScale();
|
return {
|
x: eleCenter.x + (point[0] - center.x) * scale,
|
y: eleCenter.y + (point[1] - center.y) * scale
|
};
|
};
|
|
Diagram.prototype.getSize = function (width, height) {
|
let scale = this.getScale();
|
return {
|
width: width * scale,
|
height: height * scale
|
};
|
};
|
|
export default Diagram;
|