Flash/AS2: приложение становится медленнее, чем дальше вы прокручиваете вниз

Я создал приложение во флэш-памяти, это довольно большое приложение, которое работает довольно гладко, однако это длинный список графиков, которые работают дальше окна приложения, поэтому я использую вертикальную полосу прокрутки и маску для их отображения.

Проблема в том, что чем дальше вы прокручиваете вниз, все становится прерывистым, любые твины или движения, и частота кадров в целом кажется намного ниже.

Когда вы добираетесь до дна, это невыносимо, хотя в прокрутке одинаковое количество мувиклипов и такое же количество деталей, поэтому я не понимаю, почему должен быть такой огромный удар по производительности из-за небольшого снижения.

У кого-нибудь есть идеи относительно того, что может быть причиной этого?

По запросу вот часть моего кода, которая строит графики:

var local_data = SharedObject.getLocal("user_data");
Slide_Tracker = local_data.data.user_data;
var timespan:MovieClip = this.timescale.span;
for (i=0; i<Slide_Tracker.length; i++) {
    var current_date = new Date(Slide_Tracker[i].date_int);
    var date_int:Number = Slide_Tracker[i].date_int;
    var x_range:Number = 30;
    var sorted_date:Object = new Object(sortDate(Slide_Tracker[i].date_int));
    var date_string:String = sorted_date.string;
    var startX:Number = 0;
    date_nav.push(Slide_Tracker[i].date_int);
    if (i == 0) {
        for (s=0; s<Graphs.length; s++) {
            var Chart:MovieClip = Graphs[s].chartArea.createEmptyMovieClip("chart", 10);
            Chart._x = 0;
            Chart._y = 0;
            Charts.push(Chart);
            Chart._parent.dotSpace.index = s;
            Chart._parent.dotSpace.onRollOver = function() {
                this.followDot._visible = true;
                this.followDot.enabled = false;
                this.onMouseMove = function() {
                    if(this._parent.chart.viewPortRatio == undefined) {
                        var viewPortRatio:Number = 1;
                    }
                    else {
                        var viewPortRatio:Number = this._parent.chart.viewPortRatio;
                    }
                    var xMouse:Number = this._xmouse;
                    var xToArray:Number = Math.round(((xMouse-this._parent.chart._x)*viewPortRatio));
                    this.followDot._y = lineArray[this.index][xToArray].y;
                    trace(xToArray);
                    this.followDot._x = xMouse;
                };
            };
            Chart._parent.dotSpace.onRollOut = function() {
                this.followDot._visible = false;
                delete this.onMouseMove;
            };
        }
    } else if (i>0) {
        var past_date:Date = new Date(Slide_Tracker[i-1].date_int);
        var date_diff:Number = Math.round((current_date-past_date)/86400000);
    }
    for (s=0; s<Slide_Tracker[i].val_arr.length; s++) {
        var Slide_y:Number = 100-Slide_Tracker[i].val_arr[s];
        var Chart:MovieClip = Graphs[s].chartArea.chart;
        with (Chart) {
            beginFill(0x000066,15);
            lineStyle(2,0x000066,80);
            if (i == 0) {
                moveTo(startX,Slide_y);
                Xcoords[s].push(startX);
                Ycoords[s].push(Slide_y);
            } else if (i>0) {
                var index:Number = Xcoords[s].length-1;
                var prevX:Number = Xcoords[s][index];
                var prevY:Number = Ycoords[s][index];
                moveTo(prevX,prevY);
                var newX:Number = prevX+(date_diff*(895.9/x_range));
                var newY:Number = Slide_y;
                lineTo(newX,newY);
                lineStyle(6,0x000066,0);
                lineTo(newX,100);
                lineTo(prevX,100);
                lineTo(prevX,prevY);
                convertLineToArray(s,prevX,newX,prevY,newY);
                Xcoords[s].push(newX);
                Ycoords[s].push(newY);
            }
            endFill();
            lineStyle(0,0x000066,80);
            with (Graphs[s].chartArea.timescale.span) {
                var barName:String = Slide_Tracker[i].date_int;
                var thisBar:MovieClip = attachMovie("bar", barName, this.getNextHighestDepth()+i);
                if (Slide_y != 100) {
                    var barY:Number = 100-Slide_y;
                } else {
                    var barY:Number = 0;
                }
                if (i == 0) {
                    thisBar._x = 1;
                    thisbar._height = barY/4;
                    spanXcoords[s].push(1);
                    spanYcoords[s].push(barY/4);
                } else if (i>0) {
                    var index:Number = spanXcoords[s].length-1;
                    var spanPrevX:Number = spanXcoords[s][index];
                    var spanPrevY:Number = spanYcoords[s][index];
                    var spanNewX:Number = spanPrevX+(date_diff*3);
                    var spanNewY:Number = barY/4;
                    thisBar._x = spanNewX;
                    thisBar._height = barY/4;
                    spanXcoords[s].push(spanNewX);
                    spanYcoords[s].push(spanNewY);
                }
                thisBar._y += 25;
                selector_bars[s].push(thisBar);
            }
        }
        Chart.setMask(Chart._parent.chart_mask);
        var dot_name:String = new String(Graphs[s]._name+"_dot"+i);
        var dotObj:Object = new Object();
        if (prevX != undefined) {
            dotObj._x = newX;
        } else {
            dotObj._x = startX;
        }
        dotObj._y = Slide_y;
        Chart._parent.dotArea.attachMovie("graph_dot",dot_name,Graphs[s].chartArea.dotArea.getNextHighestDepth(),dotObj);
        Chart._parent.dotArea.swapDepths(99999);
        var thisDot:MovieClip = eval(Graphs[s]+".chartArea.dotArea."+dot_name);
        Graphs_dots[s].push(thisDot);
        thisDot.date_string = date_string;
        thisDot.date_int = date_int;
        thisDot.percent = Slide_Tracker[i].val_arr[s];
        thisDot.onRollOver = function() {
            this.gotoAndStop("over");
            var dot_Coords:Object = {x:this._x, y:this._y};
            var viewPortRatio:Number = this._parent._parent.chart.viewPortRatio;
            var offsetX:Number = this._parent._parent.chart.offsetX;
            if (viewPortRatio == undefined) {
                viewPortRatio = 1;
            }
            if (offsetX == undefined) {
                offsetX = 0;
            }
            var text_x:Number = (dot_Coords.x/viewPortRatio)+offsetX;
            var text_y:Number = dot_Coords.y;
            if (dot_Coords.y<50) {
                text_y += 60;
            } else {
                text_y -= 20;
            }
            var Textbox:Object = {name:"dot_info", container:this._parent._parent._parent, x:text_x, y:text_y, text:this.date_string+"\n"+this.percent+"%"};
            var dotText:TextField = generateTextbox(Textbox);
            if (dotText._x>448) {
                dotText._x -= dotText._width;
            }


        };
        thisDot.onRollOut = thisDot.onReleaseOutside=function () {
            this.gotoAndStop("norm");
            killTxt(this._parent._parent._parent.dot_info);
            delete dot_Coords;
        };

    }
    chartsWidth = Chart._width;
}

