3

我制作了这段代码,可以制作一些淡入淡出的视觉“瓷砖”。但目前我遇到了一点性能问题。

尽管大多数浏览器都可以正常运行代码(尤其是 firefox),但有些像 safari 会在一段时间后出现问题(一段时间 = 15 秒)。

我认为这是由于我的递归函数(名为changeopacity的函数在延迟时永远调用自己)?或者是吗?

但无论如何,问题在于这段代码对于大多数浏览器来说真的很重。有没有,或者更多我怎样才能让这段代码表现得更好?有什么想法吗?(代码示例会很好)谢谢:-)

实际代码:

$(document).ready(function () {

    var aniduration = 2000;
    var tilesize = 40;

    createtable(tilesize);



    $(".tile").each(function (index, domEle) {
        var randomdelay = Math.floor(Math.random() * 3000);
        setTimeout(function () {
            changeopacity(aniduration, domEle);
        }, randomdelay);
    });



    $("td").click(function () {
        clickanimation(this, 9);
    });

    $("td").mouseenter(function () {
        var element = $(this).find("div");
        $(element).clearQueue().stop();
        $(element).animate({opacity: "0.6"}, 800);
    });


    $("td").css("width", tilesize + "px").css("height", tilesize + "px");



});

function createtable(tilesize) {
    var winwidth = $(window).width();
    var winheight = $(window).height();
    var horztiles = winwidth / tilesize;
    var verttiles = winheight / tilesize;


for (var y = 0; y < verttiles; y++)
{
    var id = "y" + y;
    $("#tbl").append("<tr id='" + id + "'></tr>");

    for (var x = 0; x < horztiles; x++)
    {
        $("#" + id).append("<td><div class='tile' style='opacity: 0; width: " + tilesize + "px; height: " + tilesize + "px;'></div></td>");
    }
}   
}

function changeopacity(duration, element){
    var randomnum = Math.floor(Math.random() * 13);
    var randomopacity = Math.floor(Math.random() * 7);
    var randomdelay = Math.floor(Math.random() * 1000);

    if ($(element).css("opacity") < 0.3)
    {
        if (randomnum != 4)
        {
            if ($(element).css("opacity") != 0)
            animation(element, 0, duration, randomdelay);
        }
        else
        {
            animation(element, randomopacity, duration, randomdelay);
        }
    }
    else
    {
        animation(element, randomopacity, duration, randomdelay);
    }

    setTimeout(function () {
        return changeopacity(duration, element);
    }, duration + randomdelay);
}

function animation(element, randomopacity, duration, randomdelay){
    $(element).clearQueue().stop().delay(randomdelay).animate({opacity: "0." + randomopacity}, duration);
}


function clickanimation(column, opacitylevel) {
        var element = $(column).find("div");
        $(element).clearQueue().stop();
        $(element).animate({"background-color": "white"}, 200);
        $(element).animate({opacity: "0." + opacitylevel}, 200);
        $(element).delay(200).animate({opacity: "0.0"}, 500);
        //$(element).delay(600).animate({"background-color": "black"}, 500);
}
4

2 回答 2

2

第一个问题是您正在setTimeout为页面上的每个单元格创建一个。唯一能够处理的浏览器是 Internet Explorer,然后由于许多 CSS 更改导致重绘缓慢而失败。

我强烈建议您编写自己的事件调度程序。像这样的东西,我在大学项目中使用过:

