由于瀑布图的实现方式有很多种,这里提供一种基于d3.js的实现方法。

HTML代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Waterfall Chart with D3.js</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <style>
        .chart {
            width: 800px;
            height: 500px;
            margin: 20px auto;
        }
        .axis path,
        .axis line {
            fill: none;
            stroke: black;
            shape-rendering: crispEdges;
        }
        .bar {
            fill: steelblue;
        }
        .bar.total {
            fill: #ccc;
        }
        .bar.negative {
            fill: #d62728;
        }
        .label {
            font-size: 12px;
            text-anchor: middle;
        }
    </style>
</head>
<body>
    <div class="chart"></div>
    <script src="waterfall.js"></script>
</body>
</html>

JavaScript代码:

// 数据
var data = [
    {name: 'Sales', value: 1000},
    {name: 'Cost of goods sold', value: -400},
    {name: 'Gross profit', value: 600},
    {name: 'Salary', value: -300},
    {name: 'Rent', value: -200},
    {name: 'Net profit', value: 100}
];

// 定义画布大小和边距
var margin = {top: 20, right: 20, bottom: 50, left: 50},
    width = 800 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

// 创建SVG元素
var svg = d3.select('.chart')
    .append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

// 计算总数
var total = d3.sum(data, function(d) { return d.value; });

// 定义比例尺
var x = d3.scaleBand()
    .domain(data.map(function(d) { return d.name; }))
    .range([0, width])
    .padding(0.1);
var y = d3.scaleLinear()
    .domain([0, d3.max(data, function(d) { return d.value; })])
    .range([height, 0]);

// 绘制x轴
var xAxis = d3.axisBottom()
    .scale(x);
svg.append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxis);

// 绘制y轴
var yAxis = d3.axisLeft()
    .scale(y);
svg.append('g')
    .attr('class', 'y axis')
    .call(yAxis);

// 绘制瀑布图
var bar = svg.selectAll('.bar')
    .data(data)
    .enter().append('rect')
    .attr('class', function(d) { return 'bar ' + (d.value < 0 ? 'negative' : ''); })
    .attr('x', function(d) { return x(d.name); })
    .attr('y', function(d) { return y(Math.max(0, d.value)); })
    .attr('width', x.bandwidth())
    .attr('height', function(d) { return Math.abs(y(d.value) - y(0)); });

// 绘制总数
svg.append('rect')
    .attr('class', 'bar total')
    .attr('x', 0)
    .attr('y', y(total))
    .attr('width', width)
    .attr('height', 1);
svg.append('text')
    .attr('class', 'label')
    .attr('x', width / 2)
    .attr('y', y(total) - 10)
    .text('Total');

// 绘制数值标签
svg.selectAll('.label')
    .data(data)
    .enter().append('text')
    .attr('class', 'label')
    .attr('x', function(d) { return x(d.name) + x.bandwidth() / 2; })
    .attr('y', function(d) { return y(d.value) + (d.value < 0 ? 20 : -5); })
    .text(function(d) { return d.value; });

注释:

  1. 首先定义数据,每个元素包含一个名称和一个值;
  2. 然后定义画布大小和边距;
  3. 创建SVG元素,并设置大小和边距;
  4. 计算总数,用于绘制总数水平线;
  5. 定义x轴和y轴的比例尺;
  6. 绘制x轴和y轴;
  7. 绘制瀑布图,包括正值和负值;
  8. 绘制总数水平线和总数标签;
  9. 绘制数值标签,包括正值和负值。
d3绘制瀑布图源码

原文地址: https://www.cveoy.top/t/topic/LSC 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录