javascript - 使 JavaScript 事件处理程序依赖于 AJAX 响应

标签 javascript ajax canvas addeventlistener

这里是 JavaScript 初学者 :) 摘要: 如何使事件监听器依赖于 AJAX 调用的结果?如果监听器是在调用之后添加的,那么它将在每个调用之后添加,从而累积监听器。如果我在调用之前执行此操作,如何将调用结果传递给它?监听器似乎不接受用户定义的参数。

详细信息:我正在尝试编写一个网络照片查看器,其中将在照片上标记面孔。要在照片之间切换,我想使用 AJAX。我的PHP脚本以JSON字符串的形式返回图片文件的名称和面的坐标(x,y,半径),例如

{"filename":"im1.jpg","faces":[{"x":129,"y":260,"radius":40},{"x":232,"y":297,"radius":40}]} 

当鼠标悬停在照片上时,我想根据面孔在 Canvas 上绘制圆圈。因此,我为 mouseover 事件创建了一个监听器。问题是,如果我在 AJAX 调用后添加监听器, Canvas 将获得多个监听器并继续从之前的照片中绘制圆圈。所以看起来处理程序需要提前定义。但后来我很难将 AJAX 响应传递给它。我怎样才能实现它?

到目前为止,我的 HTML 代码如下所示:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<canvas id="canvas" width="100" height="600"
    style="background-size: 100% 100%; border: 1px solid #FF0000;"></canvas>
<script>
    var image = new Image();
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");

    canvas.addEventListener('mouseout', function(evt) {
        context.clearRect(0, 0, canvas.width, canvas.height);
        console.log("Canvas cleared");
    }, false);

    function loadXMLDoc() {
        var xmlhttp;
        if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
        }
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                var ajaxData = JSON.parse(xmlhttp.responseText);
                image.src = ajaxData.filename;
                image.onload = function() {
                    canvas.width = Math.round(canvas.height / image.height * image.width);
                    canvas.style.backgroundImage = "url('" + image.src + "')";
                }
                var faces = ajaxData.faces;

                canvas.addEventListener('mouseover', function(evt) {
                    console.log("Canvas entered");
                    console.log("Faces to mark: " + faces.length);

                    for (i = 0; i < faces.length; i++) {
                        context.beginPath();
                        context.arc(faces[i].x, faces[i].y, 
                            faces[i].radius, 0, 2 * Math.PI);
                        context.strokeStyle = "#00BBBB";
                        context.lineWidth = 1;
                        context.stroke();
                    }
                }, false);

            }
        }
        xmlhttp.open("GET", "get_data.php", true);
        xmlhttp.send();
    }
</script>

<button type="button" onclick="loadXMLDoc()">Change Content</button>
</body>
</html>

最佳答案

您可以remove the old listener在添加新的之前。但更好的方法是将数据保存到事件监听器外部的变量中,该变量会在每次 AJAX 响应后更新。那么监听器调用的函数根本不需要改变,它只是引用带有你的面部数据的变量。

编辑

您可以在脚本顶部添加另一个变量:var faces;。脚本的其余部分将可以访问它,就像其他变量一样。您最初不需要为其分配值。现在将您的 mouseover 监听器与 mouseout 监听器置于同一级别。当您从服务器获取数据时,只需将其分配给faces:faces = ajaxData.faces;(这里不要使用var,否则它将把faces定义为回调中的局部变量)。现在上面定义的 faces 变量将具有该数据,并且监听器将可以访问它。每次进行 AJAX 调用时,它都会用新的面孔覆盖旧的面孔。您可能需要在 mouseover 监听器中添加检查,以确保变量具有数据。您可以这样检查:

if (typeof faces == 'object'){
    // your for loop can go here
}

在 AJAX 回调设置 faces 的值之前,typeof faces 将等于 'undefined'

在您掌握语言如何处理作用域之前,JavaScript 将会令人困惑。 Check this out作为一个好的起点。

关于javascript - 使 JavaScript 事件处理程序依赖于 AJAX 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26131526/

相关文章:

php - 通过 Ajax 发送到 PHP 的 Fabric.js canvas.toDataURL()

javascript - 无法读取未定义的属性 'length' [reactjs]

javascript - 使用 javascript 更改类并使用 cookie 存储

javascript - 如何通过JS从json读取 bool 值

javascript - CodeIgniter ajax重新加载页面问题

javascript - Canvas 游戏帧率下降

使用 Object.create 与使用 new 的 JavaScript 继承

javascript正则表达式条件数字格式

javascript - 调用回调方法

javascript - 通过 Meteor 更新 KineticJS Canvas 元素