简体   繁体   English

d3.js白天小时热图在服务器重新启动时加载,但在刷新页面时消失

[英]d3.js Day Hour Heatmap loads on server restart, but disappears when the page is refreshed

I have a very weird situation on my hands and I'm not sure how to fix it. 我手上的情况很奇怪,我不确定如何解决。 I will say that I am new to Angular.js and D3.js so if you see a newb mistake, it's probably not a typo, it's me having done something wrong. 我会说我是Angular.js和D3.js的新手,所以,如果您看到newb错误,可能不是错字,那是我做错了什么。

Anyways - I'm using Eclipse with m2e and tomcat plugins and running straight from the IDE. 无论如何-我正在使用带有m2e和tomcat插件的Eclipse,并直接从IDE运行。 I'm trying to load a day/hour heatmap with example code I found here: blocks.org 我正在尝试使用在这里找到的示例代码加载日/小时热图: blocks.org

I made one small change, where instead of the d3.tsv call, I'm using d3.json and implementing a REST call to retrieve the json. 我做了一个小小的更改,而不是d3.tsv调用,而是使用d3.json并实现了REST调用来检索json。 The interesting part here is that whenever I restart the server and load the page, I see the heatmap as it is supposed to appear. 这里有趣的部分是,每当我重新启动服务器并加载页面时,我都会看到应该显示的热图。 However, if I refresh the page, it disappears. 但是,如果刷新页面,它将消失。 If I load the page in a new tab, it also will not appear. 如果我在新标签页中加载页面,则该页面也不会出现。

Strangely enough it does appear when I close and re-open the browser, but then disappears again later with refreshes and new tabs. 奇怪的是,当我关闭并重新打开浏览器时,它确实出现了,但随后在刷新和新选项卡后又消失了。

Every time I refresh the page I can see the REST call being correctly called in the eclipse console. 每次刷新页面时,我都可以看到Eclipse控制台中正确调用了REST调用。 I can also see the JSON data appearing correctly in the javascript console on my browser. 我还可以在浏览器的javascript控制台中看到JSON数据正确显示。 These things all happen correctly regardless of whether or not the heatmap appears. 无论是否显示热图,这些事情都可以正确发生。

Below is some of my code that I think will be relevant, feel free to ask for more snippets if necessary. 以下是我认为与之相关的一些代码,如有必要,请随时请求更多代码段。

REST Controller method REST控制器方法

@RequestMapping(value="/heatmap", method=RequestMethod.GET, produces={"application/json"})
public @ResponseBody String getHeatMapValues(){
     return heatMapValues;
}

index.html index.html

//Assume all standard javascript imports here are correct (the thing does work correctly at least once, and I'd have bigger errors anyways
<body>
     <div class="panel panel-default" ng-app="Hello" ng-controller="myCtrl">
          <div class="panel-heading">
               <h2 class="panel-title">VISUALIZATIONS</h2>
          </div>
          <div class="panel-body">
              <div class="col-lg-1"></div>
              <div role="tabpanel" class="col-lg-10" style="border: 2px solid black">
                  <ul class="nav nav-tabs" role="tablist">
                       <li role="presentation" ng-repeat="tab in tabs" ng-click=selectTab($index) ng-class="{'active':selectedTab == $index}">
                            <a data-target="#tab" aria-controls="home" role="tab" data-toggle="tab">{{tab.id}}</a>
                       </li>
                  </ul>
                  <div class="tab-content">
                       <div role="tabpanel" class="tab-pane active" id="tab" ng-include="tabs[selectedTab].template">
                       </div> 
                  </div>
              </div>
             <div class="col-lg-1"></div>
          </div>
      </div>
</body>

