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

EaselJS Shape对象拖拽报错:无法读取'on'属性(未定义)

解决EaselJS拖拽矩形时的Cannot read property 'on' of undefined错误

这个报错的根源很清晰——你在拖拽事件里误用了全局变量i,导致索引错位了。

每次点击画布生成新矩形时,全局的i都会自增。等你去拖拽之前生成的矩形时,i已经指向了数组里还没赋值的位置,这时候rects[i]自然就是undefined,调用on方法肯定会报错。

最简单的修复方案:直接操作事件目标

不需要依赖全局的i,我们可以通过事件对象里的target属性直接获取当前被点击的矩形实例,这样就彻底避免了索引问题。

修正后的完整代码如下:

var rects = []; 
var i = 0; 
var stage; 

window.onload = function() { 
    canvas = document.getElementById("drawingCanvas"); 
    context = canvas.getContext("2d"); 
    stage = new createjs.Stage("drawingCanvas"); 
    canvas.onclick = canvasClick; 
} 

function canvasClick(e) { 
    var d = Math.random() * 150; 
    rects[i] = new createjs.Shape(); 
    // 用模板字符串优化颜色拼接,可读性更好
    rects[i].graphics.beginStroke("black")
                   .beginFill(`RGB(${parseInt(Math.random()*255)},${parseInt(Math.random()*255)},${parseInt(Math.random()*255)})`)
                   .drawRect(e.offsetX - d/2, e.offsetY - d/2, d, d); 
    stage.addChild(rects[i]); 
    
    rects[i].on("mousedown", function (event) { 
        console.log("开始拖拽"); 
        var offset = { 
            x: event.target.x - event.stageX, 
            y: event.target.y - event.stageY 
        }; 
        // 直接绑定到当前被点击的矩形,无需依赖全局i
        event.target.on("pressmove", function (event) { 
            event.target.x = event.stageX + offset.x; 
            event.target.y = event.stageY + offset.y; 
            stage.update(); 
        }); 
    }); 
    
    i++; 
    stage.update(); 
}

修复要点说明:

  1. 移除全局索引依赖:在mousedown回调里,用event.target直接获取当前操作的Shape实例,替代原来的rects[i],从根源上避免索引错位问题。
  2. 优化代码可读性:把原来繁琐的RGB颜色字符串拼接改成了ES6模板字符串,看起来更清爽。
  3. 修正拼写错误:把事件参数的evant改成了标准的event(虽然不影响运行,但规范的命名能减少后续维护的困惑)。

另一种方案:用闭包保存当前索引

如果你坚持要用数组索引来操作,也可以通过闭包把当前的i值保存下来,避免后续i自增影响:

rects[i].on("mousedown", (function(currentIndex) {
    return function(event) {
        console.log("开始拖拽"); 
        var offset = { 
            x: rects[currentIndex].x - event.stageX, 
            y: rects[currentIndex].y - event.stageY 
        }; 
        rects[currentIndex].on("pressmove", function (event) { 
            rects[currentIndex].x = event.stageX + offset.x; 
            rects[currentIndex].y = event.stageY + offset.y; 
            stage.update(); 
        }); 
    }
})(i));

不过相比之下,第一种直接操作事件目标的方法更简洁直观,推荐使用。

内容的提问来源于stack exchange,提问作者Ольга Кужикова

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:08:14