从 JSON 文件读取数据并将其显示在 Canvas 上时遇到问题

Trouble reading data from JSON file and displaying it on Canvas

背景

(JS 新手,第一次使用 canvas)

我正在尝试从 https://analytics.usa.gov/ 读取 JSON 文件并使用 canvas 显示它。我只想在下拉列表中填充前 8 条记录。

我成功地在我的机器上本地获取了该文件的转储。代码在这里 (https://jsfiddle.net/uh8jamdo/)

我想做的是: 1)数据中的页面标题应填充在下拉列表中 2) 当用户选择一个并点击提交时。我想显示页面标题 URL 和该特定页面标题的活跃用户。

以下是我的尝试。有人可以指导我吗?我已经编写代码来显示 canvas、文本和更新数据。

window.onload = function() {
  var button = document.getElementById("previewButton");
  button.onclick = previewHandler;


}

function previewHandler() {
  var canvas = document.getElementById("analytics");
  var context = canvas.getContext("2d");

  drawText(canvas, context);

}

// draws all the text, including the Analytics
function drawText(canvas, context) {

  context.font = "50px serif";
  context.fillStyle = "black";
  context.font = "bold 1em sans-serif";
  context.textAlign = "left";
  context.fillText("No of People online on Govt Websites", 20, 40);


  // draw the analytics!
  selectObj = document.getElementById("site");
  index = selectObj.selectedIndex;
  var site = selectObj[index].value;
  context.font = "italic 1.2em serif";
  context.fillText(site, 30, 100);



}





function updateAnalytics(site) {
  var siteSelection = document.getElementById("site");

  // add all data to the site dropdown
  for (var i = 0; i < site.length; i++) {
    site = site[i];

    // create option
    var option = document.createElement("option");
    option.text = site.text;

    // strip any quotes out of the site so they don't mess up our option
    option.value = site.text.replace("\"", "'");

    // add option to select
    siteSelection.options.add(option);
  }
  // make sure the top tweet is selected
  siteSelection.selectedIndex = 0;
}
canvas {
  border: 1px solid black;
}
<canvas width="600" height="200" id="analytics">
  <p>You need canvas to see the Analytics Data</p>
  <p>This example requires a browser that supports the HTML5 Canvas feature.</p>
</canvas>

<p>
  <label for="site">Pick a Site</label>
  <select id="site"></select>
</p>
<p>
  <input type="button" id="previewButton" value="Preview">
</p>
</form>
</br>
<script src="https://analytics.usa.gov/data/live/top-pages-realtime.json">
</script>

你基本上已经知道了,但是有很多奇怪的东西,我想我可以修改你的代码,你可以研究我所做的。我发现的几个问题:

  • 我们可以通过 XMLHttpRequest 获取 URL 的内容,而不是将脚本硬编码到 html 文档中。您将 运行 陷入一些时间问题。
  • 这些天没有真正需要使用 formsubmit。现代网页设计通常会在客户端维护一个有状态的对象,并使用上面的 XMLHttpRequest 之类的东西与各种后端进行通信。通过这样做,我们不必每次从服务器收到响应时都重新绘制页面。当用户单击提交时,您可以捕获该事件,但您需要遵循一个协议(处理程序中的 return false)以防止页面重新加载并破坏用户的选择。用户将看不到您的 canvas,因为您每次都会重新加载新的 canvas。他们也不会看到他们的选择,因为您将在每次提交后重置它。
  • 我们不需要在设置 javascript 值时去掉引号。首先,因为这些东西通常会为您转义,但其次,因为在您的情况下,只存储选择的索引实际上更容易。你真的根本不需要价值。如果您使用此修改后的值作为键,可能会导致问题。
  • 尽量减少全局变量的数量。 Javascript 对 closure 有很好的支持,这是一个强大的编程结构,允许我们限制变量的可见性等。这将使在调试器中测试您的代码变得容易得多,因为所有内容都将集中在一个地方。 (更多的是风格而不是实际问题)。
  • 如果您打算重新使用它,请务必清除您的 canvas。连续调用 fillText 会破坏之前的文本。
  • 我们可以探索许多其他内容,但希望这能帮助您入门。

此外,您无需借助外部库即可完成所有这些工作,这很棒,但您也应该检查一下它们——javascript 可以做一些非常令人兴奋的事情。我推荐D3.js

最后,这里是修改后的 javascript,我相信它会完成您指定的事情,并且考虑了我给出的建议:

(你可以在这里玩jsfiddle: https://jsfiddle.net/dancingplatypus/L92fq305/6/)

var site_analytics = {
    run: function () {
        var ANALYTICS_SITE = 'https://analytics.usa.gov/data/live/top-pages-realtime.json';
        var elem_select = document.getElementById("site");
        var elem_title = document.getElementById("site_title");
        var elem_preview = document.getElementById("previewButton");
        var site_data = null;

        elem_preview.onclick = render_selection;
        elem_select.onchange = render_selection;

        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function () {
            console.log('heya');
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                site_data = JSON.parse(xmlhttp.responseText);
                sync_selector();
            }
        }
        xmlhttp.open("GET", ANALYTICS_SITE, true);
        xmlhttp.send();

        function sync_selector() {
            console.log('boyo');
            elem_select.innerHtml = null;
            if (site_data) {
                for (var loop = 0; loop < Math.min(8, site_data.data.length); loop++) {
                    var item = site_data.data[loop];
                    var option = document.createElement('option');
                    option.text = item.page_title;
                    option.value = loop;
                    elem_select.add(option);
                }
            }
            selected_index = (site_data.data.length > 0) ? 0 : null;
            render_selection();
        }

        function render_selection() {
            var index = elem_select.selectedIndex;
            var item = site_data ? site_data.data[index] : null;

            elem_title.innerText = item ? item.page_title : 'n/a';
            var canvas = document.getElementById("analytics");
            var context = canvas.getContext("2d");
            context.clearRect(0, 0, canvas.width, canvas.height);
            drawText(item, canvas, context);
        };

        // draws all the text, including the Analytics
        function drawText(item, canvas, context) {
            context.font = "50px serif";
            context.fillStyle = "black";
            context.font = "bold 1em sans-serif";
            context.textAlign = "left";
            context.fillText("No of People online on Govt Websites", 20, 40);

            // draw the analytics!
            context.font = "italic 1.2em serif";
            context.fillText(item ? item.active_visitors : '', 30, 100);
        }
    }
};

window.onload = function () {
    site_analytics.run();
};