script.js (yes, I'll break up the javascript code appropriately later, now i just want everything to work) script.js(是的,我稍后会适当地分解javascript代码,现在我只希望一切正常)

var app = angular.module('Hello', ['ui.bootstrap']);
app.controller('myCtrl', function Hello($scope, $http) {
     $scope.tabs = [{id:"Main",template: "partials/main.html"},{id: "Clustering",template: "partials/clustering.html"}];
     $scope.selectedTab=0;
     $scope.selectTab = function(index){
          $scope.selectedTab = index;
     }
var margin = { top: 50, right: 0, bottom: 100, left: 30 },
      width = 960 - margin.left - margin.right,
      height = 430 - margin.top - margin.bottom,
      gridSize = Math.floor(width / 24),
      legendElementWidth = gridSize*2,
      buckets = 9,
      colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9]
      days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
      times = ["1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a", "12a", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p", "12p"];


  d3.json("/heatmap",
    function(error, data) {
      var colorScale = d3.scale.quantile()
          .domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })])
          .range(colors);

      var svg = d3.select("#chart").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 + ")");

      var dayLabels = svg.selectAll(".dayLabel")
          .data(days)
          .enter().append("text")
            .text(function (d) { return d; })
            .attr("x", 0)
            .attr("y", function (d, i) { return i * gridSize; })
            .style("text-anchor", "end")
            .attr("transform", "translate(-6," + gridSize / 1.5 + ")")
            .attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });

      var timeLabels = svg.selectAll(".timeLabel")
          .data(times)
          .enter().append("text")
            .text(function(d) { return d; })
            .attr("x", function(d, i) { return i * gridSize; })
            .attr("y", 0)
            .style("text-anchor", "middle")
            .attr("transform", "translate(" + gridSize / 2 + ", -6)")
            .attr("class", function(d, i) { return ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });

      var heatMap = svg.selectAll(".hour")
          .data(data)
          .enter().append("rect")
          .attr("x", function(d) { return (d.hour - 1) * gridSize; })
          .attr("y", function(d) { return (d.day - 1) * gridSize; })
          .attr("rx", 4)
          .attr("ry", 4)
          .attr("class", "hour bordered")
          .attr("width", gridSize)
          .attr("height", gridSize)
          .style("fill", colors[0]);

      heatMap.transition().duration(1000)
          .style("fill", function(d) { return colorScale(d.value); });

      heatMap.append("title").text(function(d) { return d.value; });

      var legend = svg.selectAll(".legend")
          .data([0].concat(colorScale.quantiles()), function(d) { return d; })
          .enter().append("g")
          .attr("class", "legend");

      legend.append("rect")
        .attr("x", function(d, i) { return legendElementWidth * i; })
        .attr("y", height)
        .attr("width", legendElementWidth)
        .attr("height", gridSize / 2)
        .style("fill", function(d, i) { return colors[i]; });

      legend.append("text")
        .attr("class", "mono")
        .text(function(d) { return "≥ " + Math.round(d); })
        .attr("x", function(d, i) { return legendElementWidth * i; })
        .attr("y", height + gridSize);
  });
}

partials/main.html partials / main.html

<div id="chart"></div>

partials/clustering.html partials / clustering.html

<b>hi there</b>

I found out the answer. 我找到了答案。 I was thinking this was an issue of state within D3. 我当时以为这是D3中的状态问题。 In reality the answer is much simpler. 实际上,答案要简单得多。

Because I was only testing the chart, I put the d3 code inside my angular controller that will execute on startup. 因为我只是测试图表,所以将d3代码放入将在启动时执行的角度控制器中。 This was causing a race condition between the d3 script (which was searching for the div with id="chart") and the DOM which was still loading html. 这导致了d3脚本(正在使用id =“ chart”搜索div)与仍在加载html的DOM之间的竞争。

I changed my app controller to contain this: 我更改了应用程序控制器以包含以下内容:

$scope.init = function(){
    //d3 chart script
}

I also changed main.html to look like this: 我还更改了main.html,使其看起来像这样:

<div id="chart" data-ng-init="init()"></div>

Now it loads consistently every time! 现在,每次都始终如一地加载!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM