d3.js多个坐标轴柱状图

最终效果图镇楼:

本文通过三个步骤来介绍d3.js。

1、简单的柱状图;

2、多个x轴的柱状图;

3、多个x轴、y轴的柱状图;

学习心得:

d3.js入门相对比较困难,一旦掌握了核心思想,不断熟悉API,就可以做出很灵活、实用的图表。

canvas中,d3帮我们计算好了每个图形的位置,我们再一个一个的画上即可。

不要担心代码看起来很多,一个一个的分析出来,就会发现其实还是有套路的。

一、简单图表

示意图:

代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script src="d3.min.js"></script>
<script>
  "use strict";
  (function () {
    function init() {
      initData();
    }
    function initData() {var oneData = [
        {‘name‘: ‘办公用品‘, ‘value‘: 100},
        {‘name‘: ‘家具‘, ‘value‘: 20},
        {‘name‘: ‘技术‘, ‘value‘: 60}
      ];
      initUI(oneData);
    }
    function initUI(data) {
      var canvas = document.querySelector(‘#myCanvas‘);
      var context = canvas.getContext(‘2d‘);
      var margin = {top: 20, right: 20, bottom: 30, left: 40};
      var width = canvas.width - margin.left - margin.right;
      var height = canvas.height - margin.top - margin.bottom;
      var x0 = d3.scaleBand()
        .domain(data.map(function (d) {
          return d.name;
        }))
        .rangeRound([0, width])
        .padding(0.5);
      var y0 = d3.scaleLinear()
        .domain([0, d3.max(data, function (d) {
          return d.value;
        })])
        .range([height, 0]);
      context.translate(margin.left, margin.top);
      context.beginPath();
      x0.domain().forEach(function (d) {
        context.moveTo(x0(d) + x0.bandwidth() / 2, height);
        context.lineTo(x0(d) + x0.bandwidth() / 2, height + 6);
      });
      context.strokeStyle = ‘black‘;
      context.stroke();
      context.textAlign = "center";
      context.textBaseline = "top";
      x0.domain().forEach(function (d) {
        context.fillText(d, x0(d) + x0.bandwidth() / 2, height + 6);
      });
      context.beginPath();
      context.moveTo(0.5, height + 0.5);
      context.lineTo(width + 0.5, height + 0.5);
      context.strokeStyle = "black";
      context.stroke();
      var yTickCount = 10;
      var yTicks = y0.ticks(yTickCount);
      context.beginPath();
      yTicks.forEach(function (d) {
        context.moveTo(0, y0(d) + 0.5);
        context.lineTo(-6, y0(d) + 0 / 5);
      });
      context.strokeStyle = ‘black‘;
      context.stroke();
      context.textAlign = "right";
      context.textBaseline = "middle";
      yTicks.forEach(function (d) {
        context.fillText(d, -9, y0(d));
      });
      context.beginPath();
      context.moveTo(-6.5, 0 + 0.5);
      context.lineTo(0.5, 0 + 0.5);
      context.lineTo(0.5, height + 0.5);
      context.lineTo(-6.5, height + 0.5);
      context.strokeStyle = "black";
      context.stroke();
      context.fillStyle = "steelblue";
      data.forEach(function (d) {
        context.fillRect(x0(d.name), y0(d.value), x0.bandwidth(), height - y0(d.value));
      });
    }
    init();
  }());
</script>
</body>
</html>

二、多个x轴

示意图:

代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script src="d3.min.js"></script>
<script>
  "use strict";
  (function () {
    function init() {
      initData();
    }
    function initData() {var data =
        [
          {
            ‘name‘: ‘东北‘,
            ‘value‘: [
              {‘name‘: ‘办公用品‘, ‘value‘: 100},
              {‘name‘: ‘家具‘, ‘value‘: 20},
              {‘name‘: ‘技术‘, ‘value‘: 60}
            ]
          },
          {
            ‘name‘: ‘华北‘,
            ‘value‘: [
              {‘name‘: ‘办公用品‘, ‘value‘: 100},
              {‘name‘: ‘家具‘, ‘value‘: 80},
              {‘name‘: ‘技术‘, ‘value‘: 60}
            ]
          },
          {
            ‘name‘: ‘西南‘,
            ‘value‘: [
              {‘name‘: ‘办公用品‘, ‘value‘: 100},
              {‘name‘: ‘家具‘, ‘value‘: 80},
              {‘name‘: ‘技术‘, ‘value‘: 60}
            ]
          }
        ];
      initUI(data);
    }
    function initUI(data) {
      var canvas = document.querySelector(‘#myCanvas‘);
      var context = canvas.getContext(‘2d‘);
      var margin = {top: 20, right: 20, bottom: 45, left: 40};
      var width = canvas.width - margin.left - margin.right;
      var height = canvas.height - margin.top - margin.bottom;
      var xAxis0 = d3.scaleBand()
        .domain(data.map(function (d) {
          return d.name;
        }))
        .rangeRound([0, width]);
      var firstRow = data[0];
      var xAxis1 = d3.scaleBand()
        .domain(firstRow.value.map(function (d) {
          return d.name;
        }))
        .rangeRound([0, xAxis0.bandwidth()])
        .padding(0.5);
      var yAxis0 = d3.scaleLinear()
        .domain([0, d3.max(data, function (d0) {
          return d3.max(d0.value, function (d1) {
            return d1.value;
          })
        })])
        .range([height, 0]);
      context.translate(margin.left, margin.top);
      context.beginPath();
      context.textAlign = "center";
      context.textBaseline = "top";
      xAxis0.domain().forEach(function (d) {
        context.fillText(d, xAxis0(d) + xAxis0.bandwidth() / 2, height + 23);
      });
      data.forEach(function (d0) {
        var pX0 = xAxis0(d0.name);
        d0.value.forEach(function (d1) {
          context.moveTo(pX0 + xAxis1(d1.name) + xAxis1.bandwidth() / 2, height);
          context.lineTo(pX0 + xAxis1(d1.name) + xAxis1.bandwidth() / 2, height + 6);
          context.fillText(d1.name, pX0 + xAxis1(d1.name) + xAxis1.bandwidth() / 2, height + 6);
        });
      });
      context.strokeStyle = ‘black‘;
      context.stroke();
      context.beginPath();
      context.moveTo(0.5, height + 0.5);
      context.lineTo(width + 0.5, height + 0.5);
      context.strokeStyle = "black";
      context.stroke();
      var yTickCount = 10;
      var yTicks = yAxis0.ticks(yTickCount);
      context.beginPath();
      yTicks.forEach(function (d) {
        context.moveTo(0, yAxis0(d) + 0.5);
        context.lineTo(-6, yAxis0(d) + 0 / 5);
      });
      context.strokeStyle = ‘black‘;
      context.stroke();
      context.textAlign = "right";
      context.textBaseline = "middle";
      yTicks.forEach(function (d) {
        context.fillText(d, -9, yAxis0(d));
      });
      context.beginPath();
      context.moveTo(-6.5, 0 + 0.5);
      context.lineTo(0.5, 0 + 0.5);
      context.lineTo(0.5, height + 0.5);
      context.lineTo(-6.5, height + 0.5);
      context.strokeStyle = "black";
      context.stroke();
      context.fillStyle = "steelblue";
      data.forEach(function (d0) {
        var pX0 = xAxis0(d0.name);
        d0.value.forEach(function (d1) {
          var pX1 = pX0 + xAxis1(d1.name);
          var pY1 = yAxis0(d1.value);
          var pWidth = xAxis1.bandwidth();
          var pHeight = height - yAxis0(d1.value);
          context.fillRect(pX1, pY1, pWidth, pHeight);
        })
      });
    }
    init();
  }());
</script>
</body>
</html>

三、多个x、y轴

示意图:

代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script src="d3.min.js"></script>
<script>
  "use strict";
  (function () {
    function init() {
      initData();
    }
    function initData() {var data =
        [
          {
            ‘name‘: ‘利润‘,
            ‘value‘: [
              {
                ‘name‘: ‘东北‘,
                ‘value‘: [
                  {‘name‘: ‘办公用品‘, ‘value‘: 100},
                  {‘name‘: ‘家具‘, ‘value‘: 50},
                  {‘name‘: ‘技术‘, ‘value‘: 60}
                ]
              },
              {
                ‘name‘: ‘华北‘,
                ‘value‘: [
                  {‘name‘: ‘办公用品‘, ‘value‘: 90},
                  {‘name‘: ‘家具‘, ‘value‘: 70},
                  {‘name‘: ‘技术‘, ‘value‘: 60}
                ]
              },
              {
                ‘name‘: ‘西南‘,
                ‘value‘: [
                  {‘name‘: ‘办公用品‘, ‘value‘: 100},
                  {‘name‘: ‘家具‘, ‘value‘: 80},
                  {‘name‘: ‘技术‘, ‘value‘: 50}
                ]
              }
            ]
          },
          {
            ‘name‘: ‘销售额‘,
            ‘value‘: [
              {
                ‘name‘: ‘东北‘,
                ‘value‘: [
                  {‘name‘: ‘办公用品‘, ‘value‘: 100},
                  {‘name‘: ‘家具‘, ‘value‘: 20},
                  {‘name‘: ‘技术‘, ‘value‘: 60}
                ]
              },
              {
                ‘name‘: ‘华北‘,
                ‘value‘: [
                  {‘name‘: ‘办公用品‘, ‘value‘: 100},
                  {‘name‘: ‘家具‘, ‘value‘: 80},
                  {‘name‘: ‘技术‘, ‘value‘: 60}
                ]
              },
              {
                ‘name‘: ‘西南‘,
                ‘value‘: [
                  {‘name‘: ‘办公用品‘, ‘value‘: 100},
                  {‘name‘: ‘家具‘, ‘value‘: 80},
                  {‘name‘: ‘技术‘, ‘value‘: 60}
                ]
              }
            ]
          }
        ];
      initUI(data);
    }
    function initUI(data) {
      var canvas = document.querySelector(‘#myCanvas‘);
      var context = canvas.getContext(‘2d‘);
      var margin = {top: 20, right: 20, bottom: 45, left: 40};
      var width = canvas.width - margin.left - margin.right;
      var height = canvas.height - margin.top - margin.bottom;
      var firstRow = data[0].value;
      var firstFirstRow = firstRow[0].value;
      var xAxis0 = d3.scaleBand()
        .domain(firstRow.map(function (d) {
          return d.name;
        }))
        .rangeRound([0, width]);
      var xAxis1 = d3.scaleBand()
        .domain(firstFirstRow.map(function (d) {
          return d.name;
        }))
        .rangeRound([0, xAxis0.bandwidth()])
        .padding(0.5);
      var yAxis0 = d3.scaleBand()
        .domain(data.map(function (d) {
          return d.name;
        }))
        .range([height, 0])
        .paddingInner(0.1);
      var yAxis1 = d3.scaleLinear()
        .domain([0, d3.max(data, function (d0) {
          return d3.max(d0.value, function (d1) {
            return d3.max(d1.value, function (d2) {
              return d2.value;
            })
          })
        })])
        .range([yAxis0.bandwidth(), 0]);
      context.translate(margin.left, margin.top);
      context.beginPath();
      context.textAlign = "center";
      context.textBaseline = "top";
      xAxis0.domain().forEach(function (d) {
        context.fillText(d, xAxis0(d) + xAxis0.bandwidth() / 2, height + 23);
      });
      firstRow.forEach(function (xData0) {
        var pX0 = xAxis0(xData0.name);
        xData0.value.forEach(function (xData1) {
          context.moveTo(pX0 + xAxis1(xData1.name) + xAxis1.bandwidth() / 2, height);
          context.lineTo(pX0 + xAxis1(xData1.name) + xAxis1.bandwidth() / 2, height + 6);
          context.fillText(xData1.name, pX0 + xAxis1(xData1.name) + xAxis1.bandwidth() / 2, height + 6);
        })
      });
      context.strokeStyle = ‘black‘;
      context.stroke();
      context.beginPath();
      data.forEach(function (yData0) {
        var pY0 = yAxis0(yData0.name);
        var y = +(pY0 + yAxis0.bandwidth()).toFixed(0) + 0.5;
        context.moveTo(0.5, y);
        context.lineTo(width + 0.5, y);
      });
      context.strokeStyle = "black";
      context.stroke();
      var yTickCount = 10;
      var yTicks = yAxis1.ticks(yTickCount);
      context.beginPath();
      data.forEach(function (yData0) {
        var pY0 = yAxis0(yData0.name);
        for (var idx = 0; idx < yData0.name.length; idx++) {
          context.fillText(yData0.name[idx], -30, pY0 + yAxis0.bandwidth() / 2 - 15 + idx * 15);
        }
        yTicks.forEach(function (d) {
          var y = +(pY0 + yAxis1(d)).toFixed(0) + 0.5;
          context.moveTo(0, y);
          context.lineTo(-6, y);
        });
      });
      context.strokeStyle = ‘black‘;
      context.stroke();
      context.textAlign = "right";
      context.textBaseline = "middle";
      data.forEach(function (yData0) {
        var pY0 = yAxis0(yData0.name);
        yTicks.forEach(function (d) {
          var y = pY0 + yAxis1(d);
          context.fillText(d, -9, y);
        });
      });
      context.beginPath();
      context.moveTo(-6.5, 0 + 0.5);
      context.lineTo(0.5, 0 + 0.5);
      context.lineTo(0.5, height + 0.5);
      context.lineTo(-6.5, height + 0.5);
      context.strokeStyle = "black";
      context.stroke();
      context.fillStyle = "steelblue";
      data.forEach(function (yData0) {
        var pY0 = yAxis0(yData0.name);
        yData0.value.forEach(function (xData0) {
          var pX0 = xAxis0(xData0.name);
          xData0.value.forEach(function (xData1) {
            var pX1 = pX0 + xAxis1(xData1.name);
            var pY1 = pY0 + yAxis1(xData1.value);
            var pWidth = xAxis1.bandwidth();
            var pHeight = yAxis0.bandwidth() - yAxis1(xData1.value);
            context.fillRect(pX1, pY1, pWidth, pHeight);
          })
        })
      });
    }
    init();
  }());
</script>
</body>
</html>

源码下载:src

时间: 2024-10-09 01:41:24

d3.js多个坐标轴柱状图的相关文章

[5.1] D3.js中整合坐标轴 - 图表 - 文字标签

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 前面几节讲解了图标.坐标轴.比例等等,这一节整合这些内容做一个实用的图表.结果图如下: 代码如下所示: <html> <head> <meta charset="utf-8"> <title>Chart</title> </head> <style> .axis pat

[D3.js] SVG-Axes(坐标轴)

D3的坐标轴组件会自动显示刻度的参考线.这可以让你只专注于数据的显示,而让坐标轴组件去帮你绘制坐标轴和标记刻度.                Axis D3的轴组件是为D3的quantitative, time 和 ordinal 标度所设计的. # d3.svg.axis() 新建一个默认的坐标轴. # aixs(selection) 轴线适用于selection 或 transition.选择器必须包含一个 svg 或者 g 元素. 例如: d3.select("body").a

零基础自学前端 D3.js 初体验03 柱状图+排序

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>d3</title> </head> <script src="https://d3js.org/d3.v4.min.js"></script> <body> <button type="button"

D3.js的v5版本入门教程(第九章)——完整的柱状图

D3.js的v5版本入门教程(第九章) 一个完整的柱状图应该包括的元素有——矩形.文字.坐标轴,现在,我们就来一一绘制它们,这章是前面几章的综合,这一章只有少量新的知识点,它们是 d3.scaleBand():这也是一个坐标轴,可以根据输入的domain的长度,等分rangeRound域(类比range域)d3.range():这个比较复杂,建议去看百度(或者官方API),在这里我只讲一下这个返回一个等差数列    1.得到SVG画布 var marge = {top:60,bottom:60,

D3.js的v5版本入门教程(第八章)—— 坐标轴

D3.js的v5版本入门教程(第八章) D3中没有现成的坐标轴图形,需要我们自己用其他组件拼凑而成.D3中提供了坐标轴组件,使得我们在SVG中绘制一个坐标轴变得像添加一个普通元素那样简单 为了表绘制一个坐标轴,我们还是需要以下新的知识点 call()函数        定义一个坐标轴 坐标轴是有朝向的,在这里我们以向下朝向.水平方向的坐标轴为例,其他朝向的(比如向左朝向的.垂直的坐标轴)类似,这里是接着上一章来的,数据用的也是上一章的 //为坐标轴定义一个线性比例尺 var xScale = d

[5] D3.js中如何添加坐标轴

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢.      第3节中做了一个图标,但没有为它添加一个相应的坐标轴,这样不知道每一个柱形到底有多长.这一节做一个坐标轴. D3中的坐标轴都是以 svg 图的形式出现的,这也是为什么在第3节中要使用 svg 的方法做柱形图的原因.第4节里我们讲解了 scale (比例)的用法,在做坐标轴的时候也需要用到比例.第4节中,我们说到scale 是一个函数,这一节中的坐标轴也

d3.js初识

d3.js简单的入门 D3是一个JavaScript的框架:主要用途是数据的可视化, 所以他是在JavaScript下开发的,目前主要用的有D3.js 3.0版本和D3.js 4.0版本 使用方法非常简单,1.到官网下载d3.js,然后在html中添加就好了 . 2.或者直接链接到官网就行了. 它只能目前用于IE 8版本之上. 1.一些简单的操作 d3.select  //选择元素 d3.selectAll  //选择所有元素 d3.attr //修改属性 d3.append //添加元素 d3

d3.js学习

画svg图像 1.添加svg元素 2.添加g元素,g元素是一个分组的元素,相当于html中的div元素 3.画图像 4.画坐标轴 ----------------------------------------------------------------------------- d3画闲线性曲线例子 html: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&

【 D3.js 入门系列 — 11 】 入门总结

D3 新专题首页 一转眼,这个入门系列已经积累了二十二篇文章之多,我想作为 D3.js 这款数据可视化工具的入门来说已经足够了.相信仅仅要看完本系列.以后全然能够在辅以查询的情况下完毕大部分可视化工作. D3.js 最早的 v1.0 版本号是由 Michael Bostock 于2011年2月18日公布,其后经过多人的不断完好,眼下最新的版本号为 v3.4.11.从公布至今三年多的时间里,D3.js 在国外不断有人尝试并制作教程.成为了流行的数据可视化工具.可是眼下在国内能查询到中文资料还比較少