zk-draw
Version:
canvas绘制AI数据的一个工具类
195 lines (172 loc) • 6.38 kB
JavaScript
/*
* @Author: wangfpp
* @Date: 2020-05-04 11:33:08
* @Last Modified by: wangfpp
* @Last Modified time: 2020-07-06 18:00:17
*/
import { drawLine } from "../../draw_line/draw_line";
import { getNodeById } from "../../../comm/comm";
/**
*
* @description 绘制RTCH图
* @param {Object} parentNode 绘制后的canvas要插入的节点
* @param {Number} canvasWidth canvas的大小
* @param {String} lineColor 网格线的颜色
* @param {String} arrowLineColor 箭头线的颜色
* @param {Number} radius 圆点大小
* @param {Object} axisStyle x轴线配置
* @param {Object} yxisStyle y轴线配置
* @param {Object} descTextStyle 描述文字配置
* @param {Array} rtchArr 待绘制的数据以及配置 {rt, ch, color}
*/
const drawRtCh = (parentNode, canvasWidth = 300, lineColor, arrowLineColor, radius, axisStyle, yxisStyle, descTextStyle, rtchArr) => {
lineColor = lineColor || '#000';
canvasWidth = canvasWidth || 300;
arrowLineColor = arrowLineColor || '#2dabff';
radius = radius || 6;
descTextStyle = descTextStyle || {teacher: {color: '#f00'}, speech: {color: '#fff'}, mix: {color: '#ff0'}, practise: {color: '#00f'}};
const defaultColor = ['#5B8FF9','#6DC8EC','#CDDDFD','#F8D0CB','#D3EEF9','#5AD8A6','#CDF3E4','#5D7092','#CED4DE','#F6BD16','#FCEBB9','#E86452','#945FB9','#DECFEA','#FF9845','#FFE0C7','#1E9493','#BBDEDE','#FF99C3','#FFE0ED'];
if (typeof window === 'undefined') {
return;
}
// 创建canvas画布
let canvas = document.createElement('canvas');
canvas.setAttribute('id', 'zkqd_rtch');
canvas.width = canvasWidth;
canvas.height = canvasWidth;
let padding = 25;
let ctx = canvas.getContext('2d');
// 绘制网格
canvasWrap(ctx, canvasWidth, lineColor, padding);
// 绘制坐标
ctx.beginPath();
let {color: xcolor, font: xfont} = axisStyle || {color: '#000', font: "14px Airal", lable: {color: '#fff'}};
ctx.fillStyle = xcolor
ctx.font = xfont;
ctx.fillText('RT', canvasWidth - 18, canvasWidth - 15);
ctx.closePath();
ctx.beginPath();
let {color: ycolor, font: yfont} = yxisStyle || {color: '#000', font: "14px Airal", lable: {color: '#fff'}};
ctx.fillStyle = ycolor
ctx.font = yfont;
ctx.fillText('CH', 5, padding - 5)
ctx.closePath();
// 绘制坐标刻度
let lineGap = (canvasWidth - padding * 2) / 10;
for(var i = 0; i <= 10; i++) {
let {lable: xlabel} = axisStyle;
xlabel = xlabel || {color: '#fff', font: "14px Airal"};
let {lable: ylabel} = yxisStyle;
ylabel = ylabel || {color: '#fff', font: "14px Airal"};
let fontWidth = ctx.measureText(i/10).width;
let startx = lineGap * i + padding - (fontWidth/2);
if (i>0) {
// x轴
let { font: xfont, color: xcolo} = xlabel;
ctx.beginPath();
ctx.fillStyle = xcolo
ctx.font = xfont;
ctx.fillText(i/10, startx, canvasWidth - padding/4);
ctx.closePath();
// y轴
let { color: ycolo} = ylabel;
ctx.beginPath();
ctx.fillStyle = ycolo
ctx.font = '14px Arial';
ctx.fillText(i/10, padding/10, canvasWidth - lineGap * i - (fontWidth/2));
ctx.closePath();
} else {
ctx.beginPath();
let { color: xcolo} = xlabel;
ctx.beginPath();
ctx.fillStyle = xcolo
ctx.font = '14px Arial';
ctx.fillText(i/10, padding/2, canvasWidth - padding / 2);
ctx.fill();
ctx.closePath();
}
}
//绘制RTCH三角形
ctx.beginPath();
ctx.strokeStyle = arrowLineColor;
ctx.lineWidth = 2.5;
// 三角形
ctx.moveTo( padding, canvasWidth - padding);
ctx.lineTo(canvasWidth/2, padding);
ctx.lineTo(canvasWidth - padding, canvasWidth - padding);
ctx.lineTo(padding, canvasWidth - padding);
// 中间的横线
ctx.moveTo(padding + lineGap * 2, padding + lineGap * 6);
ctx.lineTo(lineGap * 8 + padding, padding + lineGap * 6);
// 两条竖线
ctx.moveTo(padding + lineGap * 3, padding + lineGap * 4);
ctx.lineTo(padding + lineGap * 3, canvasWidth - padding);
ctx.moveTo(padding + lineGap * 7, padding + lineGap * 4);
ctx.lineTo(padding + lineGap * 7, canvasWidth - padding);
ctx.stroke();
ctx.closePath()
let { teacher, speech, practise, mix } = descTextStyle;
// 绘制文本
ctx.beginPath();
ctx.font = "14px Arial";
ctx.fillStyle = speech.color;
let fontWidth_speak = ctx.measureText('对话型').width;
let sx = (canvasWidth - fontWidth_speak)/2;
ctx.fillText('对话型', sx, lineGap * 5);
ctx.closePath();
ctx.beginPath();
ctx.font = "14px Arial";
ctx.fillStyle = mix.color;
let fontWidth_mix = ctx.measureText('混合型').width;
let mx = (canvasWidth - fontWidth_mix)/2
ctx.fillText('混合型', mx, lineGap * 9);
ctx.closePath()
ctx.beginPath();
ctx.font = "14px Arial";
ctx.fillStyle = practise.color;
ctx.fillText('练习型', lineGap + padding, lineGap * 10);
ctx.closePath();
ctx.beginPath();
ctx.font = "14px Arial";
ctx.fillStyle = teacher.color;
let fontWidth_teach = ctx.measureText('讲授型').width;
ctx.fillText('讲授型', lineGap * 7 + fontWidth_teach / 3 + padding, lineGap * 10);
ctx.closePath();
rtchArr.forEach((item, index) => {
let { rt, ch, color} = item;
color = color ? color : defaultColor[index];
ctx.beginPath();
ctx.fillStyle = color;
let startx = Number(rt) * lineGap * 10 + padding,
starty = (1 - Number(ch)) * lineGap * 10 + padding;
ctx.arc(startx, starty, radius,0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
})
let trueNode = getNodeById(parentNode);
let canvasNode = trueNode.querySelector('#zkqd_rtch');
if (canvasNode) {
trueNode.removeChild(canvasNode);
}
trueNode.appendChild(canvas);
}
/**
* @description 绘制canvas网格图的主体
* @param {Object} ctx canvas 2d
* @param {Number} canvasWidth canvas的大小
* @param {Number} padding 预留出的宽度
*/
const canvasWrap = (ctx, canvasWidth,lineColor, padding) => {
let maxValue = canvasWidth - padding,
minvalue = padding;
drawLine(ctx, [minvalue, minvalue], [minvalue, maxValue], {lineWidth: 1, strokeStyle: lineColor});
drawLine(ctx, [minvalue, maxValue], [maxValue, maxValue]);
drawLine(ctx, [maxValue, maxValue], [maxValue, minvalue]);
drawLine(ctx, [maxValue, minvalue], [minvalue, minvalue]);
let lineGap = (canvasWidth - padding * 2) / 10;
for(var i = 1; i < 10; i++) {
drawLine(ctx, [i * lineGap + padding, minvalue], [i * lineGap + padding, maxValue]);
drawLine(ctx, [minvalue, i * lineGap + minvalue], [maxValue, i * lineGap + minvalue]);
}
}
export { drawRtCh };