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

jQuery气泡效果迁移至Backbone遇bubble未定义问题求助

解决Backbone视图中气泡效果的「bubble未定义」错误

看起来你在把原生气泡动画迁移到Backbone视图时,踩了一个核心的逻辑坑:你把独立的bubble类拆成了视图的方法,导致没有创建真正的气泡实例。原代码里每个气泡都是bubble类的独立对象,拥有专属的位置、大小等属性,但你现在试图用视图的全局属性模拟单个气泡,这不仅会触发「bubble未定义」错误,还会让所有气泡共享同一套属性,完全失去多气泡动画的效果。

下面是修正后的完整Backbone视图代码,我会标注关键修改点:

var Achievement = CcCarousel.extend({
    initialize: function() {
        // 初始化requestAnimationFrame兼容层
        this._setupRequestAnimFrame();
    },

    render: function() {
        var courseData = this.gameData ? this.gameData : this.app.courseData;
        if (courseData.getStatus() == Status.COMPLETED) {
            this.app.router.next();
        } else {
            CcCarousel.prototype.render.call(this);
            this.showStaggerAnimation();
            this.changeLockedChaptersImage();
            this.setupButtonListeners();
            this.backgroundSetupVariables();
        }
    },

    // 1. 重新定义独立的Bubble构造函数,保留原类的封装性
    Bubble: function(canvasWidth, canvasHeight) {
        this.maxHeight = canvasHeight;
        this.maxWidth = canvasWidth;
        this.randomise();
    },

    // 把原bubble类的方法挂载到Bubble原型上
    _bubbleProto: {
        generateDecimalBetween: function(min, max) {
            return (Math.random() * (min - max) + max).toFixed(2);
        },
        update: function() {
            this.posX = this.posX - this.movementX;
            this.posY = this.posY - this.movementY;
            if (this.posY < 0 || this.posX < 0 || this.posX > this.maxWidth) {
                this.randomise();
                this.posY = this.maxHeight;
            }
        },
        randomise: function() {
            this.colour = "255, 255, 255";
            this.size = this.generateDecimalBetween(10, 15);
            this.movementX = this.generateDecimalBetween(-1, 1);
            this.movementY = this.generateDecimalBetween(1, 2);
            this.alpha = this.generateDecimalBetween(0.1, 1);
            this.posX = this.generateDecimalBetween(0, this.maxWidth);
            this.posY = this.generateDecimalBetween(0, this.maxHeight);
        }
    },

    backgroundSetupVariables: function() {
        this.canvas = document.getElementById("floatingbubbles");
        this.ctx = this.canvas.getContext("2d");
        this.canvas.height = window.innerHeight;
        this.canvas.width = window.innerWidth;
        this.bubblesList = [];
        
        // 绑定Bubble的原型方法
        this.Bubble.prototype = this._bubbleProto;
        
        this.generateBubbles();
        this.animate();
    },

    generateBubbles: function() {
        var self = this;
        // 修正气泡密度计算的语法错误:原逗号运算符无效,改为计算画布面积平方根并缩放
        var density = Math.sqrt(this.canvas.height * this.canvas.width) * 0.01;
        for (let i = 0; i < density; i++) {
            // 2. 创建真正的Bubble实例,添加到列表中
            this.addBubble(new self.Bubble(self.canvas.width, self.canvas.height));
        }
    },

    addBubble: function(bubble) {
        return this.bubblesList.push(bubble);
    },

    // 3. 补上原background类的animate动画循环方法
    animate: function() {
        let self = this;
        self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height);
        self.bubblesList.forEach(function(bubble) {
            bubble.update();
            self.ctx.beginPath();
            self.ctx.arc(bubble.posX, bubble.posY, bubble.size, 0, 2 * Math.PI);
            self.ctx.strokeStyle = "rgba(" + bubble.colour + "," + bubble.alpha + ")";
            self.ctx.stroke();
        });
        requestAnimationFrame(self.animate.bind(self));
    },

    // 兼容旧浏览器的requestAnimationFrame polyfill
    _setupRequestAnimFrame: function() {
        window.requestAnimFrame = (function() {
            return (
                window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                function(callback) {
                    window.setTimeout(callback, 1000 / 60);
                }
            );
        })();
    }
});

关键修改说明:

  • 恢复独立气泡实例:重新定义Bubble构造函数和原型方法,确保每个气泡都是拥有专属属性的独立对象,避免视图属性被共享覆盖。
  • 修正气泡生成逻辑:替换原错误的getCanvasLength调用,改为创建Bubble实例并添加到列表,这样bubblesList里才会有可调用update方法的有效对象。
  • 补全动画循环:迁移原background类的animate方法,确保气泡的更新和渲染循环正常运行,同时用bind(self)保证回调中的上下文指向视图实例。
  • 修复密度计算错误:原代码的逗号运算符无法正确计算画布面积,改为基于面积平方根的合理密度公式,避免气泡过多或过少。
  • 添加兼容层:在视图初始化时设置requestAnimationFrame的polyfill,确保旧浏览器也能正常运行动画。

内容的提问来源于stack exchange,提问作者Leo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:58:37