И вот мой код полосы прокрутки:

scrolling = function () { 
var scrollHeight:Number = scrollTrack._height - btnUp._height - btnDown._height; 
var contentHeight:Number = contentMain._height; 
var scrollFaceHeight:Number = scrollFace._height; 
var maskHeight:Number = maskedView._height; 
var initPosition:Number = scrollFace._y=scrollTrack._y + btnUp._height; 
var initContentPos:Number = contentMain._y; 
var finalContentPos:Number = maskHeight-contentHeight+initContentPos; 
var left:Number = scrollTrack._x + (scrollTrack._width - scrollFace._width)/2.4; 
var top:Number = scrollTrack._y + btnUp._height; 
var right:Number = scrollTrack._x + (scrollTrack._width - scrollFace._width)/2.4; 
var bottom:Number = (scrollTrack._height-scrollFaceHeight+scrollTrack._y) - btnDown._height; 
var dy:Number = 0; 
var speed:Number = 10; 
var moveVal:Number = (contentHeight-maskHeight)/(scrollHeight-scrollFaceHeight); 

scrollFace.onPress = function() { 
var currPos:Number = this._y; 
startDrag(this, false, left, top, right, bottom); 
this.onMouseMove = function() { 
dy = Math.abs(initPosition-this._y); 
contentMain._y = Math.round(dy*-1*moveVal+initContentPos);
};
}; 
scrollFace.onMouseUp = function() { 
stopDrag(); 
delete this.onMouseMove;
}; 
btnUp.onPress = function() { 
this.onEnterFrame = function() { 
if (contentMain._y+speed<maskedView._y) { 
if (scrollFace._y<=top) { 
scrollFace._y = top;
} else { 
scrollFace._y -= speed/moveVal;
} 
contentMain._y += speed;
} else { 
scrollFace._y = top; 
contentMain._y = maskedView._y; 
delete this.onEnterFrame;
}
};
}; 
btnUp.onDragOut = function() { 
delete this.onEnterFrame;
}; 
btnUp.onRollOut = function() { 
delete this.onEnterFrame;
}; 
btnDown.onPress = function() { 
this.onEnterFrame = function() { 
if (contentMain._y-speed>finalContentPos) { 
if (scrollFace._y>=bottom) { 
scrollFace._y = bottom;
} else { 
scrollFace._y += speed/moveVal;
} 
contentMain._y -= speed;
} else { 
scrollFace._y = bottom; 
contentMain._y = finalContentPos; 
delete this.onEnterFrame;
}
};
}; 
btnDown.onRelease = function() { 
delete this.onEnterFrame;
}; 
btnDown.onDragOut = function() { 
delete this.onEnterFrame;
}; 
var mouseListener = new Object();
mouseListener.onMouseWheel = function( wheelMotion )
{
if (wheelMotion < 0) {
if (contentMain._y-speed>finalContentPos) { 
if (scrollFace._y>=bottom) { 
scrollFace._y = bottom;
} else { scrollFace._y += speed/moveVal;
} 
contentMain._y -= speed;
} else { 
scrollFace._y = bottom; 
contentMain._y = finalContentPos; 
}
}
if (wheelMotion > 0) {
if (contentMain._y+speed<maskedView._y) { 
if (scrollFace._y<=top) { 
scrollFace._y = top;
} else { 
scrollFace._y -= speed/moveVal;
} 
contentMain._y += speed;
} else { 
scrollFace._y = top; 
contentMain._y = maskedView._y; 
}
}
}

Mouse.addListener( mouseListener );



if (contentHeight<maskHeight) { 
scrollFace._visible = false; 
btnUp.enabled = false; 
btnDown.enabled = false;
btnUp.gotoAndStop(2);
btnDown.gotoAndStop(2);
} else { 
scrollFace._visible = true; 
btnUp.enabled = true; 
btnDown.enabled = true;
btnUp.gotoAndStop(1);
btnDown.gotoAndStop(1);
}
}; 
scrolling();

