小程序纵向(竖向)三项(3项)柱状条形图canvas

公司需求我们画的条形图是竖向那种,我画的成果

代码参考https://blog.csdn.net/sinat_27180253/article/details/80932037的文章,基本上都一样的,只不过我把他的横向改成纵向,单项属性改成了三项属性,附上代码

WXML:

<!-- 折线图 -->
<view class="canvas-view">
    <canvas class="canvas" canvas-id="canvasId"></canvas>
</view>

WXSS:

/* 折线图 */
.canvas-view{
  height: 100%;
  background: #fff;
  display: flex;
  align-items: center;
  margin-top: 140rpx;
}
.canvas {
  width: 100%;
  height: 900rpx;
}

JS:

const app = getApp()
Page({
  data: {
    //条形框值
    list: [
      { "yellow": 0.5, "blue": 0.3, "red": 4.2 },
      { "yellow": 1.3, "blue": 4.7, "red": 2.1 },
      { "yellow": 3.5, "blue": 4.1, "red": 2.9 },
      { "yellow": 3.7, "blue": 2.4, "red": 0.2 },
      { "yellow": 0.2, "blue": 0.7, "red": 3.3 },
      { "yellow": 1.9, "blue": 0.1, "red": 4.1 },
      { "yellow": 4.3, "blue": 3.4, "red": 4.8 },
      { "yellow": 4.6, "blue": 5, "red": 1.6 },
    ],
    yMin: 32,  //竖
    xMin: 100, //横
    yMax: 550,  //竖
    xMax: 460,  //横
    s28: 28,  //字号大小
    s18: 18,  //字号大小
    //Y轴分成的大分段
    heightLineNum: 9,
    //X轴分成的大分段
    widthLineNum: 5,
    //Y轴一个分段的值
    yOneDuan: ["身高", "体重", "胸围", "协调性", "平衡力", "灵敏性", "柔韧性", "下肢力量"],
    color1: '#ffd338',  //黄色
    color2: '#4790fc',  //蓝色
    color3: '#f95415',  //绿色
  },

  onLoad: function (options) {
    //画图
    this.initChart()
  },

  // 初始化条形图
  initChart: function () {
    const ctx = wx.createCanvasContext('canvasId')

    ctx.beginPath()
    ctx.setStrokeStyle('#999999')
    ctx.setFillStyle('#AAAAAA')
    ctx.setLineWidth(1)

    //左上角
    const leftBottomX = this.getEleWidth(this.data.xMin)
    const leftBottomY = this.getEleWidth(this.data.yMin)
    //右上角
    const leftTopX = this.getEleWidth(this.data.xMax)
    const leftTopY = this.getEleWidth(this.data.yMin)
    //左下角
    const rightBottomX = this.getEleWidth(this.data.xMin)
    const rightBottomY = this.getEleWidth(this.data.yMax)
    //右下角
    const bottomX = this.getEleWidth(this.data.xMax)
    const bottomY = this.getEleWidth(this.data.yMax)

    const yHeight = this.getEleWidth(this.data.yMax - this.data.yMin)
    const xWidth = this.getEleWidth(this.data.xMax - this.data.xMin)

    //从Y轴坐标开始画坐标系
    //Y轴坐标到原点坐标画出Y轴线
    //画完Y轴线,再从原点坐标到X轴坐标画出X轴线
    ctx.moveTo(leftTopX, leftTopY)
    ctx.lineTo(leftBottomX, leftBottomY)
    ctx.lineTo(rightBottomX, rightBottomY)
    ctx.lineTo(bottomX, bottomY)
    //设置字体大小
    ctx.setFontSize(this.getEleWidth(this.data.s18))
    //设置字的位置
    ctx.fillText("条形图", this.getEleWidth(340), this.getEleWidth(20))

    //划分Y轴
    this.drawYScale(ctx);
    //划分X轴
    this.drawXScale(ctx);
    //画条形图
    this.drawRectScale(ctx);

    ctx.stroke()
    ctx.draw(true)
  },

  //划分Y轴
  drawYScale: function (ctx) {
    var that = this;
    //Y轴坐标刻度横坐标起点
    var scaleStartX = this.getEleWidth(this.data.xMin)
    //长的刻度
    var scaleEndX = this.getEleWidth(this.data.xMin + 5)
    //Y轴刻度总高度
    const yHeight = this.getEleWidth(this.data.yMax)
    //一个大分段的长度
    var oneScaleX = yHeight / this.data.heightLineNum
    //大分段数字字体大小
    ctx.setFontSize(this.getEleWidth(this.data.s18))
    //大分段数字位置横坐标
    var textX = this.getEleWidth(this.data.xMin - 82)
    //大分段,长刻度:50-300
    for (var i = 1; i < this.data.heightLineNum; i++) {
      var scaleEndY = oneScaleX * i + 15
      //画长刻度线条
      ctx.moveTo(scaleStartX, scaleEndY)
      ctx.lineTo(scaleEndX, scaleEndY)
      ctx.fillText(this.data.yOneDuan[i-1], textX, scaleEndY + this.getEleWidth(10))
      var littleScaleStartY = yHeight - oneScaleX * (i - 1)
    }
  },

  //划分X轴
  drawXScale: function (ctx) {
    var that = this;
    //X轴刻度值Y坐标
    var scaleStartY = this.getEleWidth(that.data.yMax)
    var scaleEndY = this.getEleWidth(that.data.yMin);
    //X轴总长度=X轴横坐标-向右偏移长度
    const xWidth = this.getEleWidth(that.data.xMax - that.data.xMin)
    //X轴起始点
    const xMaginLeft = this.getEleWidth(that.data.xMin)
    //一个分段的宽度
    const oneScaleX = xWidth / (that.data.widthLineNum)
    for (var i = 0; i < that.data.widthLineNum + 1; i++) {
      var toEndX = xMaginLeft + oneScaleX * i;
      ctx.moveTo(toEndX, scaleStartY);
      ctx.lineTo(toEndX, scaleEndY)
      ctx.fillText(i, toEndX + this.getEleWidth(0), scaleStartY + this.getEleWidth(24))
    }
  },

  //画条形方框
  drawRectScale: function (ctx) {
    var that = this;
    //Y轴坐标刻度横坐标起点
    var scaleStartX = this.getEleWidth(this.data.xMin)
    //X轴总长度=X轴横坐标-向右偏移长度
    const xWidth = this.getEleWidth(that.data.xMax - that.data.xMin)
    //Y轴刻度总高度
    const yHeight = this.getEleWidth(that.data.yMax)
    //X轴起始点
    const yMaginLeft = this.getEleWidth(that.data.yMin)
    //一个分段的宽度
    const oneScaleX = xWidth / (that.data.widthLineNum)
    //一个大分段的长度
    var oneScaleY = yHeight / this.data.heightLineNum

    for (var i = 0; i < that.data.list.length; i++) {
      var scaleEndY = oneScaleY * (i + 1) + 15
      const currentRectYellow = that.data.list[i].yellow;
      const currentRectBlue = that.data.list[i].blue;
      const currentRectRed = that.data.list[i].red;
      //Y轴角度条矩形的宽度
      const rectWidth = oneScaleY / 5;
      //条矩形的长度
      const yellowHeight = currentRectYellow * oneScaleX;
      const blueHeight = currentRectBlue * oneScaleX;
      const redHeight = currentRectRed * oneScaleX;
      //矩形左上角的x坐标和y坐标
      const x = scaleStartX;
      const y = scaleEndY;
      //黄色填充
      ctx.setFillStyle(that.data.color1)
      //画框
      ctx.fillRect(x, y - rectWidth / 2 - rectWidth, yellowHeight,rectWidth);
      ctx.save();
      //蓝色填充
      ctx.setFillStyle(that.data.color2)
      //画框
      ctx.fillRect(x, y - rectWidth / 2, blueHeight, rectWidth);
      ctx.save();
      //红色填充
      ctx.setFillStyle(that.data.color3)
      //画框
      ctx.fillRect(x, y + rectWidth / 2, redHeight, rectWidth);
    }
  },

  //获取屏幕自适应宽度
  getEleWidth: function (w) {
    var real = 0;
    try {
      var res = wx.getSystemInfoSync().windowWidth;
      //以宽度480px设计做宽度的自适应
      var scale = (480 / 2) / (w / 2);
      real = Math.floor(res / scale);
      return real;
    } catch (e) {
      return false;
    }
  }
})

其实画图不难,只要算好坐标点很简单,就是算坐标点太墨迹

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值