由于最近工作不是很忙,隧由把之前的charts项目用d3.js重写的一下,其实d3.js文档很多,但是入门不是很难,可是想真的能做一个完成的,交互良好的图还是要下一番功夫的。今天在echarts找到了一个柱状图,如图。

模仿了一番,废话不多说。下面就开始我们的代码(注意是D3.v4版本)。

1. js 类

class Bar {
constructor() {
this._width = 1000;
this._height = 700;
this._padding = 10;
this._offset = 35;
this._margins = {right: 40,bottom: 40,left: 40,top: 40};
this._scaleX = d3.scaleBand().rangeRound([0, this._width - this._margins.left - this._margins.right]);
this._scaleY = d3.scaleLinear().range([this._height - this._margins.top - this._margins.bottom, 0]);
this._color = '#3398DB';
this._data = [];
this._svg = null;
this._body = null;
this._tooltip = null;
this._shadow = null;
this._ticks = 5;
this._key = 'key';
this._value = 'value';
}
render() {
if(!this._tooltip) {
this._tooltip = d3.select('body')
.append('div')
.style('left', '40px')
.style('top', '30px')
.attr('class', 'tooltip')
.html('');
}
if(!this._svg) {
this._svg = d3.select('body')
.append('svg')
.attr('width', this._width)
.attr('height', this._height)
this.renderAxes();
this.renderClipPath();
}
this.renderBody();
}
renderAxes() {
let axes = this._svg.append('g')
.attr('class', 'axes'); this.renderXAxis(axes);
this.renderYAxis(axes);
}
renderXAxis(axes) {
let xAxis = d3.axisBottom().scale(this._scaleX)
axes.append('g')
.attr('class', 'x axis')
.attr('transform', `translate(${this.xStart()}, ${this.yStart()})`)
.call(xAxis)
}
renderYAxis(axes) {
let yAxis = d3.axisLeft().scale(this._scaleY).ticks(this._ticks);
axes.append('g')
.attr('class', 'y axis')
.attr('transform', `translate(${this.xStart()}, ${this.yEnd()})`)
.call(yAxis) d3.selectAll('.y .tick')
.append('line')
.attr('class', 'grid-line')
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', this.quadrantWidth())
.attr('y2', 0)
}
renderClipPath() {
this._svg.append('defs')
.append('clip-path')
.attr('id', 'body-clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', this.quadrantWidth())
.attr('height', this.quadrantHeight())
}
renderBody() {
if(!this._body) {
this._body = this._svg.append('g')
.attr('class', 'body')
.attr('transform', `translate(${this._margins.left},${this._margins.top})`)
.attr('clip-path', 'url(#clipPath)')
this.renderShadow()
}
this.renderBar();
this.listenMousemove();
}
renderShadow() {
this._shadow = this._body.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', this.everyWidth())
.attr('height', this._scaleY(0))
.attr('fill', '#000')
.attr('fill-opacity', 0)
}
renderBar() {
let barElements = this._body
.selectAll('rect.bar')
.data(this._data); let barEnter = barElements
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => this._scaleX(d[this._key]) + this.everyWidth() * 0.18)
.attr('y', () => this._scaleY(0))
.attr('width', this.everyWidth() * 0.64)
.attr('height', () => this.quadrantHeight() - this._scaleY(0)) let barUpdate = barEnter
.merge(barElements)
.transition()
.duration(800)
.ease(d3.easeCubicOut)
.attr('y', d => this._scaleY(d[this._value]))
.attr('height', d => {
console.log(this.quadrantHeight() - this._scaleY(d[this._value]))
return this.quadrantHeight() - this._scaleY(d[this._value])
}); let barExit = barElements
.exit()
.transition()
.attr('y', () => this._scaleY(0))
.attr('height', () => this.quadrantHeight() - this._scaleY(0))
.remove();
}
listenMousemove() {
this._svg.on('mousemove', () => {
let px = d3.event.offsetX;
let py = d3.event.offsetY;
if(px < this.xEnd() && px > this.xStart() && py < this.yStart() && py > this.yEnd()) {
this.renderShadowAndTooltip(px, py, px - this.xStart());
} else {
this.hideShadowAndTooltip();
}
})
}
renderShadowAndTooltip(x, y, bodyX) {
let cutIndex = Math.floor(bodyX / this.everyWidth());
this._shadow.transition().duration(50).ease(d3.easeLinear).attr('fill-opacity', .12).attr('x', cutIndex * this.everyWidth());
if(x > this.quadrantWidth() - this._tooltip.style('width').slice(0,-2) - this._padding * 2) {
x = x - this._tooltip.style('width').slice(0,-2) - this._padding * 2 - this._offset * 2;
}
if(y > this.quadrantHeight() - this._tooltip.style('height').slice(0,-2) - this._padding * 2) {
y = y - this._tooltip.style('height').slice(0,-2) - this._padding * 2 - this._offset * 2;
}
this._tooltip.html(`${this._data[cutIndex][this._key]}<br/>数量统计: ${this._data[cutIndex][this._value]}`).transition().duration(100).ease(d3.easeLinear).style('display', 'inline-block').style('opacity', .6).style('left', `${x + this._offset + this._padding}px`).style('top', `${y + this._offset + this._padding}px`);
}
hideShadowAndTooltip() {
    this._shadow.transition().duration(10).attr('fill-opacity', 0);
    this._tooltip.transition().duration(50).style('opacity', 0).on('end', function() {d3.select(this).style('display', 'none')})
  }
