使用d3进行转换的响应折线图

时间:2016-05-11 21:43:22

标签: d3.js transition responsive

我试图动画附加的代码但没有成功。我希望轴和路径平滑地在添加新数据点之间切换。转换时间应为deltaT。我希望有人可以帮助我! (我得到它的工作,但只要图表没有响应,请参见附件js片段)

的index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Transfer setup rpi1 interface</title>
  <meta name="viewport" content="width=device-width" />
  <link rel="stylesheet" type="text/css" href="style.css">
  <script type="text/javascript" src="jquery-1.11.3.min.js"></script>
  <script src="jquery.flot.min.js"></script>
  <script src="jquery.flot.time.js"></script>
  <script src="//d3js.org/d3.v3.js" charset="utf-8"></script>
  <script type="text/javascript" src="main.js"></script>
</head>
<body>
  <div class="content">
  <header>
  <h1>Transfer Setup Rpi1</h1>
  </header>

  <div class="main">

  <h2>Control</h2>

      <fieldset>
        <legend>Temperature</legend>
        <div id="widthReader">
        <table id="cssTable">
            <tr>
                <td>

                <table id="cssTable">
                <td><label for="toggleFan">Fan</label></td>
                <td>
                <input id="toggleFan" class="cmn-toggle cmn-toggle-round" type="checkbox">
                <label for="toggleFan"></label>
                </td>
                </table>

                </td>

                <td>
                &nbsp;
                </td>
                <td>
                <label>Speed:</label> <input type="text"
                  id="fanSpeed" name="fanSpeed" value="">
                 </td>
             </tr>
             <tr>
                <td>

                <table id="cssTable">
                <td><label for="toggleHeater">Heater</label></td>
                <td>
                <input id="toggleHeater" class="cmn-toggle cmn-toggle-round" type="checkbox">
                <label for="toggleHeater"></label>
                </td>
                </table>

                </td>
                <td>
                &nbsp;
                </td>
                <td>
                <label>Setpoint:</label> <input type="text"
                  id="heaterTemp" name="heaterTemp" value="">
                </td>
            </tr>
        </table>

        </div>
      </fieldset>

             <button id="buttonSave">Save Settings</button>


    <h2>Dashboard</h2>
    <fieldset>
    <legend>Chart</legend>
        <label>Current Temperature:</label> <label id="heater_temperature">&nbsp;</label><label>°C</label>
        <div id="chart"></div>
     </fieldset>
</div>
  </div>
</body>
</html>

main.js:

var deltaT = 2500; //temperature update intervall


