代码之家  ›  专栏  ›  技术社区  ›  Megidd

实施现金流时间表

  •  0
  • Megidd  · 技术社区  · 3 年前

    我正试图为现金流入和流出制定一个时间表,如下所示:

    Cash flow

    我不知道是否有什么图表类型可能有用。有没有可能实施这样一个图表?

    0 回复  |  直到 3 年前
        1
  •  2
  •   uminder    3 年前

    没有现成的图表类型可以生成所需的图表。但是,可以使用条形图和一些自定义代码来创建它。

    Plugin Core API 提供不同的钩子,允许您执行自定义代码。您可以定义 inline plugin 直接在画布上通过 CanvasRenderingContext2D . 我会用 beforeDraw 钩子,如下面的可运行代码段所示:

    function drawVerticalTriangle(ctx, x, y1, y2) {
      ctx.beginPath();
      ctx.moveTo(x, y1);
      ctx.lineTo(x + 6, y2);
      ctx.lineTo(x - 6, y2);
      ctx.fill();
    };
    
    function drawRightArrow(ctx, xLeft, xRight, y) {
      ctx.lineWidth = 3;
      ctx.beginPath(); 
      ctx.moveTo(xLeft, y);
      ctx.lineTo(xRight - 5, y);
      ctx.stroke();      
      ctx.beginPath();      
      ctx.moveTo(xRight, y);
      ctx.lineTo(xRight - 10, y + 6);
      ctx.lineTo(xRight - 10, y - 6);
      ctx.fill();
    };
    
    function drawTopArrow(ctx, x, yBottom, yTop) {
      ctx.lineWidth = 3;
      ctx.beginPath(); 
      ctx.moveTo(x, yBottom);
      ctx.lineTo(x, yTop - 5);
      ctx.stroke();      
      drawVerticalTriangle(ctx, x, yTop -10, yTop);
    };
    
    new Chart('myChart', {
      type: 'bar',
      plugins: [{
        beforeDraw: chart => {      
          let ctx = chart.ctx; 
          let xAxis = chart.scales.x;
          let yAxis = chart.scales.y;
          xAxis.ticks.forEach((v, i) => {       
            let x = xAxis.getPixelForTick(i);      
            let y = yAxis.getPixelForValue(chart.data.datasets[0].data[i]) - 3; 
            ctx.fillStyle = chart.data.datasets[0].borderColor;
            drawVerticalTriangle(ctx, x, y, y + 10);
            y = yAxis.getPixelForValue(chart.data.datasets[1].data[i]) + 3; 
            ctx.fillStyle = chart.data.datasets[1].borderColor;
            drawVerticalTriangle(ctx, x, y, y - 10);
          }); 
          ctx.strokeStyle = '#9999FF';
          ctx.fillStyle = '#9999FF';      
          let y = yAxis.getPixelForValue(0);
          drawRightArrow(ctx, xAxis.left - 5, xAxis.right + 40, y);
          ctx.font = '12px Arial';
          ctx.textAlign = 'right';
          ctx.fillText('PERIOD', xAxis.right + 30, y + 20);
          drawTopArrow(ctx, xAxis.left, yAxis.bottom + 10, yAxis.top - 10);
        }    
      }],
      data: {
        labels: ['1st year', '2nd year', '3rd year', '4th year'],
        datasets: [
          {
            label: 'Cash inflow', 
            data: [560, 590, 520, 620],   
            backgroundColor: '#0F9D58',    
            borderColor: '#0F9D58',
            barThickness: 4
          },
          {
            label: 'Cash outflow', 
            data: [-600, -550, -410, -570],   
            backgroundColor: '#DB4437',    
            borderColor: '#DB4437',
            barThickness: 4        
          }     
        ]
      },
      options: {
        animation: {
          duration: 100      
        },
        layout: {
          padding: {
            right: 40
          }
        },
        scales: {
          y: {
            grid: {  
              display: false,
            }        
          },
          x: {
            stacked: true,
            grid: {
              display: false,
              drawBorder: false
            }   
          }
        }
      }
    });
    canvas {
      max-width: 400px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.0/chart.min.js"></script>
    <canvas id="myChart" height="110"></canvas>
        2
  •  0
  •   Megidd    3 年前

    到目前为止,我能做的最好的事情是:

    // Import from the chart.js npm module.
    import { Chart } from "chart.js"; 
    
    // Get the context of the canvas element in our HTML file.
    let ctx = document.querySelector("canvas#chart").getContext("2d"); 
    
    // Create a chart.
    var chrt = new Chart(ctx, {
      type: "bar",
      data: {
        labels: ["1st year", "2nd year", "3rd year"],
        datasets: [
          {
            data: [-y1out.value, -y2out.value, -y3out.value]
            , backgroundColor: ["#DB4437", "#DB4437", "#DB4437"]
            , label: 'Cash outflow',
          }
          , {
            data: [y1in.value, y2in.value, y3in.value]
            , backgroundColor: ["#0F9D58", "#0F9D58", "#0F9D58"]
            , label: 'Cash inflow',
          }
        ]
      }
    });
    
    // Update chart when user modifies input values
    var els = document.getElementsByTagName("input");
    for (var i = 0; i < els.length; i++) {
      els[i].addEventListener('input', function() {
        chrt.data.datasets[0].data = [-y1out.value, -y2out.value, -y3out.value]
        chrt.data.datasets[1].data = [y1in.value, y2in.value, y3in.value]
        chrt.update();
      });
    }
    

    Result screenshot

    推荐文章