2013-04-26 35 views
0

我有一個D3水流的可視化,使用戶能夠9個流域之間進行切換,並查看原始徑流資料,「高」和「低」流事件(紅&黃點),以及用於高事件所估計的閾值(紅線):使用PHP作爲在D3--切換變量柺杖必須有一個更好的辦法

http://forestecoservices.net/FESTvisualizations/HubbardBrook/streamflow.html

的數據源是PostgreSQL數據庫與本(相對標準)的配置中的數據,這裏示出as csv:

date,ws_1,ws_2,ws_3,ws_4,ws_5,ws_6,ws_7,ws_8,ws_9 1/1/2000,40,0.541,0.57,0.605,0.643,0.594,0.456,0.299,0.206 1/2/2000,0.739,0.576,0.594,0.654,0.74,0.625,0.44,0.313,0.224

唯一的問題是我無法弄清楚如何將變量名送入D3,..我發現了一些例子,但它們都具有數據設置是這樣的:

日期,流域,值

1/1/2000,ws_1,40

1/1/2000,ws_2,0.541

它可能不是很漂亮,但我知道我可以用PHP假的吧,所以我做了一個組合框調用一個PHP腳本,查詢數據庫,並吐出一個JSON,然後用由d3重繪圖。 (我還沒有弄清楚如何讓點動起來,但那是另一回事)。我知道必須有一種(更好的)方式來在d3本地執行此操作,而不必訴諸於php。

任何建議非常感謝!

史蒂夫Signell

這裏是我的源代碼:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
body { font: 12px Arial;} 

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

.grid .tick { 
stroke: lightgrey; 
opacity: 0.9; 
} 
.grid path { 
stroke-width: 0.1; 
} 

div.tooltip { 
position: absolute; 
text-align: center; 
width: 80px; 
height: 28px; 
padding: 2px; 
font: 11px sans-serif; 
background: lightsteelblue; 
border: 0px; 
border-radius: 18px; 
pointer-events: none; 
} 

</style> 

<body> 

<div id="option"> 
<select type='select' onchange='updateData(value);' style='color:red;font-size:1.3em;'> 
    <option value='ws_1' name='ws_1' selected='true' >Watershed 1</option> 
    <option value='ws_2' name='ws_2'>Watershed 2</option> 
    <option value='ws_3' name='ws_3'>Watershed 3</option> 
    <option value='ws_4' name='ws_4'>Watershed 4</option> 
    <option value='ws_5' name='ws_5'>Watershed 5</option> 
    <option value='ws_6' name='ws_6'>Watershed 6</option> 
    <option value='ws_7' name='ws_7'>Watershed 7</option> 
    <option value='ws_8' name='ws_8'>Watershed 8</option> 
    <option value='ws_9' name='ws_9'>Watershed 9</option> 
</select> 
</div> 

<script type="text/javascript" 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 = 420 - margin.top - margin.bottom; 

var parseDate = d3.time.format("%Y-%m-%d").parse; 
var formatTime = d3.time.format("%e %b %Y"); 

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").ticks(10); 

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

//create line of stream flow values 
var valueline = d3.svg.line() 
    //.interpolate("monotone") 
    .x(function(d) { return x(d.date); }) 
    .y(function(d) { return y(d.flow); }); 

//create line for hi events threshold 
var hithreshold = d3.svg.line() 
    //.interpolate("monotone") 
    .x(function(d) { return x(d.date); }) 
    .y(function(d) { return y(17.11891); }); 

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

var svg = d3.select("body") //set up svg 
    .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 + ")"); 

//Set up Grid Lines 
function make_x_axis() { 
return d3.svg.axis() 
.scale(x) 
.orient("bottom") 
.ticks(10) 
} 
function make_y_axis() { 
return d3.svg.axis() 
.scale(y) 
.orient("left") 
.ticks(5) 
} 



