在微信小程序里面用canvas画区间图

在微信小程序里面用canvas画区间图

需求:需要展示日、周、月、年的区间图


解决方案

我发现用chart.js或者echarts都不能满足需求,所以决定用d3试一下,结果发现小程序不支持d3,所以决定用原生画一个

以下是效果图
在这里插入图片描述
wxml

<view style="height:500px">
  <canvas id="firstCanvas" type="2d"></canvas>
</view>

wxss

#firstCanvas{
  width: 300px;
  height: 185px;
  border: 1px solid #ddd;
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}

js

import {recordPaint} from '../../utils/canvas'
Page({
  data: {
    path: ''
  },
  onLoad(option) {
    this.setcanvas('#firstCanvas')
  },
  setcanvas(text){
    const query = wx.createSelectorQuery()
    query.select(text)
    .fields({ node: true, size: true })
    .exec((res) => {
      console.log(res)
      const canvas = res[0].node
      const datas = [[0,0],[97,81],[0,0],[96,85],[0,0],[0,0],[0,0],[0,0],[95,94],[0,0],[97,96],[0,0],[0,0],[0,0],[96,94],[96,95],[94,93],[0,0],[0,0],[0,0],[0,0],[71,70],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]]
      const color = ['rgba(90,200,250,0.5)','#5AC8FA']
      const xdata = [1,2,3,4,5,6,7,8,9,10,11,12,13]
      const stepSize = 10
      const max = 100
      const min = 70
      const datas1 = []
      recordPaint(canvas,datas,datas1,color,xdata,stepSize,max,min)
    })
  }
})

canvas.js