var Chart = (function(window,d3) {

  var svg, data, x, y, xAxis, yAxis, dim, chartWrapper, line, path, margin = {}, width, height, locator, textsize, xlabeloff, ylabeloff, xtickpadding, ytickpadding, xtickdistance, ytickdistance;

  var breakPoint = 400; //for rendering smaller fonts on mobile devices wiht small screen widths

  var n = 10,//(4)*60,//length of recording 
      duration = deltaT,//duration of deltat in msec
      now = new Date(Date.now() - duration),
      count = 0,
      data = Array.apply(null, new Array(n)).map(Number.prototype.valueOf,20);


  //called once the data is loaded
  function init() {

    //initialize scales
    x = d3.time.scale()
        .domain([now - (n+1)   * duration, now ])
        .range([0, width]);

    y = d3.scale.linear()
        .domain([0, (1.1*d3.max(data))])
        .range([height, 0]);

    line = d3.svg.line()
        .interpolate("basis")
        .x(function (d, i) { return x(now - ((n-1) - i) * duration); })
        .y(function (d, i) { return y(d); });

    //initialize axis
    x.axis = d3.svg.axis().scale(x).orient("top");
    y.axis = d3.svg.axis().scale(y).orient("right");

    x.axisT = d3.svg.axis().scale(x).orient("bottom").tickFormat("");
    y.axisR = d3.svg.axis().scale(y).orient("left").tickFormat("");

    //initialize svg
    svg = d3.select('#chart')
      .append('svg')
      .style('pointer-events', 'none');

    chartWrapper = svg
      .append('g')
      .style('pointer-events', 'all');

    //cliping mask needed because trace updates and thus moves
    clipMask = chartWrapper.append("defs").append("clipPath")
        .attr("id", "clip")
        .append("rect");

    path = chartWrapper.append('g').attr("clip-path", "url(#clip)").append('path').datum(data).classed('line', true);


    xAxis = chartWrapper.append('g')
                .attr("class", "x axis")
                .call(x.axis);

    xAxisT = chartWrapper.append('g')
                .attr("class", "x axis")
                .call(x.axisT);

    yAxis = chartWrapper.append('g')
                .attr("class", "y axis")
                .call(y.axis);

    yAxisR = chartWrapper.append('g')
                .attr("class", "y axis")
                .call(y.axisR);

    yLabel = chartWrapper.append("text")
            .attr("class", "y label")
            //.attr("transform", "rotate(-90)")
            .style("text-anchor", "middle")
            .text("Temperature (°C)");

    xLabel = chartWrapper.append("text")
        .attr("class", "x label")
        .attr("text-anchor", "middle")
        .text("Time (h:min)");

    chartWrapper.on('mousemove', onMouseMove)
                .on("mouseover", function() { locator.style("display", null); })
                .on("mouseout", function() { locator.style("display", "none"); });

    //add locator
    locator = chartWrapper.append('g')
              .attr("class", "focus");
              //.style("display", "none");


    locator.append('circle')
              .attr('r', 4);

    locator.append("text")
          .attr("x", 0)
          .style("text-anchor", "middle")
          .attr("dy", "-8");

    touchScale = d3.time.scale()
                   .domain([now - (n+1)   * duration, now ]);

    //render the chart
    render();
  }

  function render() {
    //get dimensions based on window size
    updateDimensions();

    clipMask.attr("width", width)
            .attr("height", height);

    //update x and y scales to new dimensions
    x.range([0, width]);
    y.range([height, 0]);

    touchScale.range([0,width]).clamp(true);

    //update svg elements to new dimensions
    svg
      .attr('width', width + margin.right + margin.left)
      .attr('height', height + margin.top + margin.bottom);

    chartWrapper
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    xLabel.attr("y", height + xlabeloff )
          .attr("x", ((width/2) ) );

    yLabel.attr("y", - ylabeloff )
          .attr("x", (margin.top - height / 2) )
          .attr("transform", "rotate(-90)");

    //update the axis and line
    x.axis.scale(x).tickPadding(xtickpadding);
    x.axisT.scale(x);
    y.axis.scale(y).tickPadding(ytickpadding);
    y.axisR.scale(y);

    x.axis.ticks(Math.max(width/xtickdistance, 2));
    y.axis.ticks(Math.max(height/ytickdistance, 2));
    x.axisT.ticks(Math.max(width/xtickdistance, 2));
    y.axisR.ticks(Math.max(height/ytickdistance, 2));

    xAxis.attr('transform', 'translate(0,' + height + ')').call(x.axis);
    xAxisT.call(x.axisT);
    yAxis.call(y.axis);
    yAxisR.call(y.axisR).attr('transform', 'translate(' +width +' ,0)');

    path.attr('d', line);
    updateTextStyle();
  }

  function updateTextStyle() {
    winWidth = document.getElementById("widthReader").offsetWidth;

    textsize = winWidth < breakPoint ? "48%" : "80%";
    //scale text size
    chartWrapper.selectAll("text").style("font-size", textsize);

    yAxis.call(y.axis).selectAll(".tick text").style("text-anchor", "end");
  }

  function updateDimensions(winWidth) {
    winWidth = document.getElementById("widthReader").offsetWidth;

    margin.top = winWidth < breakPoint ? 4 :10;
    margin.right = winWidth < breakPoint ? 4 : 10;
    margin.left = winWidth < breakPoint ? 26 : 48;
    margin.bottom = winWidth < breakPoint ? 22: 40;

    xlabeloff = winWidth < breakPoint ? 21 : 38;
    ylabeloff = winWidth < breakPoint ? 20 : 36;

    xtickpadding = winWidth < breakPoint ? "-17" : "-24";
    ytickpadding = winWidth < breakPoint ? "-10" : "-12";

    xtickdistance = winWidth < breakPoint ? 50 : 80;
    ytickdistance = winWidth < breakPoint ? 15 : 35;

    width = winWidth - margin.left - margin.right;
    height = .54 * width;
  }

  function onMouseMove() {
    var x0 = x.invert(d3.mouse(this)[0]),
    y0 = y.invert(d3.mouse(this)[1]);

    locator.attr("transform", "translate(" + d3.mouse(this)[0] + "," + d3.mouse(this)[1] + ")");
    locator.select("text").text(y0);
  }



 function tick() {

          // update the domains
          now = new Date();
          touchScale.domain([now - (n-1)   * duration, now ]);
          x.domain([now - (n-1) * duration, now ]);
          y.domain([0, (1.1*d3.max(data))]);


          // push a new data point onto the back
          data.push(Number($('#heater_temperature').text()));

          path.attr("d", line)
              .attr("transform", null);

          // slide the x-axis left, rescale the y-axis
          xAxisT.call(x.axisT);
          xAxis.call(x.axis);
          yAxis.call(y.axis);
          yAxisR.call(y.axisR);

           // redraw the line and slide line left
          path.attr("transform", "translate(" + (x(now - (n+0) * duration) ) + " ,0)");

          // pop the old data point off the front
          data.shift();
          updateTextStyle();

      };

  return {
    render : render,
    tick : tick,
    init : init
  }

})(window,d3);



$(document).ready(function() { 

// Start deltaT timer to call RESTful endpoint
setInterval(function() {
    $('#heater_temperature').text(Math.random()*220);
  Chart.tick();
}, deltaT);



});


$(window).load(function() { //is done after document ready

    window.addEventListener('resize', Chart.render);
    Chart.init();
    Chart.render();
});

的style.css

.x.label
{
    fill: #555;
}
.y.label
{
    fill: #555;
}
.axis path,
.axis line {
    stroke-width: 1px;
    fill: none;
    stroke: #ccc;
}

.axis text {

    fill: #555;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1px;
}

woking js:

var transition = d3.select({}).transition()
    .duration(deltaT)
    .ease("linear");


function tick() {
    transition = transition.each(function () {

        // update the domains
        now = new Date();
        x.domain([now - (n-1) * duration, now ]);
        y.domain([0, (1.1*d3.max(data))]);


        // push a new data point onto the back
        data.push(Number($('#heater_temperature').text()));



        // slide the x-axis left, rescale the y-axis
        xAxisT.call(x.axisT);
        xAxisB.call(x.axisB);
        yAxisL.call(y.axisL);
        yAxisR.call(y.axisR);

        // redraw the line, and slide it to the left
        path.attr("d", line)
            .attr("transform", " translate( " + margin.left + " ," + margin.top+" )");

        // slide the line left
        path.transition()
            .attr("transform", "translate(" + (x(now - (n+0) * duration) + margin.left) + " ," + margin.top+ ")");

        // pop the old data point off the front
        data.shift();
    });
}

1 个答案:

答案 0 :(得分:0)

我开始工作......问题是我开始使用d3.v3而不是d3.v2。这是我改变的:

function tick() {

  d3.transition().ease("linear").duration(deltaT-100).each(function() {
      // update the domains
      now = new Date(Date.now());
      markerScale.domain([now - (n-2)   * duration, now ]);
      xScale.domain([now - (n-2) * duration, now ]);
      yScale.domain([0, (1.1*d3.max(data))]);

      // slide the x-axis left, rescale the y-axis
      xAxisContT.transition().call(xAxisT);
      xAxisCont.transition().call(xAxis);
      yAxisCont.transition().call(yAxis);
      yAxisContR.transition().call(yAxisR);

      plot.attr("transform", null);

      // push a new data point onto the back
      data.push( Number($('#heater_temperature').text()) );
      path.attr("d", line);

      marker.data(data)
            .attr("cx", xValue)      
            .attr("cy", yValue)
            .attr("transform", null);

      // redraw the line and slide plot left
      plot.transition()
          .attr("transform", "translate(" + (xScale(now - (n-1) * duration) ) + " ,0)");

      // pop the old data point off the front
      data.shift();

      updateTextStyle();
  });
}