// Get the data 
d3.json("data/streamflow_json.php?watershed=ws_1", function(error, data)  
     { 
     data.forEach(function(d) 
      { 
      d.date = parseDate(d.date); 
      d.flow = +d.flow; 
      }); 

     // Scale the range of the data 
     x.domain(d3.extent(data, function(d) { return d.date; })); 
     y.domain([0, d3.max(data, function(d) { return d.flow; })]); 

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

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

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

     svg.append("path") // Add the hi threshold path. 
      .attr("class", "hiline") 
      .style("stroke", "red") 
      .attr("d", hithreshold(data)); 

     svg.append("text") // Chart Title 
      .attr("x", (width/2)) 
      .attr("y", 0 - (margin.top/2)) 
      .attr("text-anchor", "middle") 
      .style("font-size", "16px") 
      .style("text-decoration", "underline") 
      .text("Hubbard Brook Stream Flow"); 

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

     svg.append("text") // text label for the x axis 
      .attr("x", width/2) 
      .attr("y", height + margin.bottom) 
      .style("text-anchor", "middle") 
      .text("Date"); 

     svg.append("g") // Add the Y Axis 
      .attr("class", "y axis") 
      .call(yAxis); 

     svg.append("text") // text for Y axis 
      .attr("transform", "rotate(-90)") 
      .attr("y", 0 - margin.left) 
      .attr("x", 0 - (height/2)) 
      .attr("dy", "1em") 
      .style("text-anchor", "middle") 
      .text("Stream Flow (mm)"); 

     svg.selectAll("circle") // add value dots, sized & colored 
      .data(data) 
      .enter().append("circle") 
      //.attr("class", "dot") 
      .attr("r", function(d) { 
       if (d.flow > 17.11891) {return 3} 
       else if (d.flow < 0.01) { return 3 } 
       else {return 1} 
       ;}) 
      .style("fill", function(d) { 
       if (d.flow > 17.11891) {return "red"} 
       if (d.flow < 0.01) {return "yellow"} 
       else { return "black" } 
       ;}) 
      //.attr("d", tooltipdot(data)) 
      .attr("cx", function(d) { return x(d.date); }) 
      .attr("cy", function(d) { return y(d.flow); }) 
      .on("mouseover", function(d) { 
       tooltipdiv.transition() 
       .duration(200) 
       .style("opacity", .9); 
       tooltipdiv.html(formatTime(d.date) + "<br/>" + d.flow) 
       .style("left", (d3.event.pageX) + "px") 
       .style("top", (d3.event.pageY - 28) + "px"); 
       }) 
      .on("mouseout", function(d) { 
       tooltipdiv.transition() 
       .duration(500) 
       .style("opacity", 0); 
       }); 
}); 

function updateData(value) { 
//Get the data again 
    d3.json("data/streamflow_json.php?watershed="+value, function(error, data) 
     { 
     data.forEach(function(d) 
      { 
      d.date = parseDate(d.date); 
      d.flow = +d.flow; 
      }); 

     // Scale the range of the data again 
     x.domain(d3.extent(data, function(d) { return d.date; })); 
     y.domain([0, d3.max(data, function(d) { return d.flow; })]); 

     // Select the section we want to apply our changes to 
     var svg = d3.select("body").transition(); 
     // Make the changes 
     svg.select(".line") // change the value line 
      .duration(1750) 
      .attr("d", valueline(data)); 
     svg.select(".hiline") // change the hithreshold line 
      .duration(2750) 
      .attr("d", hithreshold(data)); 
     /*svg.select(".circle") // change the dot 
      .duration(750) 
      .attr("d", tooltipdot(data));*/ 
     svg.select(".x.axis") // change the x axis 
      .duration(2750) 
      .call(xAxis); 
     svg.select(".y.axis") // change the y axis 
      .duration(2750) 
      .call(yAxis); 
     }); 
    }; 

</script> 
</body> 
+0

所以你試圖一次加載所有的數據? JSON將是比CSV更好的選擇,因爲您可以任意嵌套。也就是說,您可以在頂層使用分水嶺名稱和每個相應數據下面的地圖。 – 2013-04-26 20:32:52

+0

嗨拉斯,我現在用的是JSON文件的CSV,而不是按照你的建議,但我只是加載整個事情一次...你暗示有更聰明的加載它呢?例如首先加載數據&ws_1,因爲這是默認值?這裏是JSON的我的第一個幾行: '代碼'[{ 「日期」: 「1990年8月24日」, 「ws_1」: 「0.194」, 「ws_2」: 「0.118」, 「ws_3」: 「0.163」,」 ws_4 「:」 0.246" , 「ws_5」: 「0.481」, 「ws_6」: 「0.310」, 「ws_7」: 「0.200」, 「ws_8」: 「0.242」, 「ws_9」: 「 - 99」},{ 「日期」: 「1990-01-01」, 「ws_1」: 「1.470」, 「ws_2」: 「2.225」, 「ws_3」: 「2.160」, 「ws_4」: 「2.139」, 「ws_5」:「2.336 」, 「ws_6」: 「2.002」, 「ws_7」: 「1.102」, 「ws_8」: 「0.739」, 「ws_9」: 「 - 99」}等 – 2013-04-29 13:37:02

+0

你當然可以在一次如果ISN加載一切」對你來說太慢了。 – 2013-04-29 15:05:23

回答

0

D3可以處理原始CSV,而不需要任何服務器端格式化:

//global variable to hold data 
var csv; 

// Get the data 
d3.csv("data/streamflow_json.php?watershed", function(error, result){ 
     csv = result; 
     var data = []; 
     csv.forEach(function(d){ 
      data.push({flow: +d['ws_1'], date: parseDate(d.date)}); 
     }); 

     //ect 
}); 

由於數據存儲在CSV變量,我們可以使用它,而無需再次查詢服務器:

function updateData(value) { 
     var data = []; 
     csv.forEach(function(d){ 
      data.push({flow: +d[value], date: parseDate(d.date)}); 
     }); 

     //ect 
} 
+0

Aaaahhhhh,那太棒了。非常感謝Adam!現在讓我們開始吧... – 2013-04-29 13:31:47

+0

我仍然不能得到點到一起,我也有這個問題,當用戶從一個組合框中選擇變量另一個條形圖transition--移動。顯然,酒吧和點需要一些不同的格式來讓他們在這個背景下更新 - 任何想法? – 2013-05-07 12:51:11

相關問題