everyWidth() {
return this.quadrantWidth() / this._data.length;
}
quadrantWidth() {
return this._width - this._margins.left - this._margins.right;
}
quadrantHeight() {
return this._height - this._margins.top - this._margins.bottom;
}
xStart() {
return this._margins.left;
}
xEnd() {
return this._width - this._margins.right;
}
yStart() {
return this._height - this._margins.bottom;
}
yEnd() {
return this._margins.top;
}
scaleX(a) {
this._scaleX = this._scaleX.domain(a);
}
scaleY(a) {
this._scaleY = this._scaleY.domain(a)
}
key(k) {
if(!arguments.length) return this._key;
this._key = k;
this.scaleX(this._data.map(d => d[this._key]))
return this;
}
value(v) {
if(!arguments.length) return this._value;
this._value = v;
let arr = this._data.map(d => d[this._value]);
let ele = Math.pow(10, d3.max(arr).toString().length - 1);
let max = Math.ceil(d3.max(arr) / ele) * ele;
this.scaleY([0, max]);
return this;
}
data(data) {
if(!arguments.length) return this._data;
this._data = data;
return this;
}
}

2 CSS 文件很简单

.domain {
stroke-width:;
fill: none;
stroke: #888;
shape-rendering: crispEdges;
}
.x .tick line {
opacity: 0 ;
}
.tick text {
font-size: 14px;
}
.grid-line {
fill: none;
stroke: #888;
opacity: .4;
shape-rendering: crispEdges;
}
.bar {
fill: #3398DB;
}
.tooltip{
font-size: 15px;
width: auto;
padding: 10px;
height: auto;
position: absolute;
text-align: center;
background-color: #000000;
opacity: .6;
border-radius:5px;
color: #ffffff;
display: none;
}

3 加下来就是html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$Title$</title>
<link rel="stylesheet" type="text/css" href="css/base.css"/>
<script type="text/javascript" src="js/d3.v4.js"></script>
<script type="text/javascript" src="js/bar.js"></script>
</head>
<body>
<script>
var dataset = [{date: 'Mon', label: 15},{date: 'Tue', label: 52},{date: 'Wed', label: 200},{date: 'Thu', label: 235},{date: 'Fri', label: 390},{date: 'Sat', label: 330},{date: 'Sun', label: 221}];
var bar = new Bar();
bar
.data(dataset)
.key('date')
.value('label')
.render();
</script>
</body>
</html>

4 接着是效果图

新上手的朋友们可以先学习一下ES6,然后在学习类的思想,d3.v3和v4 v5的版本差异比较大,直接学习d3.v4就可以了,最最后推荐一本书。D3 4.x数据可视化实战手册。这本书比较基础但是能够通过它养成良好的d3编程习惯。祝大家d3学习顺利。

如果想下载代码或者预览这个DEMO请移步到原文!!!

原文链接:http://www.bettersmile.cn

