📄 fisheyebase.as
字号:
{
return NaN;
}
/** called on mouse click to set or clear the selection */
private function updateSelection(e:MouseEvent):void
{
if(_selectionEnabled == false)
return;
var newSelection:Number = findItemForPosition(this.mouseX,this.mouseY);
if(selectedItemIndex == newSelection)
selectedIndex = -1;
else
selectedIndex = newSelection;
updateState();
animator.invalidateLayout();
}
/** called on mouse move to update the hilight */
private function updateHilight(e:MouseEvent):void
{
var newHilight:Number = findItemForPosition(this.mouseX,this.mouseY);
if(newHilight == hilightedItemIndex)
return;
hilightedItemIndex = newHilight;
updateState();
animator.invalidateLayout();
}
/**
* update the state properties of all of the items, based on
* the current hilighted and/or selected items
*/
private function updateState():void
{
var stateProperty:String = getStyle("stateProperty");
if(stateProperty != null)
{
var rolloverState:String = getStyle("rolloverValue");
var selectedState:String = getStyle("selectedValue");
var unselectedValue:String = getStyle("unselectedValue");
if (unselectedValue == null || (isNaN(selectedItemIndex) && isNaN(hilightedItemIndex)))
unselectedValue = getStyle("defaultValue");
for(var i:int=0;i<renderers.length;i++)
{
renderers[i][stateProperty] = (i == selectedItemIndex)? selectedState:
(i==hilightedItemIndex)? rolloverState:
unselectedValue;
}
}
}
/**
* each item get scaled down based on its distance from the hliighted item. this is the equation we use
* to figure out how much to scale down. The basic idea is this...we have two parameters that play a part
* in how quickly we scale down, scaleRadius and scaleSlope. scaleRadius is the number of items on either
* side of the hilighted item (inclusive) that we should be able to use to scale down. scaleSlope affects
* how whether we scale down quickly with the first few items in the radius, or the last few items.
* This equation essentially does that.
*/
private function calcDistanceFactor(params:FisheyeParameters, distance:Number):Number
{
var mult:Number = 1/params.scaleRadius;
return Math.max(0,1 - Math.pow(distance*mult,params.scaleSlope));
}
/**
* populates a set of items to fit into the distance axisLength, assuming nothing is hilighted, so they
* all scale the same. It will attempt to scale them to match the defaultScale style */
protected function populateMajorAxisForDefault(pdata:Array,axis:FisheyeAxis,axisLength:Number):FisheyeParameters
{
var vp:Number;
var itemCount:int = pdata.length;
var params:FisheyeParameters = new FisheyeParameters();
populateParameters(params,false);
var summedSpacing:Number = params.spacing*(itemCount-1);
var sizeSum:Number = 0;
var pdataInst:FisheyeItem;
for(var i:int = 0;i<itemCount;i++)
sizeSum += pdata[i][axis.EOM];
if(sizeSum > 0)
{
var maximumMinScale:Number = (axisLength - summedSpacing) / sizeSum;
params.minScale = Math.min(params.minScale,maximumMinScale);
}
vp = 0;
for(var i:int=0;i<itemCount;i++)
{
pdataInst = pdata[i];
pdataInst.scale = params.minScale;
pdataInst[axis.pos] = vp;
vp += pdataInst[axis.EOM] * params.minScale + params.spacing;
}
return params;
}
/**
* takes the parameters used in the fisheye equation, and adjusts them as best as possible to make sure the
* items can fit into distance 'axisScale.' Right now it does this by scaling down the minScale parameter if necessary. That's
* not entirely sufficient, but it does a pretty good job. For future work: If that's not sufficient, adjust the scaleRadius, scaleSlope,
* and spacing parameter
*/
private function adjustParameters(pdata:Array,targetIndex:Number,params:FisheyeParameters,axisSize:Number,axis:FisheyeAxis):void
{
var itemCount:int = pdata.length;
var summedSpacing:Number = params.spacing*(itemCount-1);
var maxSum:Number = 0;
var minSum:Number = 0;
// given the constraint:
// W(0) * S(0) + spacing + W(1) * S(1) + spacing + ... + W(N) * S(N) <= unscaledWidth
// here we adjust the numbers that go into the calculation of S(i) to fit.
// right now that just means adjusting minScale downward if necessary. We'll probably add some more complex heuristic later.
for(var i:int = 0;i<itemCount;i++)
{
var pdataInst:FisheyeItem = pdata[i];
var distanceFromItem:Number = Math.abs(targetIndex - i);
var distanceFactor:Number = calcDistanceFactor(params,distanceFromItem);
var maxFactor:Number = params.maxScale * distanceFactor;
var minFactor:Number = (1 - distanceFactor);
var itemSize:Number = pdataInst[axis.EOM];
maxSum += itemSize * maxFactor;
minSum += itemSize * minFactor;
}
var minScale:Number = (minSum > 0)? ((axisSize - summedSpacing - maxSum) / minSum):0;
// if we've got lots of extra space, we might calculate that we need to make our ends _larger_ to fill the space. We don't want
// to do that. So let's contrain it to minScale.
minScale = Math.min(params.minScale,minScale);
params.minScale = minScale;
}
/**
* populate a parameters structure from the various styles
*/
private function populateParameters(params:FisheyeParameters,hilighted:Boolean):void
{
if(hilighted == false)
{
params.minScale = getStyle("defaultScale");
if(isNaN(params.minScale))
params.minScale = .5;
params.spacing = defaultSpacingWithDefault;
}
else
{
params.minScale = getStyle("hilightMinScale");
if(isNaN(params.minScale))
{
params.minScale = getStyle("defaultScale");
if(isNaN(params.minScale))
params.minScale = .5;
}
params.spacing = getStyle("hilightSpacing");
if(isNaN(params.spacing))
params.spacing = defaultSpacingWithDefault;
}
params.maxScale = getStyle("hilightMaxScale");
if(isNaN(params.maxScale ))
params.maxScale = 1;
params.scaleRadius = getStyle("hilightScaleRadius");
if(isNaN(params.scaleRadius))
params.scaleRadius = 2;
params.scaleRadius = Math.max(1,params.scaleRadius);
params.scaleSlope = getStyle("hilightScaleSlope");
if(isNaN(params.scaleSlope))
params.scaleSlope = .75;
}
/**
* populates a set of items to fit into the distance axisLength, assuming targetIndex is hilighted.
*/
protected function populateMajorAxisFor(pdata:Array,targetIndex:Number,axisSize:Number,axis:FisheyeAxis):FisheyeParameters
{
var vp:Number;
var itemCount:int = pdata.length;
var pdataInst:FisheyeItem;
var params:FisheyeParameters = new FisheyeParameters();
populateParameters(params,true);
adjustParameters(pdata,targetIndex,params,axisSize,axis);
vp = 0;
for(var i:int=0;i<itemCount;i++)
{
pdataInst = pdata[i];
var distanceFromItem:Number = Math.abs(targetIndex - i);
var distanceFactor:Number = calcDistanceFactor(params,distanceFromItem);
var scale:Number = Math.max(0,params.minScale + (params.maxScale - params.minScale)*(distanceFactor));
pdataInst[axis.pos] = vp;
pdataInst.scale = scale;
vp += pdataInst[axis.EOM] * scale + params.spacing;
}
return params;
}
/**
* given a set of scaled and laid out items, adjust them forward or backward to match the align property
*/
protected function align(pdata:Array,axis:FisheyeAxis):void
{
var majorAlignValue:String = getStyle(axis.align);
var itemCount:int = pdata.length;
var pdataInst:FisheyeItem;
if(itemCount == 0)
return;
switch(majorAlignValue)
{
case "right":
case "bottom":
pdataInst = pdata[itemCount-1];
var offset:Number = this[axis.unscaled] - (pdataInst[axis.pos] + pdata[itemCount-1][axis.EOM] * pdataInst.scale);
for(var i:int = 0;i<itemCount;i++)
{
pdata[i][axis.pos] += offset;
}
break;
case "left":
case "top":
break;
case "center":
default:
var offset:Number;
var midIndex:int = Math.floor(itemCount/2);
pdataInst = pdata[itemCount-1];
var rightPos:Number = pdataInst[axis.pos] + pdataInst[axis.EOM]*pdataInst.scale;
offset = (this[axis.unscaled]/2 - (rightPos)/2);
for(var i:int = 0;i<itemCount;i++)
{
pdata[i][axis.pos] += offset;
}
break;
}
}
/**
* overridden in the subclasses
*/
protected function generateLayout():void
{
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
graphics.clear();
graphics.moveTo(0,0);
graphics.beginFill(0,0);
graphics.drawRect(0,0,unscaledWidth,unscaledHeight);
// update the mask
mask.width = unscaledWidth;
mask.height = unscaledHeight;
animator.invalidateLayout();
}
override public function styleChanged(styleProp:String):void
{
if(styleProp == "animationSpeed")
animator.animationSpeed = getStyle("animationSpeed");
invalidateSize();
invalidateDisplayList();
animator.invalidateLayout();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -