Flash/AS2: Application gets slower the further you scroll down
I have built an application in flash, it is rather a large application that runs pretty smoothly, however it is a long list of graphs that run further than the application window so I use a vertical scrollbar and a mask to display them.
The problem is everything becomes choppy the further you scroll down, any Tweens or movement and the framerate in general just appears to be much much lower.
When you get to the bottom it is unbearable although there is the same amount of movieclips and same amount of detail throughout the scroll, so I don't see why there should be this massive performance hit for going down a bit.
Anyone have any ideas as to what could be causing this?
As requested here is the part of my code which builds the graphs:
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(开发者_JAVA百科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;
}
And here is my scrollbar code:
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();
I solved this today and what a relief, I just ran into the scrollRect()
function which only renders the data which is viewable within it's bounds as long as it is bitmap cached (vector objects will still be rendered in full whether viewable or not).
Despite the fact I let the user modify the _scaleX of the graphs and caching them as a bitmap now I still see an absolutely huge performance increase since swapping my masks with a scrollable rectangle, as after enough data these graphs were over 20,000 in width. Despite their humongous size everything works fluidly.
Adobe's explanation of scrollRect()
精彩评论