canvas绘制曲线图

在这里插入图片描述

/**

  • moveTo() 是Canvas 2D API 将一个新的子路径的起始点移动到(x,y)坐标的方法

  • CanvasRenderingContext2D.lineTo()是

  • Canvas 2D API 使用直线连接子路径的终点到(x,y)做标的方法(并不会真正地绘制)。

  • 使用beginPath() 绘制路径的起始点, 使用moveTo()移动画笔,

  • 使用stroke()方法真正的画线

  • 定义和用法:

  • fillText()方法在画布上绘制填色的文本。文本的默认颜色是黑色。

  • 提示:请使用 font 属性来定义字体和字号,并使用fillStyle属性以另一种颜色/渐变来渲染文本。

  • JavaScript 语法:

  • context.fillText(text,x,y,maxWidth);

  • 参数值

  • 参数 描述

  • text 规定在画布上输出的文本。

  • x 开始绘制文本的x坐标位置(相对于画布)。

  • y 开始绘制文本的y坐标位置(相对于画布)。

  • maxWidth 可选。允许的最大文本宽度,以像素计。

  • fillStyle属性来设置用于填充绘图的颜色、渐变或模式

  • strokeStyle 设置描边样式 接收所有颜色类型

  • values为一个数组,从中获取values数组中的最大值

  • var max = Math.max.apply(Math,values);

  • 从中获取values数组中的最小值

  • var min = Math.min.apply(Math,values);

  • PI就是圆周率π,PI是弧度制的π,也就是180°
    所以,Math.PI = 3.14 = 180°

  • const定义的变量不可以修改,而且必须初始化。

  • var定义的变量可以修改,如果不初始化会输出undefined,不会报错。

  • let是块级作用域,函数内部使用let定义后,对函数外部无影响。

  • @param json

  • @returns
    */
    function lenCanvasCT(json){

    var canvas_lens_ct = document.getElementById(‘canvas_lens_ct’);
    // 获取上下文;'2d’建立一个CanvasRenderingContext2D对象代表一个二维渲染上下文。
    var context = canvas_lens_ct.getContext(“2d”);

    //2、获取画布的宽度和高度
    const WIDTH = canvas_lens_ct.width;
    const HEIGHT = canvas_lens_ct.height;

    //3、定义坐标轴相对于画布的内边距
    var padding = 20; //初始化内边距
    var paddingLeft = 50; //至少大于绘制文字的宽度
    var paddingBottom = 70; //至少大于绘制文字的高度
    //4、定义绘制坐标轴的关键点的坐标值;以下这个方式是对象字面量表法,与JsonObject相类似;axis轴线的意思
    var axisY = { //y轴的起点坐标值
    x: paddingLeft,
    y: padding
    };
    var origin = { //原点坐标值(x轴与y轴交叉点)
    x: paddingLeft,
    y: HEIGHT - paddingBottom
    }
    var axisX = { //x轴的起点坐标值
    x: WIDTH - padding,
    y: HEIGHT - paddingBottom
    }

    //绘制坐标轴;axisY:y轴的起点坐标值;orgin:原点坐标值(x轴与y轴交叉点);axisX:x轴的起点坐标值
    context.beginPath();
    context.moveTo(axisY.x, axisY.y); //y轴的起点坐标值开始;Canvas 2D API 将一个新的子路径的起始点移动到(x,y)坐标的方法
    context.lineTo(origin.x, origin.y); //到原点坐标值(x轴与y轴交叉点),竖线
    context.lineTo(axisX.x, axisX.y); //到x轴的起点坐标值,横线
    context.stroke(); //真正的绘制画线

    //绘制坐标轴的箭头;y轴箭头
    context.beginPath();
    context.moveTo(axisY.x - 5, axisY.y + 10);
    context.lineTo(axisY.x, axisY.y); //y轴的起点坐标值
    context.lineTo(axisY.x + 5, axisY.y + 10);
    context.stroke();
    //x轴箭头
    context.beginPath();
    context.moveTo(axisX.x - 10, axisX.y - 5);
    context.lineTo(axisX.x, axisX.y); //x轴的起点坐标
    context.lineTo(axisX.x - 10, axisX.y + 5);
    context.stroke();

    //病例量表平均T分,顶部线
    context.beginPath();
    context.moveTo(WIDTH/3-70, axisY.y);
    context.lineTo(WIDTH/3-50, axisY.y);
    context.strokeStyle = ‘#55aa00’; //绿色
    context.stroke();
    //绘制实心圆点
    context.fillStyle = ‘#55aa00’;
    context.beginPath();
    context.arc(WIDTH/3-60,axisY.y,4,0,2*Math.PI); //创建弧/曲线(用于创建圆形或部分圆);半径为4的实心圆
    context.fill();

    //心理症状T分;顶部线
    context.beginPath();
    context.moveTo(WIDTH/2-50, axisY.y);
    context.lineTo(WIDTH/2-30, axisY.y);
    context.strokeStyle = ‘#aa0000’; //红色
    context.stroke();
    //绘制实心圆点
    context.fillStyle = ‘#aa0000’;
    context.beginPath();
    context.arc(WIDTH/2-40,axisY.y,4,0,2*Math.PI); //创建弧/曲线(用于创建圆形或部分圆);半径为4的实心圆
    context.fill();

    //装好装坏因子T分;顶部线
    context.beginPath();
    context.moveTo(WIDTH-WIDTH/3-30, axisY.y);
    context.lineTo(WIDTH-WIDTH/3-10, axisY.y);
    context.strokeStyle = ‘#0055aa’; //蓝色
    context.stroke();
    //绘制实心圆点
    context.fillStyle = ‘#0055aa’;
    context.beginPath();
    context.arc(WIDTH-WIDTH/3-20,axisY.y,4,0,2*Math.PI); //创建弧/曲线(用于创建圆形或部分圆);半径为4的实心圆
    context.fill();

    //绘制文字;#55aa00绿色;红色#aa0000;#0055aa蓝色;黑色#030303;
    context.fillStyle = ‘#030303’;
    context.strokeStyle = ‘#030303’;
    context.font = ‘13px 宋体’;
    //(参数:要写的字,x坐标,y坐标);context.fillText(‘要写的文字’, 100, 100);
    context.fillText(‘T分’, axisY.x-5, axisY.y-10);
    context.fillText(‘测查日期’, axisX.x-35, HEIGHT - paddingBottom + axisY.y);
    //病例量表平均T分;绿色
    context.fillStyle = ‘#55aa00’;
    context.strokeStyle = ‘#55aa00’;
    context.font = ‘13px 宋体’;
    context.fillText(‘病例量表平均T分’, WIDTH/3-50, axisY.y);
    //心理症状T分;红色
    context.fillStyle = ‘#aa0000’;
    context.strokeStyle = ‘#aa0000’;
    context.font = ‘13px 宋体’;
    context.fillText(‘心理症状T分’, WIDTH/2-30, axisY.y);
    //装好装坏因子T分;蓝色
    context.fillStyle = ‘#0055aa’;
    context.strokeStyle = ‘#0055aa’;
    context.font = ‘13px 宋体’;
    context.fillText(‘装好装坏因子T分’, WIDTH-WIDTH/3-10, axisY.y);
    //恢复原来颜色;黑色
    context.fillStyle = ‘#030303’;
    context.strokeStyle = ‘#030303’;

    //得到数组对象;resultIds即rids数组的长度是多少就加载多少个;即jasMd == json.length-2
    var jasMd = json[json.length-1].jasMd;
    var iave = []; //病例量表平均T分 集合数组
    var mentT = []; //心理症状(总)T分 集合数组
    var gdbd = []; //装好-装坏因子T分 集合数组
    var xsurd = []; //测查日期 集合数组
    //json得到的第1个json[0]对象[object Object]是常数,最后一个json[json.length-1]对象[object Object]对象是MD.DAT文件中所需要的内容数据
    for (var i = 1; i < json.length-1; i++) {
    //console.log(‘json’+i+’:’+json[i]); //得到对应对象
    var japct = json[i].japct;
    var pct1 = japct[0].pctrp; //报告1
    var pct2 = japct[1].pctrp; //报告2
    var pct4 = japct[3].pctrp; //报告4
    mentT.push(pct4[0].jopct); //心理症状(总)T分
    gdbd.push(pct2[91].jopct); //装好装坏因子T分
    xsurd.push(pct1[15].jopct); //测查日期
    var jaMd = jasMd[i-1].jaMd;
    iave.push(jaMd[3].joMd); //病例量表平均T分
    }
    console.log(‘病例量表平均T分iave:’+iave+’–心理症状(总)T分mentT:’+mentT+’–装好-装坏因子T分gdbd:’+gdbd); //可得到具体数组数据

    //存储x轴的值
    var pointsX = [];
    //7、绘制坐标轴的刻度(x轴的测查日期和y轴的总分);x轴的测查日期
    var surveyDay = {
    x: paddingLeft,
    y: HEIGHT - paddingBottom + 5
    }

    //x轴测查日期
    for (var i = 0; i < xsurd.length; i++) {
    context.font = ‘16px’;
    context.textBaseline = ‘top’;
    if(xsurd.length < 9){
    //测查日期数小于9时
    context.fillText(xsurd[i] + ‘日’, surveyDay.x, surveyDay.y);
    }else{
    //测查日期数大于9时,字体竖直排列
    context.fillTextVertical(xsurd[i] + ‘日’, surveyDay.x, surveyDay.y);
    }
    pointsX.push(surveyDay.x);
    surveyDay.x += (axisX.x - origin.x) / xsurd.length;
    }

    //var scoY = (origin.y - axisY.y) / (max / hg + 1); //hg10:y轴划分值;100/10+1;hgap10:最高值间隔
    var scoY = (origin.y-axisY.y)/11; //即单元格高
    var score = {
    x: axisY.x - 5,
    y: axisY.y + scoY,
    fen: 100
    }
    context.textAlign = ‘right’;
    //y轴间隔分数
    for (var i = 0; i <= 10; i++) {
    context.font = ‘16px 宋体’;
    context.fillText(score.fen + ‘分’,score.x, score.y);
    score.y += scoY;
    score.fen -= 10;
    }
    //x轴刻度
    for (var i = 1; i <= 20; i++) {
    context.beginPath();
    context.moveTo(axisY.x, axisY.y+(i+1)scoY/2);
    context.lineTo(axisY.x-5, axisY.y+(i+1)scoY/2);
    context.stroke(); //真正的绘制画线
    }
    //y轴刻度
    for (var i = 0; i < xsurd.length; i++) {
    console.log(‘surveyDay.x:’+surveyDay.x);
    context.moveTo(pointsX[i], axisX.y);
    context.lineTo(pointsX[i], axisX.y+5);
    context.stroke(); //真正的绘制画线
    }
    /

    • var iave = []; //病例量表平均T分 集合数组
      var mentT = []; //心理症状(总)T分 集合数组
      var gdbd = []; //装好-装坏因子T分 集合数组
      */
      //绘制折线;var iave = []; //病例量表平均T分 集合数组
      context.beginPath();
      for (let i = 0; i < iave.length; i++) {
      //x轴的坐标
      let pointX = pointsX[i];
      //y轴的坐标
      let pointY = origin.y - (origin.y - (axisY.y + scoY)) * iave[i] / 100;
      context.fillStyle = ‘#55aa00’;
      if(i === 0){
      // context.textBaseline = ‘’;
      context.textAlign = ‘right’
      context.moveTo(pointX, pointY);
      context.fillText(iave[i]+‘分’, pointX+35, pointY);
      }else{
      context.textBaseline = ‘bottom’;
      context.textAlign = ‘center’;
      context.lineTo(pointX, pointY);
      context.setLineDash([10,10]); //设置虚线
      context.fillText(iave[i]+‘分’, pointX, pointY);
      }
      context.font = ‘16px’;
      }
      context.strokeStyle = ‘#55aa00’; //#55aa00绿色
      context.stroke();

    //绘制小圆点
    for (let i = 0; i < iave.length; i++) {
    //x轴的坐标
    let pointX = pointsX[i];
    //y轴的坐标
    let pointY = origin.y - (origin.y - (axisY.y +scoY)) * iave[i] / 100;
    context.fillStyle = ‘#55aa00’; //#55aa00绿色;红色#aa0000
    context.beginPath();
    context.arc(pointX,pointY,4,0,2*Math.PI); //创建弧/曲线(用于创建圆形或部分圆);半径为4的实心圆
    context.fill();
    }

    //折线var mentT = []; //心理症状(总)T分 集合数组
    context.beginPath();
    for (let i = 0; i < mentT.length; i++) {
    //x轴的坐标
    let pointX = pointsX[i];
    //y轴的坐标
    let pointY = origin.y - (origin.y - (axisY.y + scoY)) * mentT[i] / 100;
    context.fillStyle = ‘#aa0000’;
    if(i === 0){
    // context.textBaseline = ‘’;
    context.textAlign = ‘right’
    context.moveTo(pointX, pointY);
    context.fillText(mentT[i]+‘分’, pointX+35, pointY);
    }else{
    context.textBaseline = ‘bottom’;
    context.textAlign = ‘center’;
    context.lineTo(pointX, pointY);
    //context.setLineDash([10,10]); //设置虚线
    context.fillText(mentT[i]+‘分’, pointX, pointY);
    }
    context.font = ‘16px’;
    }
    context.strokeStyle = ‘#aa0000’; //#55aa00绿色
    context.stroke();

    //绘制小圆点
    for (let i = 0; i < mentT.length; i++) {
    //x轴的坐标
    let pointX = pointsX[i];
    //y轴的坐标
    let pointY = origin.y - (origin.y - (axisY.y +scoY)) * mentT[i] / 100;
    context.fillStyle = ‘#aa0000’; //#55aa00绿色;红色#aa0000
    context.beginPath();
    context.arc(pointX,pointY,4,0,2*Math.PI); //创建弧/曲线(用于创建圆形或部分圆);半径为4的实心圆
    context.fill();
    }

    //折线:var gdbd = []; //装好-装坏因子T分 集合数组
    context.beginPath();
    for (let i = 0; i < gdbd.length; i++) {
    //x轴的坐标
    let pointX = pointsX[i];
    //y轴的坐标
    let pointY = origin.y - (origin.y - (axisY.y + scoY)) * gdbd[i] / 100;
    context.fillStyle = ‘#0055aa’;
    if(i === 0){
    // context.textBaseline = ‘’;
    context.textAlign = ‘right’
    context.moveTo(pointX, pointY);
    context.fillText(gdbd[i]+‘分’, pointX+35, pointY);
    }else{
    context.textBaseline = ‘bottom’;
    context.textAlign = ‘center’;
    context.lineTo(pointX, pointY);
    context.setLineDash([1,0]); //恢复实线
    context.fillText(gdbd[i]+‘分’, pointX, pointY);
    }
    context.font = ‘16px’;
    }
    context.strokeStyle = ‘#0055aa’; //#0055aa蓝色;#55aa00绿色
    context.stroke();

    //绘制小圆点
    for (let i = 0; i < gdbd.length; i++) {
    //x轴的坐标
    let pointX = pointsX[i];
    //y轴的坐标
    let pointY = origin.y - (origin.y - (axisY.y +scoY)) * gdbd[i] / 100;
    context.fillStyle = ‘#0055aa’; //#0055aa蓝色;#55aa00绿色;红色#aa0000
    context.beginPath();
    context.arc(pointX,pointY,4,0,2*Math.PI); //创建弧/曲线(用于创建圆形或部分圆);半径为4的实心圆
    context.fill();
    }

    //打印显示,canvas本身不显示,用img替换
    canvas_lens_ct.style.display = ‘none’;
    var img_len_ct = document.getElementById(‘img_len_ct’);
    img_len_ct.src = canvas_lens_ct.toDataURL();
    img_len_ct.style.display = ‘block’;
    }

/**

  • @author zhangxinxu(.com)

  • @licence MIT

  • @description http://www.zhangxinxu.com/wordpress/?p=7362

  • canvas日期竖直排列;js混合计算逐字排列

  • values为一个数组,从中获取values数组中的最大值

    • var max = Math.max.apply(Math,values);
    • 从中获取values数组中的最小值
    • var min = Math.min.apply(Math,values);
      */
      CanvasRenderingContext2D.prototype.fillTextVertical = function (text, x, y) {
      var context = this;
      var canvas = context.canvas;

    var arrText = text.split(’’);
    var arrWidth = arrText.map(function (letter){
    return context.measureText(letter).width;
    });

    var align = context.textAlign;
    var baseline = context.textBaseline;

    if(align == ‘left’){
    x = x + Math.max.apply(null, arrWidth) / 2;
    }else if(align == ‘right’){
    x = x - Math.max.apply(null, arrWidth) / 2;
    }
    if(baseline == ‘bottom’ || baseline == ‘alphabetic’ || baseline == ‘ideographic’){
    y = y -arrWidth[0] / 2;
    }else if (baseline == ‘top’ || baseline == ‘hanging’){
    y = y + arrWidth[0] / 2;
    }

    context.textAlign = ‘center’;
    context.textBaseline = ‘middle’;

    //开始逐字绘制
    arrText.forEach(function (letter, index){
    //确定下一个字符的纵坐标位置
    var letterWidth = arrWidth[index];

      // 旋转90度
      context.translate(x, y);
      context.rotate(90 * Math.PI /180);
      context.translate(-x, -y);
      context.fillText(letter, x, y);
      
      // 旋转坐标系还原成初始态
      context.setTransform(1, 0, 0, 1, 0, 0);
      // 确定下一个字符的纵坐标位置
      var letterWidth = arrWidth[index];
      y = y + letterWidth;
    

    });
    // 水平垂直对齐方式还原
    context.textAlign = align;
    context.textBaseline = baseline;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值