1

我编写了一个小网页,创建了一个图表,其中包含 24 小时内的警报分布,警报计数是一个变量,驱动在此期间将发送多少警报。

之后,我编写了一个小表单,在输入字段中包含警报计数变量

<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>
4

2 回答 2

1

在这里,是一个带有更新代码的 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();
于 2013-08-31T15:14:24.000 回答
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);
    });
});
于 2013-08-31T17:03:04.307 回答