export function recordPaint(elem, datas,datas1,color,xdata,stepSize,max,min) {
  //1.创建画布对象
  var context = elem.getContext('2d');
  // 设置canvas的真实宽高
  elem.width = 2 * elem._width; // 想当于 2 * 375 = 750 
  elem.height = 2 * elem._height;
  //2、获取画布的宽度和高度
  const WIDTH = elem.width;
  const HEIGHT = elem.height;
  //定义坐标轴相对于画布的内边距
  var padding = 10;//初始化内边距
  var paddingLeft = 40;// 至少大于绘制文字的宽度
  var paddingBottom = 30;// 至少大于绘制文字的高度
  // 4、定义绘制坐标轴的关键点的坐标值
  var axisY = { // y轴的起点坐标值
    x: paddingLeft,
    y: paddingBottom
  };
  var origin = { // 原点坐标值(x轴与y轴交叉点)
    x: paddingLeft,
    y: HEIGHT - paddingBottom
  };
  var axisX = { // X轴的起点坐标值
    x: WIDTH - padding-5,
    y: HEIGHT - paddingBottom
  };
  context.strokeStyle = '#BDC2CE'
  context.fillStyle = '#BDC2CE'
  //存储x轴的值
  var pointsX = [];
  //绘制坐标轴的刻度
  //x轴的月份
  var month = {
    x: paddingLeft,
    y: HEIGHT - paddingBottom + 5
  };
  let z = (axisX.x - origin.x) / xdata.length/2 // 格子的中间值
  for (var i = 0; i < xdata.length; i++) {
    context.textBaseline = "top";
    context.font = "20pt Calibri"
    context.fillText(xdata[i], month.x+z, month.y); // 设置x轴值
    pointsX.push(month.x + z);
    month.x += (axisX.x - origin.x) / xdata.length;
  }
  //绘制y轴值
  var moneyY = (origin.y - axisY.y) / ((max-min) / stepSize)
  var money = {
    x: axisX.x + 20,
    y: axisY.y + moneyY-4,
    jin: max
  }
  //遍历y轴值
  for (var i = 0; i <= (max-min) / stepSize; i++) {
    context.fillText(money.jin,0, money.y-moneyY); // 设置y轴值
    money.y += moneyY;
    money.jin -= stepSize;
  }
  //绘制水平方向的网格线
  let n = (max-min) / stepSize
  for(let y=origin.y;y>moneyY;y-=moneyY){
    //开启路径
    if(n > 1){
      drawDashLine(context,origin.x + 5,y-moneyY, axisX.x,y-moneyY)
    }else{
      context.beginPath()
      context.fillStyle = color[0]
      context.moveTo(origin.x,y-moneyY)
      context.lineTo(axisX.x,y-moneyY)
      context.stroke()
    }
    // context.font = "20pt Calibri"
    // context.fillText(money.jin,0, money.y-moneyY); // 设置y轴值
    // money.y += moneyY;
    // money.jin -= stepSize;
    n--
  }
  //绘制垂直方向的网格线
  let space1 = (axisX.x - origin.x) / xdata.length
  for(let x=origin.x;x<axisX.x+space1;x+=space1){
    //开启路径
    context.beginPath()
    context.lineWidth = 1
    if(max == 350){
      context.moveTo(x,axisY.y-10)
      context.lineTo(x,origin.y)
    }else{
      context.moveTo(x,axisY.y)
      context.lineTo(x,origin.y)
    }
    context.stroke()
  }
   //绘制坐标轴
   context.beginPath()
   context.moveTo(axisY.x, axisY.y)
   context.lineTo(origin.x, origin.y)
   context.lineTo(axisX.x, axisX.y)
   context.stroke();
  //绘制折线
  var width=12;//设定每个柱子的宽度
  for (let i = 0; i < datas.length; i++) {
    context.beginPath();
    context.fillStyle = color[0]
    //x轴的坐标
    let pointX = pointsX[i];
    if (datas[i][0]!=0 && datas[i][1]!=0){
      //y轴的坐标
      let pointY = origin.y - (origin.y - (axisY.y)) * datas[i][0] / max;
      let pointY1 = origin.y - (origin.y - (axisY.y)) * datas[i][1] / max;
      if (i === 0) {
        // context.textBaseline = "";
        context.textAlign = "left"
        context.moveTo(pointX, pointY);
      } else {
        context.textBaseline = "bottom";
        context.textAlign = "center"
        context.lineTo(pointX, pointY);
      }
      var height = pointY-pointY1
      //绘制
      context.fillRect(pointX-6,pointY, width, -height);//绘制一个柱状
    }
  }
  for (let i = 0; i < datas1.length; i++) {
    context.beginPath();
    context.fillStyle = color[2]
    //x轴的坐标
    let pointX = pointsX[i];
    if (datas1[i][0]!=0 && datas1[i][1]!=0){
      //y轴的坐标
      let pointY = origin.y - (origin.y - (axisY.y)) * datas1[i][0] / max;
      let pointY1 = origin.y - (origin.y - (axisY.y)) * datas1[i][1] / max;
      if (i === 0) {
        // context.textBaseline = "";
        context.textAlign = "left"
        context.moveTo(pointX, pointY);
      } else {
        context.textBaseline = "bottom";
        context.textAlign = "center"
        context.lineTo(pointX, pointY);
      }
      var height = pointY-pointY1
      //绘制
      context.fillRect(pointX-6,pointY, width, -height);//绘制一个柱状
    }
  }
  context.stroke();

  //绘制小圆点
  for(let i = 0; i < datas.length; i++){
      //x轴的坐标
      let pointX = pointsX[i];
      //y轴的坐标
      if(datas[i][0]!=0 && datas[i][1]!=0){
        let pointY = origin.y - (origin.y - (axisY.y)) * datas[i][0] / max;
        let pointY1 = origin.y - (origin.y - (axisY.y)) * datas[i][1] / max;
        context.fillStyle = color[1]
        context.beginPath();
        context.arc(pointX,pointY1,6,0,2*Math.PI);
        context.arc(pointX,pointY,6,0,2*Math.PI);
        context.fill();
      }
  }
  for(let i = 0; i < datas1.length; i++){
    //x轴的坐标
    let pointX = pointsX[i];
    //y轴的坐标
    if(datas1[i][0]!=0 && datas1[i][1]!=0){
      let pointY = origin.y - (origin.y - (axisY.y)) * datas1[i][0] / max;
      let pointY1 = origin.y - (origin.y - (axisY.y)) * datas1[i][1] / max;
      context.fillStyle = color[3]
      context.beginPath();
      context.arc(pointX,pointY1,6,0,2*Math.PI);
      context.arc(pointX,pointY,6,0,2*Math.PI);
      context.fill();
    }
}
}
function drawDashLine(context, x1, y1, x2, y2, dashLength) { //绘制虚线
  dashLength = dashLength === undefined ? 5 : dashLength
   var deltaX = x2 - x1;
   var deltaY = y2 - y1;
   var numDashes = Math.floor(
     Math.sqrt(deltaX * deltaX + deltaY * deltaY) / dashLength
   )
   for(var i = 0; i < numDashes; i++) {
     context[ i % 2 === 0 ? 'moveTo' : 'lineTo']
     (x1 + (deltaX / numDashes) * i, y1 + (deltaY / numDashes) * i);
   }
   context.fillStyle = "#BDC2CE";
   context.stroke();
}

还有一个用d3画的区间图,有需要的去我博客取http://t.csdn.cn/0m7mJ


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值