• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >JavaScript > d3.js实现立体柱图的方法详解

d3.js实现立体柱图的方法详解

作者:勿忘初心梦于歌 字体:[增加 减小] 来源:互联网 时间:2017-05-11

勿忘初心梦于歌通过本文主要向大家介绍了d3.js,d3.js官网,d3.js中文教程,d3.js下载,d3.js入门教程等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

众所周知随着大数据时代的来临,数据可视化的重要性也越来越凸显,那么今天就基于d3.js今天给大家带来可视化基础图表柱图进阶:立体柱图,之前介绍过了d3.js实现柱状图的文章,感兴趣的朋友们可以看一看。

关于d3.js

d3.js是一个操作svg的图表库,d3封装了图表的各种算法.对d3不熟悉的朋友可以到d3.js官网学习d3.js.

另外感谢司机大傻(声音像张学友一样性感的一流装逼手)和司机呆(呆萌女神)等人对d3.js进行翻译!

HTML+CSS

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <style>
 * {
 margin: 0;
 padding: 0;
 }

 div.tip-hill-div {
 background: rgba(0, 0, 0, 0.7);
 color: #fff;
 padding: 10px;
 border-radius: 5px;
 font-family: Microsoft Yahei;
 }

 div.tip-hill-div > h1 {
 font-size: 14px;
 }

 div.tip-hill-div > h2 {
 font-size: 12px;
 }
 </style>
</head>
<body>
<div id="chart"></div>
</body>
</html>
</div>

JS

当前使用d3.v4+版本

<script src="d3-4.js"></script>
</div>

图表所需数据

var data = [{
 "letter": "白皮鸡蛋",
 "child": {
 "category": "0",
 "value": "459.00"
 }
 }, {
 "letter": "红皮鸡蛋",
 "child": {
 "category": "0",
 "value": "389.00"
 }
 }, {
 "letter": "鸡蛋",
 "child": {
 "category": "0",
 "value": "336.00"
 }
 }, {
 "letter": "牛肉",
 "child": {
 "category": "0",
 "value": "282.00"
 }
 }, {
 "letter": "羊肉",
 "child": {
 "category": "0",
 "value": "249.00"
 }
 }, {
 "letter": "鸭蛋",
 "child": {
 "category": "0",
 "value": "242.00"
 }
 }, {
 "letter": "红薯",
 "child": {
 "category": "0",
 "value": "222.00"
 }
 }, {
 "letter": "白菜",
 "child": {
 "category": "0",
 "value": "182.00"
 }
 }, {
 "letter": "鸡肉",
 "child": {
 "category": "0",
 "value": "102.00"
 }
 }];
</div>

图表的一些基础配置数据

var margin = {
 top: 20,
 right: 50,
 bottom: 50,
 left: 90
 };

var svgWidth = 1000;
var svgHeight = 500;


//创建各个面的颜色数组
var mainColorList = ['#f6e242', '#ebec5b', '#d2ef5f', '#b1d894','#97d5ad', '#82d1c0', '#70cfd2', '#63c8ce', '#50bab8', '#38a99d'];
var topColorList = ['#e9d748', '#d1d252', '#c0d75f', '#a2d37d','#83d09e', '#68ccb6', '#5bc8cb', '#59c0c6', '#3aadab', '#2da094'];
var rightColorList = ['#dfce51', '#d9db59', '#b9d54a', '#9ece7c','#8ac69f', '#70c3b1', '#65c5c8', '#57bac0', '#42aba9', '#2c9b8f'];

var svg = d3.select('#chart')
 .append('svg')
 .attr('width', svgWidth)
 .attr('height', svgHeight)
 .attr('id', 'svg-column');
</div>

创建X轴序数比例尺

function addXAxis() {
 var transform = d3.geoTransform({
 point: function (x, y) {
 this.stream.point(x, y)
 }
 });
 //定义几何路径
 var path = d3.geoPath()
 .projection(transform);

 xLinearScale = d3.scaleBand()
 .domain(data.map(function (d) {
  return d.letter;
 }))
 .range([0, svgWidth - margin.right - margin.left], 0.1);
 var xAxis = d3.axisBottom(xLinearScale)
 .ticks(data.length);
 //绘制X轴
 var xAxisG = svg.append("g")
 .call(xAxis)
 .attr("transform", "translate(" + (margin.left) + "," + (svgHeight - margin.bottom) + ")");

 //删除原X轴
 xAxisG.select("path").remove();
 xAxisG.selectAll('line').remove();
 //绘制新的立体X轴
 xAxisG.append("path")
 .datum({
  type: "Polygon",
  coordinates: [
  [
  [20, 0],
  [0, 15],
  [svgWidth - margin.right - margin.left, 15],
  [svgWidth + 20 - margin.right - margin.left, 0],
  [20, 0]
  ]
  ]
 })
 .attr("d", path)
 .attr('fill', 'rgb(187,187,187)');
 xAxisG.selectAll('text')
 .attr('font-size', '18px')
 .attr('fill', '#646464')
 .attr('transform', 'translate(0,20)');

 dataProcessing(xLinearScale)//核心算法
 }
