基于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仿qq界面的折叠菜单实现代码
Dec 12 Javascript
页面元素绑定jquery toggle后元素隐藏的解决方法
Mar 27 Javascript
JS动态修改iframe高度和宽度的方法
Apr 01 Javascript
Js+php实现异步拖拽上传文件
Jun 23 Javascript
百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
Feb 19 Javascript
JS Attribute属性操作详解
May 19 Javascript
jquery.guide.js新版上线操作向导镂空提示jQuery插件(推荐)
May 20 jQuery
vue2.0 自定义组件的方法(vue组件的封装)
Jun 05 Javascript
Three.js实现简单3D房间布局
Dec 30 Javascript
JavaScript数据结构与算法之检索算法示例【二分查找法、计算重复次数】
Feb 22 Javascript
VUE+node(express)实现前后端分离
Oct 13 Javascript
Vue学习笔记之计算属性与侦听器用法
Dec 07 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
PHP 数组入门教程小结
2009/05/20 PHP
php几个预定义变量$_SERVER用法小结
2014/11/07 PHP
PHPstorm快捷键(分享)
2017/07/17 PHP
JavaScript 私有成员分析
2009/01/13 Javascript
jQuery html() in Firefox (uses .innerHTML) ignores DOM changes
2010/03/05 Javascript
jquery之empty()与remove()区别说明
2010/09/10 Javascript
jquery怎样实现ajax联动框(一)
2013/03/08 Javascript
jquery给图片添加鼠标经过时的边框效果
2013/11/12 Javascript
利用NodeJS和PhantomJS抓取网站页面信息以及网站截图
2013/11/18 NodeJs
详解JavaScript的变量和数据类型
2015/11/27 Javascript
基于JavaScript实现动态创建表格和增加表格行数
2015/12/20 Javascript
详解XMLHttpRequest(一)同步请求和异步请求
2016/09/14 Javascript
vuex 的简单使用
2018/03/22 Javascript
jQuery AJAX 方法success()后台传来的4种数据详解
2018/08/08 jQuery
Vue.js实现双向数据绑定方法(表单自动赋值、表单自动取值)
2018/08/27 Javascript
linux环境下安装pyramid和新建项目的步骤
2013/11/27 Python
python数据结构链表之单向链表(实例讲解)
2017/07/25 Python
Python实现连接MySql数据库及增删改查操作详解
2019/04/16 Python
Python Django切换MySQL数据库实例详解
2019/07/16 Python
基于python traceback实现异常的获取与处理
2019/12/13 Python
使用 PyTorch 实现 MLP 并在 MNIST 数据集上验证方式
2020/01/08 Python
Python中url标签使用知识点总结
2020/01/16 Python
Python 窗体(tkinter)下拉列表框(Combobox)实例
2020/03/04 Python
Python手动或自动协程操作方法解析
2020/06/22 Python
Html5画布_动力节点Java学院整理
2017/07/13 HTML / CSS
美国在线印刷公司:PsPrint
2017/10/12 全球购物
Perfume’s Club德国官网:在线购买香水
2019/04/08 全球购物
期终自我鉴定
2014/02/17 职场文书
行政管理毕业生自荐信
2014/02/24 职场文书
技术比武方案
2014/05/19 职场文书
2016新年慰问信范文
2015/03/25 职场文书
2015年教学管理工作总结
2015/05/20 职场文书
2019年大学生学年自我鉴定!
2019/03/25 职场文书
python开发的自动化运维工具ansible详解
2021/08/07 Python
Python游戏开发实例之graphics实现AI五子棋
2021/11/01 Python