var timer = {
    length: 0,
    stack: {},
    timer: null,
    id: 0,
    add: function(f,d) {
        timer.id++;
        timer.stack[timer.id] = {f: f, d: d, r: 0};
        timer.length++;
        if( timer.timer == null) timer.timer = setInterval(timer.run,50);
        return timer.id;
    },
    addInterval: function(f,d) {
        timer.id++;
        timer.stack[timer.id] = {f: f, d: d, r: d};
        timer.length++;
        if( timer.timer == null) timer.timer = setInterval(timer.run,50);
        return timer.id;
    },
    remove: function(id) {
        if( id && timer.stack[id]) {
            delete timer.stack[id];
            timer.length--;
            if( timer.length == 0) {
                clearInterval(timer.timer);
                timer.timer = null;
            }
        }
    },
    run: function() {
        var x;
        for( x in timer.stack) {
            if( !timer.stack.hasOwnProperty(x)) continue;
            timer.stack[x].d -= 50;
            if( timer.stack[x].d <= 0) {
                timer.stack[x].f();
                if( timer.stack[x]) {
                    if( timer.stack[x].r == 0)
                        timer.remove(x);
                    else
                        timer.stack[x].d = timer.stack[x].r;
                }
            }
        }
    }
};

然后,使用相同的参数setTimeout调用而不是使用。timer.add同样,setInterval您可以调用timer.addInterval.

这将允许您拥有任意数量的计时器,并且它们都将运行在一个单一setInterval的 ,对浏览器造成的问题要少得多。

于 2012-07-19T20:44:36.347 回答
2

不错的动画:-) 但是,我发现了一些错误和可能的改进:

  • 您的表格不会在窗口调整大小时重建。不确定是错误还是功能:-)
  • 使用委托事件。你有很多元素,每个事件处理程序都是昂贵的。可悲的是,这不适用于非冒泡mouseenter事件。
  • 如果您不对 with 和 height 使用内联样式,那就太好了——这些不会改变。对于 div 来说,无论如何它们都是 superflouos 。
  • 我看不出所有这些元素都有 ID 的原因。html-string 的构建可能更简洁。

  • 缓存元素!!!您几乎在每个变量上都使用了jQuery构造函数,构建了一个新实例。只需重复使用它们!

  • 你的changeopacity函数看起来有点奇怪。如果不透明度低于 0.3,是否有 13 分之一的机会将动画设为零?这可能表达得更严格。您也可以将不透明度缓存到一个变量中,而不是每次都从 dom 中读取它。

  • 没有理由将 theduration和其他常量作为参数传递,它们永远不会改变并且可以在全局范围内使用。

  • 您应该使用方法的完整回调,animate而不是使用超时。超时永远不会准确,它们甚至可能会干扰这里导致(小)问题。

var duration = 2000,
    tilesize = 40,
    clickopacity = 0.9;

$(document).ready(function () {

    filltable($("#tbl"), tilesize)
      .on("click", "td", clickanimation);

    $(".tile").each(function() {
        changeopacity($(this));
    });

    $("#tbl div").mouseenter(function () {
        $(this).clearQueue()
               .stop()
               .animate({opacity: "0.6"}, 800);
    });
});

function filltable(tbl, tilesize) {
    var win = $(window).width();
    var horztiles = win.width() / tilesize;
    var verttiles = win.height() / tilesize;

    for (var y = 0; y < verttiles; y++) {
        var tr = "<tr>";
        for (var x = 0; x < horztiles; x++)
            tr += "<td style='width:"+tilesize+"px;height:"+tilesize+"px;'><div class='tile' style='opacity:0;'></div></td>");
        tbl.append(tr+"</tr>");
    }
    return tbl;
}

function changeopacity(element) {
    var random = Math.floor(Math.random() * 13);
    var opacity = Math.floor(Math.random() * 7);
    var delay = Math.floor(Math.random() * 1000);

    if (element.css("opacity") < 0.3 && random != 4)
        opacity = 0;

    element.clearQueue().stop().delay(delay).animate({
        opacity: "0." + opacity
    }, duration, function() {
        changeopacity(element);
    });
}

function clickanimation() {
    $(this.firstChild)
      .clearQueue()
      .stop()
      .animate({"background-color": "white"}, 200)
      .animate({opacity: "0." + clickopacity}, 200)
      .delay(200).animate({opacity: "0.0"}, 500);
    //.delay(600)
    //.animate({"background-color": "black"}, 500);
}
于 2012-07-19T20:58:56.593 回答