</div>

你可能注意到了,上面代码中不仅使用了序数比例尺,还有地理路径生成器,因为需要生成立体的柱图,所以需要讲原本的X轴删除,自己重新进行绘制.下图是自己重新绘制出来的path路径:


创建Y轴线性比例尺

var yLinearScale;
 //创建y轴的比例尺渲染y轴
 function addYScale() {
 yLinearScale = d3.scaleLinear()
 .domain([0, d3.max(data, function (d, i) {
  return d.child.value * 1;
 }) * 1.2])
 .range([svgHeight - margin.top - margin.bottom, 0]);

 //定义Y轴比例尺以及刻度
 var yAxis = d3.axisLeft(yLinearScale)
 .ticks(6);

 //绘制Y轴
 var yAxisG = svg.append("g")
 .call(yAxis)
 .attr('transform', 'translate(' + (margin.left + 10) + "," + margin.top + ")");
 yAxisG.selectAll('text')
 .attr('font-size', '18px')
 .attr('fill', '#636363');
 //删除原Y轴路径和tick
 yAxisG.select("path").remove();
 yAxisG.selectAll('line').remove();
 }
</div>

创建Y轴时同样需要把原来的路径和tick删除,下图是效果:

到这,我们的基础搭建完毕,下面就是核心算法

核心算法

为了实现最终效果,我希望大家在理解的时候能把整个立体柱图分解一下.

我实现立体柱图的思路是通过2个path路径和一个rect进行拼凑.

正面是一个rect,上面和右面利用path路径生成.

利用三角函数,通过给定的angle角度计算上面的一个点就可以知道其他所有点的位置进而进行绘制.

通过上图可以看到,一个立体柱图我们只需要知道7个点的位置就能够绘制出来.

并且已知正面rect4个红色点的位置.已知柱子的宽度和高度,那么只要求出Top面左上角点的位置,就可以知道余下绿色点的位置.具体算法如下:

//核心算法思路是Big boss教的,我借花献佛
function dataProcessing(xLinearScale) {
 var angle = Math.PI / 2.3;
 for (var i = 0; i < data.length; i++) {
  var d = data[i];
  var depth = 10; 
  d.ow = xLinearScale.bandwidth() * 0.7;
  d.ox = xLinearScale(d.letter);
  d.oh = 1;
  d.p1 = {
  x: Math.cos(angle) * d.ow,
  y: -Math.sin(angle) - depth
  };
  d.p2 = {
  x: d.p1.x + d.ow,
  y: d.p1.y
  };
  d.p3 = {
  x: d.p2.x,
  y: d.p2.y + d.oh
  };
 }
 }
</div>

渲染

最终我们还要鼠标进行交互,所以先添加tip生成函数

//tip的创建方法(方法来自敬爱的鸣哥)
 var tipTimerConfig = {
 longer: 0,
 target: null,
 exist: false,
 winEvent: window.event,
 boxHeight: 398,
 boxWidth: 376,
 maxWidth: 376,
 maxHeight: 398,
 tooltip: null,

 showTime: 3500,
 hoverTime: 300,
 displayText: "",
 show: function (val, e) {
  "use strict";
  var me = this;

  if (e != null) {
  me.winEvent = e;
  }

  me.displayTex



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • d3.js入门教程之数据绑定详解
  • d3.js实现立体柱图的方法详解
  • D3.js中强制异步文件读取同步的几种方法
  • d3.js中冷门却实用的内置函数总结

相关文章

  • 2017-05-11js 颜色选择插件
  • 2017-05-11Vue.js学习之计算属性
  • 2017-05-11详谈Ajax请求中的async:false/true的作用(ajax 在外部调用问题)
  • 2017-05-11JS批量替换内容中关键词为超链接
  • 2017-05-11原生js实现放大镜特效
  • 2017-05-11jquery实现图片平滑滚动详解
  • 2017-05-11JavaScript中利用构造器函数模拟类的方法
  • 2017-05-11javascript实现多张图片左右无缝滚动效果
  • 2017-05-11简单实现jQuery弹幕效果
  • 2017-05-11js select下拉联动 更具级联性!

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • vue + socket.io实现一个简易聊天室示例代码
    • jQuery插件autocomplete使用详解
    • 微信小程序scroll-view实现横向滚动和上拉加载示例
    • JSON字符串和JSON对象相互转化实例详解
    • Android中Okhttp3实现上传多张图片同时传递参数
    • jQuery实现最简单实用的分秒倒计时
    • jquery 实时监听输入框值变化的完美方法(必看)
    • 原生js实现轮播图
    • js轮播图透明度切换(带上下页和底部圆点切换)
    • JavaScript正则表达式替换字符串中图片地址(img src)的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有