最终效果图镇楼:

本文通过三个步骤来介绍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. 可存放任意类型变量的动态数组--C语言实现

    之前在训练营的时候被要求用C语言实现一个可以存放任意类型数据的栈.现在尝试实现一个数组版本. 首先用到的结构体如下(接触了Win32编程所以长得有点像里面的那些类型): typedef struct ...

  2. Java解析OFFICE(word,excel,powerpoint)以及PDF的实现方案及开发中的点滴分享

    Java解析OFFICE(word,excel,powerpoint)以及PDF的实现方案及开发中的点滴分享 在此,先分享下写此文前的经历与感受,我所有的感觉浓缩到一个字,那就是:"坑&qu ...

  3. Linux学习-->linux系统在移动硬盘的安装

    由于自己看了一些文章和linux的好奇,想来一窥Linux的奥秘,因此自己准备学习使用Linux系统,这里记录下自己的安装过程,方便以后自己重装系统时进行查阅. 参考的书籍是鸟哥的<Linux私 ...

  4. 31. leetcode 122. Best Time to Buy and Sell Stock II

    122. Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price ...

  5. 阿里消息队列中间件 RocketMQ 源码分析 —— Message 拉取与消费(上)

  6. 移动Web学习笔记(第1天)-bootstrap框架的使用

    移动web前言 移动web : 移动端手机浏览器或者微信里面浏览的网页 移动APP : 手机上需要下载安装的应用程序 1. 移动web介绍 1.1 3 天 响应式开发 一套代码运行多个终端 优点:开发 ...

  7. nopcommerce数据库字典

    http://www.xcode.me/open/document/nopcommercedatadict.html

  8. 刚开始学python——数据结构——“自定义队列结构“

    自定义队列结构  (学习队列后,自己的码) 主要功能:用列表模拟队列结构,考虑了入队,出队,判断队列是否为空,是否已满以及改变队列大小等基本操作. 下面是封装的一个类,把代码保存在myQueue.py ...

  9. java中使用poi导出excel表格数据并且可以手动修改导出路径

    在我们开发项目中,很多时候会提出这样的需求:将前端的某某数据以excel表格导出,今天就给大家写一个简单的模板. 这里我们选择使用poi导出excel: 第一步:导入需要的jar包到 lib 文件夹下

  10. Appium入门示例(Java)

    一.使用Eclipse直接创建案例工程 1.打开Eclipse,[File]-->[New]-->[Project] 2.选择[Java Project]-->[Next] 3.输入 ...