最终效果图镇楼:

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

    8542-1090-0308-5951 2786-2836-1103-4104 6835-5846-6090-5388 5443-4068-2394-0845

  2. swift 3.0 基础练习 面向对象 类

    模拟需求 创建100个女朋友 1.用面向对象思想 2.名字随机 3.年龄随机 4.拥有约会功能 5.将所有女朋友信息输出 class GirlFirend: NSObject { var name:S ...

  3. IT软件管理人员的职业路线(从技术经理到总经理) - CEO之公司管理经验谈

    技术.业务和管理永远是工作的一个话题.笔者今天就根据自身的经验,通过这三个方面介绍下IT软件管理人员的职业路线.前面写过一个文(IT软件技术人员的职位路线(从程序员到技术总监) - 部门管理经验谈), ...

  4. C语言编译过程(转)

    内容摘要 : C语言编译的整个过程是非常复杂的,里面涉及到的编译器知识.硬件知识.工具链知识都是非常多的,深入了解整个编译过程对工程师理解应用程序的编写是有很大帮助的,希望大家可以多了解一些,在遇到问 ...

  5. Python:使用Kivy将python程序打包为apk文件

    1.概述 Kivy是一套Python下的跨平台开源应用开发框架,官网,我们可以用 它来将Python程序打包为安卓的apk安装文件.以下是在windows环境中使用. 安装和配置的过程中会下载很多东西 ...

  6. NlpirParser智能挖掘平台词性标注新算法

    词性标注是自然语言浅层理解的一个重要环节,它可帮助系统自动判定词语所属的语法范畴,为进一步处理提供更高层面的支持.词性标注主要任务是消除词性兼类歧义,对于新信息检测来说,它的实际意义还在于: (1)能 ...

  7. Jetty的工作原理

    Jetty的工作原理 Jetty 的基本架构 Jetty 目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器,它有一个基本数据模型,这个数据模型就 ...

  8. 数据库中间件 Sharding-JDBC 源码分析 —— SQL 解析(三)之查询SQL

  9. React Native 系列(五) -- 组件间传值

    前言 本系列是基于React Native版本号0.44.3写的.任何一款 App 都有界面之间数据传递的这个步骤的,那么在RN中,组件间是怎么传值的呢?这篇文章将介绍到顺传.逆传已经通过通知传值. ...

  10. python------函数嵌套及作用域链

    1.三元运算if条件成立的结果 if 条件 else 条件不成立的结果例如: a=20 b=10 c=a if a>b else b print(c) 2.命名空间 全局命名空间:创建的存储&q ...