UNPKG

zk-draw

Version:

canvas绘制AI数据的一个工具类

195 lines (172 loc) 6.38 kB
/* * @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 };