基于d3.js实现实时刷新的折线图


Posted in Javascript onAugust 03, 2016

先来看看效果图

基于d3.js实现实时刷新的折线图

下面直接上源代码,html文件

<html> 
 <head> 
    <meta charset="utf-8"> 
    <title>实时刷新折线图</title> 
 <style>
 .axis path,
 .axis line{
 fill: none;
 stroke: black;
 shape-rendering: crispEdges;
 }
 
 .axis text {
 font-family: sans-serif;
 font-size: 11px;
 }

 .overlay {
 fill: none;
 pointer-events: all;
 }
 
 .tooltip{
 width: 150px;
 height: auto;
 position: absolute;
 font-family: simsun;
 font-size: 16px;
 line-height: 26px;
 text-align: left;
 border: 1px solid black;
 background-color: white;
 border-radius: 5px;
  }

  .tooltip .title{
   border-bottom: 1px solid #000;
   text-align: center;
  }

  .tooltip .desColor{
   width: 10px;
   height: 10px;
   float: left;
 margin: 9px 8px 1px 8px;
  }

  .tooltip .desText{
   display: inline;
  }

  .focusLine {
 stroke: black;
 stroke-width: 1px;
 stroke-dasharray: 5,5;
 }
 </style>
 </head> 
<body>

<script src="http://d3js.org/d3.v3.js" charset="utf-8"></script> 
<script src="linechart.js" charset="utf-8"></script> 
<svg contentScriptType="text/ecmascript" width="2000" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" style="background-color:#ffffff;" contentStyleType="text/css" viewBox="0 0 2000.0 2000.0" height="2000" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" version="1.0">
<defs>
<symbol id="fillgauge1" viewBox="0 0 500.0 300.0" preserveAspectRatio="none meet">
</symbol>
<symbol id="fillgauge2" viewBox="0 0 200.0 200.0" preserveAspectRatio="none meet">
</symbol>
</defs>
<use x="0" y="0" width="500" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#fillgauge1" xlink:type="simple" xlink:actuate="onLoad" symboltype="17" height="300" xlink:show="embed"/>
<use x="20" y="20" width="50" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#fillgauge2" xlink:type="simple" xlink:actuate="onLoad" symboltype="17" height="180" xlink:show="embed"/>
</svg>
<script> 
var dataset = [
 {
 country: "china",
 gdp: [[2000,11920],[2001,13170],[2002,14550],
  [2003,16500],[2004,19440],[2005,22870],
  [2006,27930],[2007,35040],[2008,45470],
  [2009,51050],[2010,59490],[2011,73140],
  [2012,83860],[2013,103550]]
 },
 {
 country: "usa",
 gdp: [[2000,47310],[2001,41590],[2002,39800],
  [2003,43020],[2004,46550],[2005,45710],
  [2006,43560],[2007,43560],[2008,48490],
  [2009,50350],[2010,54950],[2011,59050],
  [2012,59370],[2013,48980]]
 }
];

var gauge1=loadLineChart("fillgauge1",dataset);
 function NewValue(){
    if(Math.random() > .5){
      return Math.round(Math.random()*100);
    } else {
      return (Math.random()*100).toFixed(1);
    }
  }
 
function refreshLine(gauge1){
 //alert("hehe");
 // document.getElementById("fillgauge1").innerHTML="";
 var updateData =[
 {
 country: "china",
 gdp: [[2000,NewValue()],[2001,NewValue()],[2002,NewValue()],
  [2003,NewValue()],[2004,NewValue()],[2005,NewValue()],
  [2006,NewValue()],[2007,NewValue()],[2008,NewValue()],
  [2009,NewValue()],[2010,NewValue()],[2011,NewValue()],
  [2012,NewValue()],[2013,NewValue()]]
 },
 {
 country: "usa",
 gdp: [[2000,NewValue()],[2001,NewValue()],[2002,NewValue()],
  [2003,NewValue()],[2004,NewValue()],[2005,NewValue()],
  [2006,NewValue()],[2007,NewValue()],[2008,NewValue()],
  [2009,NewValue()],[2010,NewValue()],[2011,NewValue()],
  [2012,NewValue()],[2013,NewValue()]]
 }
  ];

 gauge1.update(updateData);
 }
