如何在按下按钮时更新D3.js中的图形?

问题描述:

我正在绘制一张显示温度,日期和时间的图表。到目前为止,所有工作都很好,但为了从我的MySQL数据库中获取新值,以便完全刷新我的页面。 我希望能够在不按刷新按钮的情况下更新图形。 这是代码:如何在按下按钮时更新D3.js中的图形?

<?php require($_SERVER['DOCUMENT_ROOT'] . '/assets/php/getTemp.php'); ?> 

<!DOCTYPE html> 
<meta charset="utf-8"> 

<head> 
    <title>RPi</title> 
</head> 

<style> 

div.tooltip { 
    position: absolute; 
    text-align: center; 
    width: 120px; 
    height: 28px; 
    padding: 3px; 
    font: 12px sans-serif; 
    background: lightgrey; 
    border: 0px; 
    border-radius: 8px; 
    pointer-events: none; 
} 


body { font: 14px Arial;} 

path { 
    stroke: #FF8C00; 
    stroke-width: 3; 
    fill: none; 
} 

.axis path, 
.axis line { 
    fill: none; 
    stroke: black; 
    stroke-width: 2; 
    shape-rendering: crispEdges; 
} 

.grid .tick { 
    stroke: grey; 
    stroke-opacity: 0.3; 
    shape-rendering: geometricPrecision; 
} 
.grid path { 
      stroke-width: 0; 
} 


</style> 
<body> 


<div id="option"> 
    <input name="updateButton" 
      type="button" 
      value="Update" 
      onclick="updateData()" 
    /> 
</div> 


<!-- load the d3.js library --> 
<script src="http://d3js.org/d3.v3.min.js"></script> 

<script> 


var margin = {top: 30, right: 20, bottom: 30, left: 50}, 
    width = 800 - margin.left - margin.right, 
    height = 270 - margin.top - margin.bottom; 

var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse; 
var formatTime = d3.time.format("%d-%m-%Y %H:%M:%S"); 

var x = d3.time.scale().range([0, width]); 
var y = d3.scale.linear().range([height, 0]); 


var xAxis = d3.svg.axis().scale(x) 
    .orient("bottom"); 

var yAxis = d3.svg.axis().scale(y) 
    .orient("left").ticks(5); 

var valueline = d3.svg.line() 
    .interpolate("basis") 
    .x(function(d) { return x(d.datetime); }) 
    .y(function(d) { return y(d.temperature); }); 

var div = d3.select("body").append("div") 
    .attr("class", "tooltip") 
    .style("opacity", 0); 

var svg = d3.select("body") 
    .append("svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
     .attr("transform", 
       "translate(" + margin.left + "," + margin.top + ")"); 

function make_x_axis() { 
    return d3.svg.axis() 
     .scale(x) 
     .orient("bottom") 
     .ticks(5) 
} 

function make_y_axis() { 
    return d3.svg.axis() 
     .scale(y) 
     .orient("left") 
     .ticks(5) 
} 

<?php echo "data=".$json_data.";" ?> 
data.forEach(function(d) { 
d.datetime = parseDate(d.datetime); 
d.temperature = +d.temperature; 
}); 

x.domain(d3.extent(data, function(d) { return d.datetime; })); 
y.domain([0, d3.max(data, function(d) { return d.temperature; })]); 


svg.append("path") 
.attr("class", "line") 
.attr("d", valueline(data)); 


svg.selectAll("dot") 
    .data(data) 
.enter().append("circle") 
    .attr("r", 4) 
    .attr("cx", function(d) { return x(d.datetime); }) 
    .attr("cy", function(d) { return y(d.temperature); }) 
    .on("mouseover", function(d) { 
     div.transition() 
      .duration(200) 
      .style("opacity", 1); 
     div.html(formatTime(d.datetime) + "<br/>" + d.temperature + " &#8451") 
      .style("left", (d3.event.pageX + 16) + "px") 
      .style("top", (d3.event.pageY + 16) + "px") 
     .style("position", "absolute"); 
     }) 
    .on("mouseout", function(d) { 
     div.transition() 
      .duration(50) 
      .style("opacity", 0); 
}); 

svg.append("g") 
    .attr("class", "grid") 
    .attr("transform", "translate(0," + height + ")") 
    .call(make_x_axis() 
     .tickSize(-height, 0, 0) 
     .tickFormat("") 
) 

svg.append("g") 
    .attr("class", "grid") 
    .call(make_y_axis() 
     .tickSize(-width, 0, 0) 
     .tickFormat("") 
) 

svg.append("g") 
.attr("class", "x axis") 
.attr("transform", "translate(0," + height + ")") 
.call(xAxis); 

svg.append("g") 
.attr("class", "y axis") 
.call(yAxis); 


</script> 
</body> 

我试着这样做:

function updateData() { 

//d3.json("/assets/php/getTemp.php", function(error, data) { 
     <?php echo "data=".$json_data.";" ?> 
     data.forEach(function(d) { 
     d3.select("body").selectAll("svg") 
     d.datetime = parseDate(d.datetime); 
     d.temperature = +d.temperature; 
}); 

x.domain(d3.extent(data, function(d) { return d.datetime; })); 
y.domain([0, d3.max(data, function(d) { return d.temperature; })]); 

var svg = d3.select("body").transition(); 

    svg.select(".line") 
     .duration(750) 
     .attr("d", valueline(data)); 
    svg.select(".x.axis") 
     .duration(750) 
     .call(xAxis); 
    svg.select(".y.axis") 
     .duration(750) 
     .call(yAxis); 
}; 

但没有任何反应,甚至不是一个错误。

如果它的事项,这是用来获取温度和时间形式的MySQL的PHP​​代码:

<?php 
$hostname = 'localhost'; 
$username = 'root'; 
$password = 'admin'; 

try { 
    $dbh = new PDO("mysql:host=$hostname;dbname=temp_database", 
           $username, $password); 


    $sth = $dbh->prepare(" 
     SELECT `datetime`, `temperature` FROM `tempLog` 
    "); 
    $sth->execute(); 


    $result = $sth->fetchAll(PDO::FETCH_ASSOC); 


    $dbh = null; 

} 
catch(PDOException $e) 
    { 
     echo $e->getMessage(); 
    } 

$json_data = json_encode($result); 
?> 

我需要做什么?

+0

看起来是对我的。你可以用一个你正在使用的数据类型的例子把它粘在一个jsfiddle中吗? – BHouwens

+0

当然:https://jsfiddle.net/zzmoL7Le/4/我希望链接是好的。 –

+0

问题似乎是您在'updateData'函数中对数据执行的格式。如果您在代码运行时注释该部分 – BHouwens

查看使用d3.json函数。这可以让你从php脚本获取json,而无需从头重新加载整个页面。这是AJAX的东西,但d3 helper函数隐藏细节。

https://github.com/mbostock/d3/wiki/Requests

PS。请记住,这将是一个异步调用,所以看到这里接受的答案还有: JSON output from PHP using d3.json


至于为什么它没有目前的工作,我的预感*,但没有足够的信息来确认,是那有没有变化,因为它总是相同的数据,所以不会有任何变化

<?php echo "data=".$json_data.";" ?> 

该行^^^在updateData在一开始被评估一次,然后整体功能被砰的一声扔到到JavaScript的境界。然而,很多时候,如果调用updateData,那么以前生成的javascript变量(data={some_json})不会在没有重新加载生成updateData的php页面的情况下更改,即使您调用生成服务器端变量的数据库相关的php。

*可能是废话,但上面的位仍然是正确的