最终效果图镇楼:

本文通过三个步骤来介绍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

d3.js多个x轴y轴canvas柱状图的更多相关文章

  1. vue中使用v-chart改变柱状图颜色以及X轴Y轴的文字颜色和大小以及标题

    1.html部分 <ve-histogram :tooltip-visible="true" :x-axis="xAxis" :y-axis=" ...

  2. highcharts 不显示X轴 Y轴 刻度

    xAxis: { tickWidth:0,        //设置刻度标签宽度 lineColor:'#ffffff',//设置坐标颜色 lineWidth:0,        //设置坐标宽度 la ...

  3. 3d照片环效果(修改版--添加了x轴y轴双向转动和修复模糊度的bug)

    今天用用前两天总结的css3新效果写了一个3d照片环的效果,其中还有些bug大家可以看一看,一起改进. <!DOCTYPE html> <html lang="en&quo ...

  4. JS逆向实战6-- x轴 y轴 过点触验证码

    点触验证码是一种常见的反爬手段 解决方案有两种:一种是直接解决,这需要深度学习机器学习等图像处理技术,以大量的数据训练识别模型,最终达到模型足矣识别图片中的文字提示和应该点击的区域之间的对应关系. 这 ...

  5. PhoneGap 加速计 api 获取加速计 x 轴 y 轴 z 轴信息

    一.PhoneGap 加速计 Accelerometer 对象介绍 1.主要方法 accelerometer.getCurrentAcceleration 获取当前设备在 x,y,z 轴上的加速度信息 ...

  6. Echarts X轴 Y轴 线的类型、颜色、及标签字体颜色 设置

    // 人均效能 var initRjxnChart = function () { var rjxnChart = echarts.init(document.getElementById(" ...

  7. svg 动画 透明度 放大缩小 x轴Y轴

    参考链接:https://www.cnblogs.com/Chrimisia/p/6670303.html vue 中封装svg:http://www.cnblogs.com/Jiangchuanwe ...

  8. 绕X 轴 Y轴 Z轴旋转的结果

    void warp_perspect_3_angle(cv::Mat face, float roll, float yaw, float pitch) { cv::Mat face_img = fa ...

  9. Opencv中图像height width X 轴 Y轴 rows cols之间的对应关系

    这里做一个备忘录:

随机推荐

  1. KMP算法 --- 在文本中寻找目标字符串

    KMP算法 --- 在文本中寻找目标字符串 很多时候,为了在大文本中寻找到自己需要的内容,往往需要搜索关键字.这其中就牵涉到字符串匹配的算法,通过接受文本和关键词参数来返回关键词在文本出现的位置.一般 ...

  2. HDOJ2004-成绩转换

    Problem Description 输入一个百分制的成绩t,将其转换成对应的等级,具体转换规则如下:90~100为A;80~89为B;70~79为C;60~69为D;0~59为E;   Input ...

  3. 【samba】samba 用户权限配置(转)

    首先要保证你的samba安装并配置好,关于安装和配置samba请参考此文章 http://blog.csdn.net/linglongwunv/archive/2010/01/19/5212875.a ...

  4. Java第三次上课课堂试验博文

    1.Java字段初始化的规律: 运行如下所示的代码 package demo; public class InitializeBlockDemo { /** * @param args */ publ ...

  5. TypeScript 异步代码类型技巧

    在typescript下编写异步代码,会遇到难以自动识别异步返回值类型的情况,本文介绍一些技巧,以辅助编写更健全的异步代码. callback 以读取文件为例: readFile是一个异步函数,包含p ...

  6. oracle 修改表空间文件路径方法

     比如说修改 user01.dbf  文件 的路径 1.先登录sqlplus:    C:\Documents and Settings\chezh>sqlplus  system/passwo ...

  7. 关于Python3中venv虚拟环境

    Python3.3以上的版本通过venv模块原生支持虚拟环境,可以代替Python之前的virtualenv. 该venv模块提供了创建轻量级"虚拟环境",提供与系统Python的 ...

  8. vue-router的使用

    关于vue-router的基本使用方法    首先,需要下载vue-router npm install vue-router --save vue-router在html或组件中的展现 ``` &l ...

  9. 【NO.4】jmeter-cookie管理器

    Compatibility 这种兼容性设计要求是适应尽可能多的不同的服务器,尽管不是完全按照标准来实现的.如果你遇到了解析Cookies的问题,你就可能要用到这一个规范. 有太多的web站点是用CGI ...

  10. IntelliJ IDEA Windows下Spark开发环境部署

    0x01 环境说明 本地 OS: windows 10 jdk: jdk1.8.0_121 scala: scala-2.11.11 IDE: IntelliJ IDEA ULTIMATE 2017. ...