어디에서 퍼왔는지는 기억이 잘 안나는데 Adobe사이트였나 -_-;
하여간 유용하게 잘 사용하시기 바랍니다. 한글주석부분만 제가 추가한 부분임 -_-;
약간 수정하여 사용하시면 다양하게 확장하여 사용 할 수 있습니다.
아래 코드를 나름 요약하여 설명하자면....
현재 커서의 위치를 얻어와 Point 에 저장한 다음 그것 기준으로 차트를 드로잉 해주는 것입니다. -_-/
그리고 중요 메소드는 updateDisplayList()입니다. 화면의 변화가 발생하는 경우 동작하는 메소드임.
참조로 Flex Help에서는 : Drawing programmatically 을 검색하여 보면 그리기 방법을 이해 할 수 있습니다.
사용 방법 해당 랜더러를 annotationElements 에 추가 시켜주면 됩니다.
예시)
<mx:annotationElements> <!--차트 위 드로잉 (강조)-->
<comp:RangeSelector />
</mx:annotationElements>
이런식으로 ^^;
package
{
importflash.display.*;
importflash.events.*;
importflash.geom.*;
importmx.charts.chartClasses.*;
importmx.controls.*;
public class RangeSelector extendsChartElement {
private const TEXT_COLOR:uint = 0xFFE635;
private const BOX_RANGE_THICKNESS:uint = 2;
private const BOX_RANGE_COLOR:uint = 0xFFE635;
private const BOX_BG_COLOR:uint = 0xB6FF37;
private const BOX_BG_ALPHA:Number = 0.2;
private const BOX_LINE_COLOR:uint = 0x518200;
private const BOX_LINE_THICKNESS:uint = 2;
private const LINE_COLOR:uint = 0xffffff;
private const LINE_THICKNESS:uint = 3;
private const LINE_ALPHA:Number = 0.5;
/* the bounds of the selected region*/
private var dLeft:Number = 20;
private var dTop:Number = 20;
private var dRight:Number = 80;
private var dBottom:Number = 80;
/* the x/y coordinates of the start of the trackingregion */
private var tX:Number;
private var tY:Number;
/* whether or not a region is selected */
private var bSet:Boolean = false;
/* whether or not we're currently tracking */
private var bTracking:Boolean = false;
/* the current position of the crosshairs */
private var _crosshairs:Point;
/* the four labels for the data bounds of the selectedregion */
private var _labelLeft:Label;
private var _labelRight:Label;
private var _labelTop:Label;
private var _labelBottom:Label;
/* constructor */
public function RangeSelector():void
{
super();
setStyle("color",0);
/* mousedowns are where we start tracking the selection*/
//addEventListener("mouseDown",startTracking);
/* mousemove and rollout are used to track the crosshairs*/
addEventListener("mouseMove",updateCrosshairs);
addEventListener("rollOut",removeCrosshairs);
/* create our labels */
_labelLeft = new Label();
_labelTop = new Label();
_labelRight = new Label();
_labelBottom = new Label();
_labelLeft.setStyle("color",TEXT_COLOR);
_labelTop.setStyle("color",TEXT_COLOR);
_labelRight.setStyle("color",TEXT_COLOR);
_labelBottom.setStyle("color",TEXT_COLOR);
addChild(_labelLeft);
addChild(_labelTop);
addChild(_labelRight);
addChild(_labelBottom);
}
/* draw the overlay */
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
var g:Graphics= graphics;
g.clear();
// draw a big transparent square so the flash player seesus for mouse events */
g.moveTo(0,0);
g.lineStyle(0,0,0);
g.beginFill(0,0);
g.drawRect(0,0,unscaledWidth,unscaledHeight);
g.endFill();
/* draw the crosshairs. Crosshairs are drawn where themouse is, only when the mouse is over us, so we don't need to transform
* to data coordinates
*/
if(_crosshairs!= null)
{
g.lineStyle(LINE_THICKNESS,LINE_COLOR,LINE_ALPHA);
g.moveTo(0,_crosshairs.y);
g.lineTo(unscaledWidth,_crosshairs.y);
g.moveTo(_crosshairs.x,0);
g.lineTo(_crosshairs.x,unscaledHeight);
//내가 추가한거 - 네모상자 그려주기
varR_SIZE:Number = 8;
var R_BG:uint =0xff0000;
varR_ALPHA:Number = 1;
var R_LINETHICK:Number = 2;
var R_LINECOLOR:uint = 0xffffff;
g.lineStyle(R_LINETHICK,R_LINECOLOR,R_ALPHA);
g.beginFill(R_BG,R_ALPHA);
g.drawRect(_crosshairs.x-R_SIZE/2, _crosshairs.y-R_SIZE/2,R_SIZE,R_SIZE);
g.endFill();
}
/* draw the selected region, if there is one */
if(bSet)
{
/* the selection is a data selection, so we want to makesure the region stays correct as the chart changes size and/or ranges.
* so we store it in data coordaintes. So beforewe draw it, we need to transform it back into screen coordaintes
*/
var c:Array =[{dx: dLeft, dy: dTop}, {dx:dRight, dy: dBottom}];
dataTransform.transformCache(c,"dx","x","dy","y");
/* now draw the region on screen */
g.moveTo(c[0].x,c[0].y);
g.beginFill(BOX_BG_COLOR,BOX_BG_ALPHA);
g.lineStyle(BOX_LINE_THICKNESS,BOX_LINE_COLOR);
g.drawRect(c[0].x,c[0].y,c[1].x- c[0].x, c[1].y - c[0].y);
g.endFill();
/* now we're going to draw the decorators indicating thebottom and right edges of the box
*/
g.lineStyle(BOX_RANGE_THICKNESS,BOX_RANGE_COLOR);
// draw bottom line
g.moveTo(c[0].x,c[1].y + 9);
g.lineTo(c[0].x,c[1].y + 15);
g.moveTo(c[0].x,c[1].y + 12);
g.lineTo(c[1].x,c[1].y + 12);
g.moveTo(c[1].x,c[1].y + 9);
g.lineTo(c[1].x,c[1].y + 15);
// draw right line
g.moveTo(c[1].x + 9,c[0].y);
g.lineTo(c[1].x + 15,c[0].y);
g.moveTo(c[1].x + 12,c[0].y);
g.lineTo(c[1].x + 12,c[1].y);
g.moveTo(c[1].x + 9,c[1].y);
g.lineTo(c[1].x + 15,c[1].y);
/* now we're going to position the labels at the edges ofthe box */
_labelLeft.visible =_labelRight.visible = _labelTop.visible = _labelBottom.visible = true;
_labelLeft.setActualSize(_labelLeft.measuredWidth,_labelLeft.measuredHeight);
_labelLeft.move(c[0].x -_labelLeft.width/2,c[1].y + 24);
_labelRight.setActualSize(_labelRight.measuredWidth,_labelRight.measuredHeight);
_labelRight.move(c[1].x -_labelRight.width/2,c[1].y + 24 );
_labelTop.setActualSize(_labelTop.measuredWidth,_labelTop.measuredHeight);
_labelTop.move(c[1].x +24,c[0].y - _labelTop.height/2);
_labelBottom.setActualSize(_labelBottom.measuredWidth,_labelBottom.measuredHeight);
_labelBottom.move(c[1].x +24,c[1].y - _labelBottom.height/2);
} else {
_labelLeft.visible =_labelRight.visible = _labelTop.visible = _labelBottom.visible = false;
}
}
/* to make sure we end up in any ranges autogenerated bythe axes, we need to describe our data to them
*/
override public functiondescribeData(dimension:String,requiredFields:uint):Array
{
/* if no region is selected, we have no data */
if(bSet == false)
return [];
vardd:DataDescription = new DataDescription();
if (dimension== CartesianTransform.HORIZONTAL_AXIS) {
/* describe the minimum and maximum values we need onscreen */
dd.min = dLeft;
dd.max = dRight;
if((requiredFields& DataDescription.REQUIRED_BOUNDED_VALUES) != 0)
{
/*
since we don't want our labels sticking off the edgeof the chart, we
need to ask for 'bounded values' around the selected data.
* a bounded value is a pixel margin to theleft/right of a specific data point. In this case, we'll ask for the width ofour labels
*/
dd.boundedValues = [
new BoundedValue(dLeft),
new BoundedValue(dRight,_labelLeft.width/2,24 +Math.max(_labelLeft.width,_labelRight.width))
]
}
}
else {
dd.min = dBottom;
dd.max = dTop;
if((requiredFields& DataDescription.REQUIRED_BOUNDED_VALUES) != 0)
{
/*
since we don't want our labels sticking off the edgeof the chart, we
need to ask for 'bounded values' around the selected data.
* a bounded value is a pixel margin to thetop/bottom of a specific data point. In this case, we'll ask for the height ofour labels
*/
dd.boundedValues = [
new BoundedValue(dTop),
new BoundedValue(dBottom,24 +Math.max(_labelLeft.height,_labelRight.height,_labelTop.height/2))
]
}
}
return [dd];
}
override protected function commitProperties():void
{
super.commitProperties();
/* when our data changes, we need to update the textdisplayed in our labels */
// _labelLeft.text =Math.round(dLeft).toString();
// _labelRight.text =Math.round(dRight).toString();
varstartTime:Date = new Date;
varendTime:Date = new Date;
startTime.setTime(dLeft);
startTime.setTime(dRight);
var hh1:uint =startTime.getHours();
var mm1:uint =startTime.getMinutes();
var ss1:uint =startTime.getSeconds();
var hh2:uint =endTime.getHours();
var mm2:uint =endTime.getMinutes();
var ss2:uint =endTime.getSeconds();
_labelLeft.text = zeroSpace(hh1)+":"+zeroSpace(mm1)+":"+zeroSpace(ss1);
_labelRight.text = zeroSpace(hh2)+":"+zeroSpace(mm2)+":"+zeroSpace(ss2);
_labelTop.text =Math.round(dTop).toString();
_labelBottom.text =Math.round(dBottom).toString();
}
private function zeroSpace(num:uint, space:uint=2,word:String="0"):String{
var tmpLen:uint = space - String(num).length;
var tmpStr:String="";
for(var i:uint=0;i<tmpLen;i++){
tmpStr+="0";
}
return tmpStr+num;
}
override public function mappingChanged():void
{
/*
since we store our selection in data coordinates, weneed to redraw when
the mapping between data coordinates and screen coordinateschanges
*/
invalidateDisplayList();
}
private function startTracking(e:MouseEvent) :void
{
/* the user clicked the mouse down. First, we need to addlisteners for the mouse dragging */
bTracking = true;
parentApplication.addEventListener("mouseUp",endTracking,true);
parentApplication.addEventListener("mouseMove",track,true);
/* now store off the data values where the user clickedthe mouse */
vardataVals:Array = dataTransform.invertTransform(mouseX,mouseY);
tX = dataVals[0];
tY = dataVals[1];
bSet = false;
updateTrackBounds(dataVals);
}
private function track(e:MouseEvent):void {
if(bTracking== false)
return;
bSet = true;
updateTrackBounds(dataTransform.invertTransform(mouseX,mouseY));
e.stopPropagation();
}
private function endTracking(e:MouseEvent):void
{
/* the selection is complete, so remove our listeners andupdate one last time to match the final position of the mouse */
bTracking = false;
parentApplication.removeEventListener("mouseUp",endTracking,true);
parentApplication.removeEventListener("mouseMove",track,true);
e.stopPropagation();
updateTrackBounds(dataTransform.invertTransform(mouseX,mouseY));
}
private function updateCrosshairs(e:MouseEvent):void
{
/* the mouse moved over the chart, so grab the mousecoordaintes and redraw */
_crosshairs = new Point(mouseX,mouseY);
invalidateDisplayList();
}
private function removeCrosshairs(e:MouseEvent):void
{
/* the mouse left the chart area, so throw away anystored coordinates and redraw */
_crosshairs = null;
invalidateDisplayList();
}
private function updateTrackBounds(dataVals:Array):void
{
/* store the bounding rectangle of the selection, in anormalized data-based rectangle */
dRight = Math.max(tX,dataVals[0]);
dLeft = Math.min(tX,dataVals[0]);
dBottom = Math.min(tY,dataVals[1]);
dTop = Math.max(tY,dataVals[1]);
/* invalidate our data, and redraw */
dataChanged();
invalidateProperties();
invalidateDisplayList();
}
}
}