基于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 Onunload与Onbeforeunload使用小结
Dec 31 Javascript
javascrip客户端验证文件大小及文件类型并重置上传
Jan 12 Javascript
js实现上传图片之上传前预览图片
Mar 25 Javascript
JavaScript中输出标签的方法
Aug 27 Javascript
使用JavaScript 编写简单计算器
Nov 24 Javascript
JavaScript SweetAlert插件实现超酷消息警告框
Jan 28 Javascript
JavaScript中Form表单技术汇总(推荐)
Jun 26 Javascript
JS简单实现禁止访问某个页面的方法
Sep 13 Javascript
js截取字符串功能的实现方法
Sep 27 Javascript
node文字生成图片的示例代码
Oct 26 Javascript
微信小程序下拉刷新PullDownRefresh的使用方法
Nov 29 Javascript
Array.filter中如何正确使用Async
Nov 04 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
PHPMailer 中文使用说明小结
2010/01/22 PHP
PHP SPL标准库之文件操作(SplFileInfo和SplFileObject)实例
2015/05/11 PHP
PHPWind9.0手动屏蔽验证码解决后台关闭验证码但是依然显示的问题
2016/08/12 PHP
php使用变量动态创建类的对象用法示例
2017/02/06 PHP
删除PHP数组中的重复元素的实现代码
2017/04/10 PHP
判断用户的在线状态 onbeforeunload事件
2011/03/05 Javascript
JavaScript中的稀疏数组与密集数组[译]
2012/09/17 Javascript
简述AngularJS的控制器的使用
2015/06/16 Javascript
理解javascript中的MVC模式
2016/01/28 Javascript
js一维数组、多维数组和对象的混合使用方法
2016/04/03 Javascript
JS仿hao123导航页面图片轮播效果
2016/09/01 Javascript
jQuery EasyUI tree 使用拖拽时遇到的错误小结
2016/10/10 Javascript
详解jQuery中的DOM操作
2016/12/23 Javascript
Ajax异步获取html数据中包含js方法无效的解决方法
2017/02/20 Javascript
websocket+node.js实现实时聊天系统问题咨询
2017/05/17 Javascript
Vue.js数据绑定之data属性
2017/07/07 Javascript
Vue中的Vux配置指南
2017/12/08 Javascript
浅谈vue的props,data,computed变化对组件更新的影响
2018/01/16 Javascript
NodeJs实现简易WEB上传下载服务器
2019/08/10 NodeJs
Vue 同步异步存值取值实现案例
2020/08/05 Javascript
react的hooks的用法详解
2020/10/12 Javascript
[01:48]帕吉至宝加入游戏,遗迹战场现“千劫神屠”
2018/04/07 DOTA
python批量提取word内信息
2015/08/09 Python
Python中常用的8种字符串操作方法
2019/05/06 Python
Selenium 配置启动项参数的方法
2020/12/04 Python
HTML5本地存储之Web Storage详解
2016/07/04 HTML / CSS
房地产出纳岗位职责
2013/12/01 职场文书
马云的职业生涯规划之路
2014/01/01 职场文书
邮政员工辞职信
2014/01/16 职场文书
运动会四百米广播稿
2014/01/19 职场文书
我的动漫时代的创业计划书范文
2014/01/27 职场文书
函授毕业个人自我评价
2014/02/20 职场文书
中考冲刺决心书
2014/03/11 职场文书
精神文明建设汇报材料
2014/12/24 职场文书
Python 流媒体播放器的实现(基于VLC)
2021/04/28 Python
Python实现滑雪小游戏
2021/09/25 Python