JavaScript读取JSON文件在Canvas绘制对应城市飞机图片问题求助
代码存在的问题
- 异步请求时序问题:XMLHttpRequest是异步请求,
getJsonData执行后不会立刻返回数据,若调用该函数后立即执行drawPlanes,全局变量schedule还未完成赋值,会触发undefined报错。 - 参数传递错误:
drawPlanes中拿到的randomCity是包含城市名、坐标的完整对象,直接传给findImage和字符串做匹配,永远匹配失败。 - 方法调用缺失括号:
findImage中toLowerCase是字符串方法,你没有加执行括号,直接拼接会把函数本身转为字符串,生成的图片路径完全错误。 - 城市名匹配错误:JSON中城市名是
St. John(点后带空格),你判断条件中写的是St.John(无空格),无法匹配到对应分支,导致findImage返回undefined。 drawImage参数不符合要求:Canvas的drawImage第一个参数要求是加载完成的Image对象,你现在传入的是图片路径字符串,会直接抛出类型错误;同时绘制坐标写死为(0,0),不符合随机/对应城市坐标的需求。- 变量未声明:
schedule、canvas、ctx等变量未用let/const/var声明,会泄漏为全局变量,容易引发作用域污染问题。
修正方案
- 调整JSON获取逻辑,添加回调机制,确保数据加载完成后再执行绘制操作
- 修正参数传递逻辑,仅把城市名字符串传给
findImage - 补全
toLowerCase的执行括号,修正St. John的匹配拼写 - 新增Image对象加载逻辑,图片加载完成后再调用
drawImage绘制,坐标可根据需求选随机值或者对应城市的xCoor/yCoor - 所有变量补充声明,避免全局污染
完整修正代码
// 提前声明存储JSON数据的变量 let schedule = null // 调整后支持回调的JSON获取函数 function getJsonData(callback) { const xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (xhttp.readyState == 4 && xhttp.status == 200) { schedule = JSON.parse(xhttp.responseText); // 数据加载完成后执行传入的回调函数 if (typeof callback === 'function') callback() } } xhttp.open("GET", "capitals.json", true); xhttp.send(); } // 修正后的绘制函数 function drawPlanes() { const canvas = document.getElementById("myCanvas"); const ctx = canvas.getContext("2d"); const cityList = schedule["cities"]; const randomCity = cityList[Math.floor(Math.random() * cityList.length)]; const imgPath = findImage(randomCity.city) // 仅传递城市名字符串 // 创建Image实例,加载完成后再绘制 const planeImg = new Image() planeImg.src = imgPath planeImg.onload = function() { // 随机坐标生成逻辑,也可以直接替换为randomCity.xCoor、randomCity.yCoor使用城市对应坐标 const randomX = Math.floor(Math.random() * (canvas.width - planeImg.width)) const randomY = Math.floor(Math.random() * (canvas.height - planeImg.height)) ctx.drawImage(planeImg, randomX, randomY) } planeImg.onerror = function() { console.error('图片加载失败:', imgPath) } } // 修正后的图片路径匹配函数 function findImage(cityName) { if (["Iqaluit", "Whitehorse", "Yellowknife"].includes(cityName)) { return "img/plane.jpg"; } // 修正St. John拼写,补全toLowerCase执行括号 if (["Halifax", "Charlottetown", "Winnipeg", "Regina", "Edmonton", "Victoria", "Toronto", "St. John"].includes(cityName)) { return `img/${cityName.toLowerCase()}.jpg`; } if (["Fredericton", "Ottawa", "Quebec"].includes(cityName)) { return `img/${cityName.toLowerCase()}.png`; } // 新增默认返回,避免无匹配时返回undefined return "img/plane.jpg" } // 调用示例:确保数据加载完成后再执行绘制 getJsonData(function() { drawPlanes() // 如果需要重复生成多架飞机,可开启定时器 // setInterval(drawPlanes, 1000) })
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

