从 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 文档中。您将 运行 陷入一些时间问题。
- 这些天没有真正需要使用
form
和 submit
。现代网页设计通常会在客户端维护一个有状态的对象,并使用上面的 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();
};
背景
(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 文档中。您将 运行 陷入一些时间问题。 - 这些天没有真正需要使用
form
和submit
。现代网页设计通常会在客户端维护一个有状态的对象,并使用上面的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();
};