Canvas series 06 – histogram project 4

Time:2020-10-5

As I said in the last article, it’s very easy to draw a picture when the data is ready. If you’re worried about not answering back, I’ll give you a simple example,

You practice first.

This is very simple. You don’t have to use object-oriented or anything. You just roll it out in the most crude way.

Then, if you look at the code I wrote below, it’s easy. Final renderings

The following code has only one difficulty:

1. How to calculate the horizontal axis and vertical axis label coordinate position

The rest is much easier. There is a problem to note. In fact, it is complicated to write. All positions are calculated dynamically, because the actual project will have problems if you use the value browser that is written dead. Don’t say on the code, first patience to type once, and then in a little bit of research.

/**
  Here you can write something for 13
  Try to use English as much as possible, and you won't be able to Baidu yourself,

  For example:
  Author:leo lau
  desc:ni shishibushiwozuitengaideren ,ni weisha bushuo hua
**/
'use strict';
//Imitation http://echarts.baidu.com/demo.html#bar -gradient
window.onload = function(){
    var data = [
      {"label": "January", "value": getrandomint (0400)},
      {"label": "February", "value": getrandomint (1400)},
      {"label": "March", "value": getrandomint (1400)},
      {"label": "April", "value": getrandomint (0400)},
      {"label": "may", "value": getrandomint (1400)}
    ];

    var targetId = 'div1';
    var cw = 600;
    var ch = 450;
    //Why use object-oriented method, because it seems to drag
    //
    function Bcharts(targetId,cw,ch,data){
      //Basic information
        Var C = this; // why? I'm lazy, C = chart = this;
        c.configureChart(targetId,cw,ch,data);
        c.init();

    }
    Bcharts.prototype.configureChart = function(targetId,cw,ch,data){
      var c = this;
      c.setCanvasParameters(targetId,cw,ch,data);
      c.setChartParameters(targetId,cw,ch,data);
    };
    Bcharts.prototype.setCanvasParameters = function(targetId,cw,ch,data){
      var c = this;
      c.id = targetId;
      c.cw = cw;
      c.ch = ch;
      c.data = data;
    };
    Bcharts.prototype.setChartParameters = function(targetId,cw,ch,data){
      var c = this;
      c. Axeradio = 10; // define a scale. Why is it 10? Look at the picture. It's arbitrary. Don't be ridiculous
      c.horGap = (c.cw*c.axeRadio)/100;
      c.verGap = (c.ch*c.axeRadio)/100;
    //Sign preparation
      c. Fontradio = 3; // the reason is the same as above
      c.horFontSize = (c.cw*c.fontRadio)/100;
      c.verFontSize = (c.ch*c.fontRadio)/100;

    };
    //Initialization
    Bcharts.prototype.init = function(){
        var c = this;
        c.createCanvas();
        //This is just to sort out the data that the background gives you, not the data that can be drawn directly by the chart
        //For example, the maximum value is 234. In fact, we have to spend 240. It can't be untidy
        c.handleData();
        //So we need to process the data
        c.prepareData();

        //Painting
        c.draw();


    };
    Bcharts.prototype.createCanvas = function(){
        var c = this;
        var canvas = document.createElement('canvas');
        canvas.id = c.id + '-' + Math.random();
        canvas.width = c.cw;
        canvas.height = c.ch;
        document.getElementById(c.id).innerHTML = '';
        document.getElementById(c.id).appendChild(canvas);
        c.canvas = canvas;
        c.context = c.canvas.getContext('2d');
    };
    Bcharts.prototype.handleData = function(){
        //Because the background must give you a stack of standard array format, but you can't use it directly, you have to own 666
        var c = this;
        c. Label = []; // this array contains the name of the loop content, such as [January, February]
        c. Values = []; // value [200,45 ]
        c.data.forEach(function(item){
          c.label.push(item.label);
          c.values.push(item.value);
        });
    };
    Bcharts.prototype.prepareData = function(){
        var c = this;
        c.itemNum = c.data.length;
        c.MaxValue = Math.max.apply(null,c.values);
        c.MinValue = Math.min.apply(null,c.values);
        //Calculate coordinate width and height
        c.horAxiWidth = c.cw - 2*c.horGap;
        c.verAxiWidth = c.ch - 2*c.verGap;

        //Calculate the maximum upper boundary. For example, if the maximum number is 234, the coordinates get 240 instead of 234
        //Determine the width of horizontal and vertical grids
        c.verBound = Math.ceil(c.MaxValue/10)*10;
        c.verFeq = c.verBound/c.itemNum;
        c.horFeq = c.horAxiWidth/c.itemNum;
    };
    Bcharts.prototype.draw = function(){
        var c = this;
        c. Drawx(); // X axis
        c. Drawy(); // Y axis
        c. Drawylabel(); // Y coordinate word
        c. Drawxlabel(); // Y coordinate word
        c.HorGuideLines();
        c.verGuideLines();
        c.drawBars();
    };
    Bcharts.prototype.drawX = function(){
      var c = this;
      var gd = c.context;
        gd.beginPath();
        gd.moveTo(c.horGap,c.ch -c.verGap);
        gd.lineTo(c.cw -c.horGap,c.ch -c.verGap);
        gd.lineWidth = 2;
        gd.stroke();
    };
    Bcharts.prototype.drawY = function(){
      var c = this;
      var gd = c.context;
        gd.beginPath();
        gd.moveTo(c.horGap,c.ch -c.verGap);
        gd.lineTo(c.horGap,c.verGap);
        gd.lineWidth = 2;
        gd.stroke();
    };
    Bcharts.prototype.drawYLabel = function(){
      var c = this;
      var gd = c.context;
      for(var i = 0;i<=c.itemNum;i++){
        var labelYText = c.verBound - i*c.verFeq;
        var labelPosX = c.horGap - c.horGap/c.axeRadio;
        var scaleReq = (c.verAxiWidth/c.verBound)*c.verFeq;
        var labelPosY = c.verGap+i*scaleReq;
        gd.textAlign = 'right';
        gd.fillText(labelYText,labelPosX,labelPosY);
      }
      Bcharts.prototype.drawXLabel = function(){
        var c = this;
        var gd = c.context;
        for(var i = 0;i<c.itemNum;i++){
          var labelXText = c.label[i];
          var labelPosX = c.horGap + i*c.horFeq +c.horFeq/2;
          var labelPosY = c.ch - c.verGap+c.verGap/c.axeRadio;
          gd.textAlign = 'center';
          gd.textBaseline = 'top';
          gd.fillText(labelXText,labelPosX,labelPosY);
        }
      };


    };
    Bcharts.prototype.drawY = function(){
      var c = this;
      var gd = c.context;
        gd.moveTo(c.horGap,c.ch -c.verGap);
        gd.lineTo(c.horGap,c.verGap);
        gd.lineWidth = 2;
        gd.stroke();
    };
    Bcharts.prototype.HorGuideLines = function(){
      var c = this;
      var gd = c.context;

      gd.strokeStyle = '#eeeeee';
      gd.lineWidth = 1;
      for(var i = 0;i<c.itemNum;i++){
        gd.beginPath();
        var scaleReq = (c.verAxiWidth/c.verBound)*c.verFeq;
        var horStartX = c.horGap;
        var horStartY = c.verGap+i*scaleReq;
        var horEndX = c.cw -c.horGap;
        var horEndY = c.verGap+i*scaleReq;
        gd.moveTo(horStartX,horStartY);
        gd.lineTo(horEndX,horEndY);
        gd.stroke();

      }
    };
    Bcharts.prototype.verGuideLines = function(){
      var c = this;
      var gd = c.context;

      gd.strokeStyle = '#eeeeee';
      gd.lineWidth = 1;
      for(var i = 0;i<=c.itemNum;i++){
        gd.beginPath();
        var verStartX = c.horGap+i*c.horFeq;
        var verStartY = c.ch - c.verGap;
        var verEndX = c.horGap+i*c.horFeq;
        var verEndY = c.verGap;
        gd.moveTo(verStartX,verStartY);
        gd.lineTo(verEndX,verEndY);
        gd.stroke();

      }
    };
    Bcharts.prototype.drawBars = function () {
      // alert(1);
      var c = this;

      for(var i = 0; i < c.itemNum; i++){
        // alert(1);
        var color = c.rndColor();
        var fillOpacity = '0.3';
        var fillColor = 'rgba('+ color.r + ', ' + color.g  + ', ' + color.b + ', ' + fillOpacity +')';
        var borderColor = 'rgba('+ color.r + ', ' + color.g  + ', ' + color.b + ')';

        c.context.beginPath();

        var barX = c.horGap + i * c.horFeq+c.horFeq/c.axeRadio;
        var barY = c.ch - c.verGap;
        var barWidth = c.horFeq - 2*c.horFeq/c.axeRadio;
        var barHeight = -c.verAxiWidth * c.values[i] / c.MaxValue;
        console.log(c.MaxValue);

        c.context.fillStyle = fillColor;
        c.context.strokeStyle = borderColor;
        c.context.rect(barX, barY, barWidth, barHeight);
        // console.log(barX,barY,barWidth,barHeight);
        c.context.stroke();
        c.context.fill();
      }
    };

    Bcharts.prototype.rndColor = function () {
      var r = getRandomInt(0, 257);
      var g = getRandomInt(0, 257);
      var b = getRandomInt(0, 257);
      return {r: r, g: g, b: b};
    };
    var charts = new Bcharts(targetId,cw,ch,data);
};
//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random
//If you're lazy, you can't write the basic function
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}

PS: there are many basic functions to know. In fact, drawing canvas tests not canvas technology, but mathematics and basic knowledge. We must lay a good foundation.

Git address of the whole code:

https://github.com/leolau2012…

Recommended Today

In depth analysis of message middleware selection

preface Message Queuing Middleware (hereinafter referred to as message middleware) refers to the use of efficient and reliable message delivery mechanism for platform independent data exchange, and based on data communication to integrate distributed systems. By providing message delivery and message queuing model, it can provide application decoupling, elastic scaling, redundant storage, traffic peak clipping, […]