self.setInterval("refreshLine(gauge1)",5000);
</script> 

</body>
</html>

lineChart.js负责加载和刷新折线图

function loadLineChart(elementId, dataset) {
 var svg = d3.select("#" + elementId);
 var strs = svg.attr("viewBox").split(" ");
 alert(dataset);
 var width = strs[2];
 var height = strs[3];

 //外边框
 var padding = {
 top : 50,
 right : 50,
 bottom : 50,
 left : 50
 };

 var names = new Array();
 //计算GDP的最大值
 var gdpmax = 0;
 for (var i = 0; i < dataset.length; i++) {
 var currGdp = d3.max(dataset[i].gdp, function (d) {
  return d[1];
  });
 if (currGdp > gdpmax)
  gdpmax = currGdp;

 }
 var gdpnumb = dataset[0].gdp.length;
 for (var j = 0; j < gdpnumb; j++) {
 names[j] = (dataset[0].gdp[j])[0];
 }

 alert(names);
 var xScale = d3.scale.linear()
 .domain([2000, 2013])
 .range([0, width - padding.left - padding.right]);
 // var xScale = d3.scale.ordinal()
 // .domain(names)
 // .rangeRoundBands([0, width - padding.left - padding.right]);

 var yScale = d3.scale.linear()
 .domain([0, gdpmax * 1.1])
 .range([height - padding.top - padding.bottom, 0]);

 //创建一个直线生成器
 var linePath = d3.svg.line()
 .x(function (d) {
  return xScale(d[0]);
 })
 .y(function (d) {
  return yScale(d[1]);
 })
 .interpolate("basis");

 //定义两个颜色
 var colors = [d3.rgb(0, 0, 255), d3.rgb(0, 255, 0)];

 //添加路径
 svg.selectAll("path") //选择<svg>中所有的<path>
 .data(dataset) //绑定数据
 .enter() //选择enter部分
 .append("path") //添加足够数量的<path>元素
 .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
 .attr("d", function (d) {
 return linePath(d.gdp); //返回直线生成器得到的路径
 })
 .attr("fill", "none")
 .attr("stroke-width", 3)
 .attr("stroke", function (d, i) {
 return colors[i];
 });

 //添加垂直于x轴的对齐线
 var vLine = svg.append("line")
 .attr("class", "focusLine")
 .style("display", "none");

 //添加一个提示框
 var tooltip = d3.select("body")
 .append("div")
 .attr("class", "tooltip")
 .style("opacity", 0.0);

 var title = tooltip.append("div")
 .attr("class", "title");

 var des = tooltip.selectAll(".des")
 .data(dataset)
 .enter()
 .append("div");

 var desColor = des.append("div")
 .attr("class", "desColor");

 var desText = des.append("div")
 .attr("class", "desText");

 //添加一个透明的监视鼠标事件用的矩形
 svg.append("rect")
 .attr("class", "overlay")
 .attr("x", padding.left)
 .attr("y", padding.top)
 .attr("width", width - padding.left - padding.right)
 .attr("height", height - padding.top - padding.bottom)
 .on("mouseover", function () {
 tooltip.style("left", (d3.event.pageX) + "px")
 .style("top", (d3.event.pageY + 20) + "px")
 .style("opacity", 1.0);

 vLine.style("display", null);
 })
 .on("mouseout", function () {
 tooltip.style("opacity", 0.0);
 vLine.style("display", "none");
 })
 .on("mousemove", mousemove);

 function mousemove() {
 /* 当鼠标在透明矩形内滑动时调用 */

 //折线的源数组
 var data = dataset[0].gdp;

 //获取鼠标相对于透明矩形左上角的坐标,左上角坐标为(0,0)
 var mouseX = d3.mouse(this)[0] - padding.left;
 var mouseY = d3.mouse(this)[1] - padding.top;

 //通过比例尺的反函数计算原数据中的值,例如x0为某个年份,y0为GDP值
 var x0 = xScale.invert(mouseX);
 var y0 = yScale.invert(mouseY);

 //对x0四舍五入,如果x0是2005.6,则返回2006;如果是2005.2,则返回2005
 x0 = Math.round(x0);

 //查找在原数组中x0的值,并返回索引号
 var bisect = d3.bisector(function (d) {
  return d[0];
  }).left;
 var index = bisect(data, x0);

 //获取年份和gdp数据
 var year = x0;
 var gdp = [];

 for (var k = 0; k < dataset.length; k++) {
  gdp[k] = {
  country : dataset[k].country,
  value : dataset[k].gdp[index][1]
  };
 }

 //设置提示框的标题文字(年份)
 title.html("<strong>" + year + "年</strong>");

 //设置颜色标记的颜色
 desColor.style("background-color", function (d, i) {
  return colors[i];
 });

 //设置描述文字的内容
 desText.html(function (d, i) {
  return gdp[i].country + "\t" + "<strong>" + gdp[i].value + "</strong>";
 });

 //设置提示框的位置
 tooltip.style("left", (d3.event.pageX) + "px")
 .style("top", (d3.event.pageY + 20) + "px");

 //获取垂直对齐线的x坐标
 var vlx = xScale(data[index][0]) + padding.left;

 //设定垂直对齐线的起点和终点
 vLine.attr("x1", vlx)
 .attr("y1", padding.top)
 .attr("x2", vlx)
 .attr("y2", height - padding.bottom);
 }

 var markStep = 80;

 var gMark = svg.selectAll(".gMark")
 .data(dataset)
 .enter()
 .append("g")
 .attr("transform", function (d, i) {
  return "translate(" + (padding.left + i * markStep) + "," + (height - padding.bottom + 40) + ")";
 });

 gMark.append("rect")
 .attr("x", 0)
 .attr("y", 0)
 .attr("width", 10)
 .attr("height", 10)
 .attr("fill", function (d, i) {
 return colors[i];
 });

 gMark.append("text")
 .attr("dx", 15)
 .attr("dy", ".5em")
 .attr("fill", "black")
 .text(function (d) {
 return d.country;
 });

 //x轴
 var xAxis = d3.svg.axis()
 .scale(xScale)
 .ticks(5)
 .tickFormat(d3.format("d"))
 .orient("bottom");

 //y轴
 var yAxis = d3.svg.axis()
 .scale(yScale)
 .orient("left");

 svg.append("g")
 .attr("class", "axis")
 .attr("transform", "translate(" + padding.left + "," + (height - padding.bottom) + ")")
 .call(xAxis);

 svg.append("g")
 .attr("class", "y axis")
 .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
 .call(yAxis);

 function updateLineChart() {

 this.update = function (updateData) {
  //xScale.domain(updateData,function(d){return d.name});
  var numValues = updateData.length;
  var updategdpmax = 0;
  for (var i = 0; i < updateData.length; i++) {
  var currGdp = d3.max(updateData[i].gdp, function (d) {
   return d[1];
   });
  if (currGdp > updategdpmax)
   updategdpmax = currGdp;
  }

  yScale = d3.scale.linear()
  .domain([0, updategdpmax * 1.1])
  .range([height - padding.top - padding.bottom, 0]);
  yAxis = d3.svg.axis()
  .scale(yScale)
  .orient("left");
  svg.selectAll("g.y.axis")
  .call(yAxis);

  svg.selectAll("path") //选择<svg>中所有的<path>
  .data(updateData) //绑定数据
  .transition()
  .duration(2000)
  .ease("linear")
  .attr("d", function (d) {

  return linePath(d.gdp); //返回直线生成器得到的路径
  });

 }

 }
 return new updateLineChart();
}