person George Reith    schedule 18.07.2011    source источник
comment
Вы добавляете дополнительные видеоклипы в список отображения при прокрутке вниз, и как насчет того, когда вы один раз прокручиваете вниз и возвращаетесь к началу прокрутки, становится ли он вдвое медленнее или становится лучше, когда вы возвращаетесь наверх?   -  person Badr    schedule 18.07.2011
comment
становится лучше, когда вы прокручиваете вверх, элементы ниже существуют, как только человек входит в кадр, и статичны, за исключением изменения значения Y при прокрутке.   -  person George Reith    schedule 18.07.2011
comment
Обновлено, это вступает в силу только при наличии большого количества графических данных, до тех пор они прокручиваются и воспроизводятся плавно. Но все же не должно становиться хуже, когда вы прокручиваете вниз, верно?   -  person George Reith    schedule 18.07.2011
comment
код кажется достаточно хорошим, и есть несколько хороших практик, которые могут сделать его лучше, только рекомендации для вас, которые разделяют обработку данных графика и рендеринг в разных кадрах, разделяют обработку на куски, а не делают это за один раз, поскольку это расширит кадр и рендеринг пользовательского интерфейса будет показывать задержки и при необходимости использовать сборщик мусора, я думаю, что у меня не будет проблем с памятью, но на случай, если вы столкнетесь с проблемой памяти, нам GC. удачи   -  person Badr    schedule 19.07.2011
comment
Спасибо, просто я немного не уверен, что вы подразумеваете под разделением обработки данных и рендеринга, вы имеете в виду построение графиков в одном кадре и отображение их в следующем?   -  person George Reith    schedule 19.07.2011


Ответы (1)


Я решил это сегодня, и какое облегчение, я только что столкнулся с функцией scrollRect(), которая отображает только те данные, которые доступны для просмотра в пределах своих границ, пока они кэшированы в растровом изображении (векторные объекты все равно будут отображаться полностью независимо от того, доступны они для просмотра или нет).

Несмотря на то, что я позволил пользователю изменить _scaleX графиков и кэшировать их в виде растрового изображения, теперь я все еще вижу абсолютно огромный прирост производительности после замены моих масок прямоугольником с возможностью прокрутки, поскольку после достаточного количества данных эти графики были более 20 000 в ширину. Несмотря на их огромные размеры, все работает плавно.

объяснение Adobe scrollRect()

person George Reith    schedule 19.07.2011