2013-08-31 57 views
1

我寫了一個小型網頁,它創建了一個包含24小時內警報分佈圖的圖表,其中警報計數是一個變量,用於驅動在此期間發送多少警報。如何用html表單中的數據重繪我的d3.js圖表​​?

之後,我寫了一個小的形式,將有報警計數變量在輸入字段

<input id="alarm_count_input" type="number"/>

現在我想能夠重新繪製d3.js圖沒有頁面重載,同時報警統計用戶使用表單/輸入字段進行提交。

的jsfiddle:http://jsfiddle.net/L42LU/

代碼:

<script type="text/javascript"> 
$(function(){ 

........ 

function createDataForD3(alarm_cnt, array) { 
    var data = []; 
    for(var i = 0, n=array.length; i< n; i++) 
    { 
     data.push({ "hour": i, 
        "alarms": getRatioForHour(i, array) * alarm_cnt 
        }); 
    } 
    return data; 
} 

var schedule = [1, 1, 1, 1, 4, 1, 1, 3, 2, 3, 4, 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1]; 
var alarm_count = 1000; 

var margin = {top: 20, right: 20, bottom: 30, left: 50}, 
    width = 0.85 * document.width - margin.left - margin.right, 
    height = 0.9 * document.height - margin.top - margin.bottom; 

var x_extent = [-0.5, 23.5]; 
var y_extent = [0, Math.round(
        getMaxAlarmCountForHourInArray(alarm_count, schedule)[1] * 1.2) ]; 

var x_scale = d3.scale.linear() 
    .range([0, width]) 
    .domain(x_extent); 

var y_scale = d3.scale.linear() 
    .range([ height, 0]) 
    .domain(y_extent); 


var data = createDataForD3(alarm_count , schedule); 

var xAxis = d3.svg.axis() 
    .scale(x_scale) 
    .orient("bottom") 
    .ticks(24); 

var yAxis = d3.svg.axis() 
    .scale(y_scale) 
    .orient("left"); 

var line = d3.svg.line() 
    .x(function(d) { return x_scale(d.hour) ; }) 
    .y(function(d) { return y_scale(Math.round(d.alarms)) ; }); 

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


    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis) 
    .append("text") 
     .attr("y", margin.bottom) 
     .attr("x", (width)/2) 
     .text("Hour"); 

    svg.append("g") 
     .classed("x grid ", true) 
     .attr("transform", "translate(0,"+height+")") 
     .call(xAxis 
      .tickSize(-height,0,0) 
      .tickFormat("") 
    ); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis) 
    .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 8) 
     .attr("x", -20) 
     .attr("dy", ".71em") 
     .style("text-anchor", "end") 
     .text("Alarms per hour"); 

    svg.append("g") 
     .classed("y grid", true) 
     .call(yAxis 
      .tickSize(-width,0,0) 
      .tickFormat("") 
    ) 

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

    svg.append("g") 
     .selectAll("circle") 
     .data(data) 
     .enter() 
     .append("circle"); 

    d3.selectAll("circle") 
     .attr("cx", function(d){ return x_scale(d.hour); }) 
     .attr("cy", function(d){ return y_scale(d.alarms); }) 
     .attr("r", 6); 

    $("#alarm_count_input").val(alarm_count); 
}); 
</script> 
<form id="form1" role="form" onSubmit="return false;"> 
    <div class=form-group"> 
     <label for="alarm_count_input" >Alarm count</label><br> 
     <input id="alarm_count_input" class="form-control" type="number" placeholder="Alarm count" min="0" max="999999" step="1" /> 
    </div> 
</form> 
</body> 
+0

jsfiddle會很好。 :) – Yogesh

+0

@Yogesh我已添加它:) – Patryk

回答

1

Here,是用一個更新代碼的jsfiddle。我將依賴於警報計數的代碼的所有部分移動到每次更改警報計數值時調用的獨立函數。

