You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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声明,会泄漏为全局变量,容易引发作用域污染问题。
修正方案
  1. 调整JSON获取逻辑,添加回调机制,确保数据加载完成后再执行绘制操作
  2. 修正参数传递逻辑,仅把城市名字符串传给findImage
  3. 补全toLowerCase的执行括号,修正St. John的匹配拼写
  4. 新增Image对象加载逻辑,图片加载完成后再调用drawImage绘制,坐标可根据需求选随机值或者对应城市的xCoor/yCoor
  5. 所有变量补充声明,避免全局污染

完整修正代码

// 提前声明存储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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 17:15:05