刚开始数据刷新了但是坐标轴木有刷新

引入

svg.selectAll("g.y.axis")
  .call(yAxis);

以上就是d3.js实现实时刷新折线图的全部内容,希望给大家学习d3.js带来帮助。

Javascript 相关文章推荐
为调试JavaScript添加输出窗口的代码
Feb 07 Javascript
基于jquery的合并table相同单元格的插件(精简版)
Apr 05 Javascript
js跨域访问示例(客户端/服务端)
May 19 Javascript
JavaScript判断textarea值是否为空并给出相应提示
Sep 04 Javascript
json实现前后台的相互传值详解
Jan 05 Javascript
jquery获取easyui日期控件的值实现方法
Nov 09 Javascript
浅析jsopn跨域请求原理及cors(跨域资源共享)的完美解决方法
Feb 06 Javascript
node.js程序作为服务并在windows下开机自启动(用forever)
Mar 29 Javascript
layui的table中显示图片方法
Aug 17 Javascript
javascript面向对象三大特征之封装实例详解
Jul 24 Javascript
使用Vue+Django+Ant Design做一个留言评论模块的示例代码
Jun 01 Javascript
深入理解 ES6中的 Reflect用法
Jul 18 Javascript
JS判断iframe是否加载完成的方法
Aug 03 #Javascript
两行代码轻松搞定JavaScript日期验证
Aug 03 #Javascript
Highcharts学习之数据列
Aug 03 #Javascript
JavaScript中日期函数的相关操作知识
Aug 03 #Javascript
JS实现的表格行上下移动操作示例
Aug 03 #Javascript
基于jQuery实现淡入淡出效果轮播图
Jul 31 #Javascript
JS使用正则表达式实现关键字替换加粗功能示例
Aug 03 #Javascript
You might like
用函数读出数据表内容放入二维数组
2006/10/09 PHP
Apache2 httpd.conf 中文版
2006/12/06 PHP
php常量详细解析
2015/10/27 PHP
微信封装的调用微信签名包的类库
2017/06/08 PHP
layui框架实现文件上传及TP3.2.3(thinkPHP)对上传文件进行后台处理操作示例
2018/05/12 PHP
laravel通用化的CURD的实现
2019/12/13 PHP
指定位置如果有图片显示图片,无图片显示广告的JS
2010/06/05 Javascript
jQuery $.data()方法使用注意细节
2012/12/31 Javascript
javascript中[]和{}对象使用介绍
2013/03/20 Javascript
JavaScript Window浏览器对象模型方法与属性汇总
2015/04/20 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
jquery用ajax方式从后台获取json数据后如何将内容填充到下拉列表
2015/08/26 Javascript
JS 动态加载js文件和css文件 同步/异步的两种简单方式
2016/09/23 Javascript
利用vue-router实现二级菜单内容转换
2016/11/30 Javascript
详解nodeJS之路径PATH模块
2017/05/31 NodeJs
js中的reduce()函数讲解
2019/01/18 Javascript
javascript实现自由编辑图片代码详解
2019/06/21 Javascript
pageGroup.js实现分页功能
2019/07/27 Javascript
使用Vue.js中的过滤器实现幂方求值的方法
2019/08/27 Javascript
JS跨浏览器解析XML应用过程详解
2020/10/16 Javascript
pycharm 使用心得(六)进行简单的数据库管理
2014/06/06 Python
Python学习小技巧之列表项的排序
2017/05/20 Python
Python实现两个list对应元素相减操作示例
2017/06/09 Python
pygame实现非图片按钮效果
2019/10/29 Python
找Python安装目录,设置环境路径以及在命令行运行python脚本实例
2020/03/09 Python
详解python 支持向量机(SVM)算法
2020/09/18 Python
iKRIX意大利网上商店:男女豪华服装和配件
2019/10/09 全球购物
销售文员的岗位职责
2013/11/20 职场文书
单位门卫岗位职责
2013/12/20 职场文书
新闻学专业大学生职业生涯规划范文
2014/03/02 职场文书
党员群众路线承诺书
2014/05/20 职场文书
幼儿学前班评语
2014/12/29 职场文书
Golang: 内建容器的用法
2021/05/05 Golang
Python爬虫中urllib3与urllib的区别是什么
2021/07/21 Python
javascript遍历对象的五种方式实例代码
2021/10/24 Javascript
聊聊redis-dump工具安装问题
2022/01/18 Redis