function render(){  
    yAxis = yAxis.tickFormat(d3.format(",")); 
    y_extent = [0, Math.round(
        getMaxAlarmCountForHourInArray(alarm_count, schedule)[1] * 1.2) ]; 

    y_scale.domain(y_extent); 

    var data = createDataForD3(alarm_count , schedule); 


    svg.select("g.y.axis").call(yAxis); 

    gridAxis.tickFormat(""); 
    svg.select("g.y.grid").call(gridAxis); 

    var lineData = svg.selectAll(".line").data([data]); 

    lineData.enter().append("path") 
     .attr("d", line(data)) 
    .attr("class", "line"); 

    lineData.exit().remove(); 

    var svgData = svg.selectAll("circle") 
     .data(data); 

    var svgEnter = svgData.enter().append("circle") 
     .attr("cx", function(d){ return x_scale(d.hour); }) 
     .attr("cy", function(d){ return y_scale(d.alarms); }) 
     .attr("r", 6); 

    svgData.exit().remove(); 

    } 
render(); 
+0

好的非常感謝。雖然你提供的小提琴不能按需要工作。你也可以看看我的解決方案。你能解釋一下你的代碼嗎?尤其是'var lineData = ...'之後的行? – Patryk

+0

@Patryk:你能解釋爲什麼我的解決方案不能按需要工作嗎?什麼不起作用?我正在選擇當前行,然後根據數據進行更新。您可以在D3.js wiki – Yogesh

+0

上閱讀有關enter()和exit()的更多信息當我啓動您的小提琴時,音階是恆定的(從0.1到1.0),並且鬧鈴計數變化沒有任何變化(並按Enter鍵) – Patryk

0

我發佈我的解決方案,以及(有人可能會覺得它有用)。我對Yogesh做了類似的方法,但我明確地刪除並添加了元素(不知道這是否是正確的方法 - 也許有人會指出一些錯誤給我)。

function drawY(alarm_cnt, array) { 

    d3.selectAll(".circles").remove(); 
    d3.selectAll(".y").remove(); 
    d3.selectAll(".line").remove(); 

    var data = createDataForD3(alarm_cnt , array); 

    var y_extent = [0, Math.round(
        getMaxAlarmCountForHourInArray(alarm_cnt, array)[1] * 1.2) ]; 

    var y_scale = d3.scale.linear() 
     .range([ height, 0]) 
     .domain(y_extent); 

    var yAxis = d3.svg.axis() 
     .scale(y_scale) 
     .orient("left"); 

    var line = d3.svg.line() 
     .x(function(d) { return x_scale(d.hour) ; }) 
     .y(function(d) { return y_scale(Math.round(d.alarms)) ; }); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis) 
    .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 8) 
     .attr("x", -20) 
     .attr("dy", ".71em") 
     .style("text-anchor", "end") 
     .text("Alarms per hour"); 

    svg.append("g") 
     .classed("y grid", true) 
     .call(yAxis 
      .tickSize(-width,0,0) 
      .tickFormat("") 
    ) 

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

    svg.append("g") 
     .attr("class", "circles") 
     .selectAll("circle") 
     .data(data) 
     .enter() 
     .append("circle"); 

    d3.selectAll("circle") 
     .attr("cx", function(d){ return x_scale(d.hour); }) 
     .attr("cy", function(d){ return y_scale(Math.round(d.alarms)); }) 
     .attr("r", 6); 
} 

var margin = {top: 20, right: 20, bottom: 30, left: 70}, 
    width = 0.85 * document.width - margin.left - margin.right, 
    height = 0.9 * document.height - margin.top - margin.bottom; 

var schedule = [1, 2, 1, 2, 2, 2, 1, 4, 4, 3, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; 
var alarm_count = 1000; 

var data = createDataForD3(alarm_count , schedule); 

var x_extent = [-0.8, 23.5]; 

var x_scale = d3.scale.linear() 
    .range([0, width]) 
    .domain(x_extent); 

var xAxis = d3.svg.axis() 
    .scale(x_scale) 
    .orient("bottom") 
    .ticks(24); 


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


    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis) 
    .append("text") 
     .attr("y", margin.bottom) 
     .attr("x", (width)/2) 
     .text("Hour"); 

    svg.append("g") 
     .classed("x grid ", true) 
     .attr("transform", "translate(0,"+height+")") 
     .call(xAxis 
      .tickSize(-height,0,0) 
      .tickFormat("") 
    ); 


    drawY(alarm_count, schedule); 
    $("#alarm_count_input").val(alarm_count); 

    $("#alarm_count_input").change(function(){ 
     drawY($("#alarm_count_input").val(), schedule); 
    }); 
});