d3.js 教程 模仿echarts柱状图的更多相关文章

  1. d3.js 教程 模仿echarts折线图

    今天我们来仿echarts折线图,这个图在echarts是折线图堆叠,但是我用d3改造成了普通的折线图,只为了大家学习(其实在简单的写一个布局就可以).废话不多说商行代码. 1 制作 Line 类 c ...

  2. d3.js 教程 模仿echarts legend功能

    上一节记录没有加上echarts的legend功能,这一小节补一下. 1. 数据 我们可以从echarts中看出,折线数据并不是我们传进入的原始数据(多数情况下我们也不会修改原始数据),而是原始数组的 ...

  3. javascript实例教程使用canvas技术模仿echarts柱状图

    canvas 画布是HTML5中新增的标签,可以通过js操作 canvas 绘图 API在网页中绘制图像. 百度开发了一个开源的可视化图表库ECharts,功能非常强大,可以实现折线图.柱状图.散点图 ...

  4. D3.js的v5版本入门教程(第三章)—— 选择元素和绑定数据

    D3.js的v5版本入门教程(第三章) 在D3.js中,选择元素和绑定元素是最基本的内容,也是很重要的内容,等你看完整个教程后你会发现,这些D3.js教程都是在选择元素和绑定元素的基础上展开后续工作的 ...

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

    D3.js的v5版本入门教程(第九章) 一个完整的柱状图应该包括的元素有——矩形.文字.坐标轴,现在,我们就来一一绘制它们,这章是前面几章的综合,这一章只有少量新的知识点,它们是 d3.scaleBa ...

  6. D3.js 入门教程

    最近需要用到d3, 记录下d3的教程 网上搜了几个关于d3的教程 D3.js 入门教程      http://wiki.jikexueyuan.com/project/d3wiki/author.h ...

  7. 页面生成柱状图 --- D3.js

    转载自:https://www.cnblogs.com/fastmover/p/7779660.html D3.js从入门到"放弃"指南 前言 近期略有点诸事不顺,趁略有闲余之时, ...

  8. D3.js的v5版本入门教程(第十一章)——交互式操作

    D3.js的v5版本入门教程(第十一章) 与图形进行交互操作是很重要的!所谓的交互操作也就是为图形元素添加监听事件,比如说当你鼠标放在某个图形元素上面的时候,就会显示相应的文字,而当鼠标移开后,文字就 ...

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

    D3.js的v5版本入门教程(第八章) D3中没有现成的坐标轴图形,需要我们自己用其他组件拼凑而成.D3中提供了坐标轴组件,使得我们在SVG中绘制一个坐标轴变得像添加一个普通元素那样简单 为了表绘制一 ...

随机推荐

  1. 在vue中监听storage的变化

    1.首先在main.js中给Vue.protorype注册一个全局方法,其中,我们约定好了想要监听的sessionStorage的key值为’watchStorage’,然后创建一个StorageEv ...

  2. Docker系列开篇之Virtual Machine VS Container(一)

    前言 本节开始我们正式进入Docker系列,网上关于Docker相关文章如数家珍,写博客至今,我也一直在朝着如何写出通俗易懂且不枯燥的文章这个目标前进,喃喃自语的同时也希望看到文章的童鞋能明白我在讲什 ...

  3. 【POJ - 3176】牛保龄球 (简单dp)

    牛保龄球 直接中文了 Descriptions 奶牛打保龄球时不使用实际的保龄球.它们各自取一个数字(在0..99范围内),然后排成一个标准的保龄球状三角形,如下所示: 7 3 8 8 1 0 2 7 ...

  4. Sublime Text3激活及个性化配置

    [TOC] 在我们的开发过程中,选择正确的开发工具会让我们事半功倍.作为后端开发我们熟悉的myeclipse和itellij idea这些工具我也介绍曾介绍过关于他们的安装及破解.但是我们并不能仅仅使 ...

  5. LayDate使用

    layDate非常愿意和您成为工作伙伴.她致力于成为全球最用心的web日期支撑,为国内外所有从事web应用开发的同仁提供力所能及的动力.她基于原生JavaScript精心雕琢,兼容了包括IE6在内的所 ...

  6. Servlet生成验证码并进行账号密码和验证码的验证登陆!

    前言: 人不是生来就懂事的,在编程的世界也是一样,想想在大一的时候我还是那个连输出Hello World!都不会的小孩子是,现在我已经可以编出属于我自己的小程序了.编程其实并不可怕,可怕的是你不去编. ...

  7. JAVA-SpringMVC 概述及组件介绍

    一.SpringMVC概述 SpringMVC是一个WEB层.控制层框架,主要用来负责与客户端交互,业务逻辑的调用. SpringMVC是Spring家族中的一大组件,Spring整合SpringMV ...

  8. asp.net core 从单机到集群

    asp.net core 从单机到集群 Intro 这篇文章主要以我的活动室预约的项目作为示例,看一下一个 asp.net core 应用从单机应用到分布式应用需要做什么. 示例项目 活动室预约提供了 ...

  9. 逛公园[NOIP2017 D2 T3](dp+spfa)

    题目描述 策策同学特别喜欢逛公园. 公园可以看成一张 \(N\)个点\(M\) 条边构成的有向图,且没有自环和重边.其中 1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条 ...

  10. Top 10 顶级项目管理工具

    成功的项目都要归功于成功的项目管理.这些工具帮你踏上成功之旅! 项目管理是成功完成项目并使公司变得伟大的秘诀.不,这不是标题党(clickbait) -- 我已经看到两家软件公司(我在那里工作)因为项 ...