基于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不同页面传值的改进版
Sep 30 Javascript
JavaScript 学习笔记之一jQuery写法图片等比缩放以及预加载
Jun 28 Javascript
jquery插件ajaxupload实现文件上传操作
Dec 09 Javascript
关于Iframe父页面与子页面之间的相互调用
Nov 22 Javascript
简单理解js的prototype属性及使用
Dec 07 Javascript
Bootstrap警告(Alerts)的实现方法
Mar 22 Javascript
Scala解析Json字符串的实例详解
Oct 11 Javascript
vue打包相关细节整理(小结)
Sep 28 Javascript
jQuery实现动态添加和删除input框实例代码
Mar 26 jQuery
浅析vue-router实现原理及两种模式
Feb 11 Javascript
echarts.js 动态生成多个图表 使用vue封装组件操作
Jul 19 Javascript
NestJs使用Mongoose对MongoDB操作的方法
Feb 22 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
PHP脚本数据库功能详解(下)
2006/10/09 PHP
第二章 PHP入门基础之php代码写法
2011/12/30 PHP
解析php通过cookies获取远程网页的指定代码
2013/06/25 PHP
PHP CURL 多线程操作代码实例
2015/05/13 PHP
TP5.0框架实现无限极回复功能的方法分析
2019/05/04 PHP
laravel 解决groupBy时出现的错误 isn't in Group By问题
2019/10/17 PHP
DOM相关内容速查手册
2007/02/07 Javascript
jQuery获取地址栏参数插件(模仿C#)
2010/10/26 Javascript
javascript showModalDialog 内跳转页面的问题
2010/11/25 Javascript
JS获取CSS样式(style/getComputedStyle/currentStyle)
2016/01/19 Javascript
jquery实现点击弹出可放大居中及关闭的对话框(附demo源码下载)
2016/05/10 Javascript
JS中使用正则表达式g模式和非g模式的区别
2017/04/01 Javascript
详解angularjs中如何实现控制器和指令之间交互
2017/05/31 Javascript
如何快速解决JS或Jquery ajax异步跨域的问题
2018/01/08 jQuery
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
2019/04/08 Javascript
vue结合el-upload实现腾讯云视频上传功能
2020/07/01 Javascript
[37:45]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第二场 12.09
2020/12/11 DOTA
python通过yield实现数组全排列的方法
2015/03/18 Python
python下载文件记录黑名单的实现代码
2017/10/24 Python
python入门前的第一课 python怎样入门
2018/03/06 Python
python3实现字符串的全排列的方法(无重复字符)
2018/07/07 Python
python3使用腾讯企业邮箱发送邮件的实例
2019/06/28 Python
Java文件与类动手动脑实例详解
2019/11/10 Python
python循环输出三角形图案的例子
2019/11/22 Python
python socket通信编程实现文件上传代码实例
2019/12/14 Python
Python直接赋值及深浅拷贝原理详解
2020/09/05 Python
HTML5中的autofocus(自动聚焦)属性介绍
2014/04/23 HTML / CSS
墨西哥网上购物:Linio墨西哥
2016/10/20 全球购物
捷克领先的户外服装及配件市场零售商:ALPINE PRO
2018/01/09 全球购物
洲际酒店集团英国官网:IHG英国
2019/07/10 全球购物
药学专业大专生的自我评价
2013/12/12 职场文书
中学生关于梦想的演讲稿
2014/08/22 职场文书
导游词之张家口
2019/12/13 职场文书
《正面管教》读后有感:和善而坚定的旅程
2019/12/19 职场文书
深入浅析Redis 集群伸缩原理
2021/05/15 Redis
使用Redis实现实时排行榜功能
2021/07/02 Redis