应用程序
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
xmlns:degrafa="com.degrafa.*"
xmlns:paint="com.degrafa.paint.*"
xmlns:geometry="com.degrafa.geometry.*" viewSourceURL="srcview/index.html"
backgroundColor="#ffffff" xmlns:local="*"
creationComplete="inipolyline()" xmlns:text="flash.text.*">
<degrafa:Surface id="asur">
<!-- Creating fills. -->
<degrafa:fills>
<paint:SolidFill id="blue"
color="#62ABCD"/>
</degrafa:fills>
<!-- Creating Strokes. -->
<degrafa:strokes>
<paint:SolidStroke id="black"
color="#000000"
alpha="1"
weight="3"/>
<paint:SolidStroke id="red"
color="#FF0000"
alpha="1"
weight="3"/>
</degrafa:strokes>
<!-- Creating Polyline-->
<!-- Creating a Geometry Group. -->
<degrafa:GeometryGroup x="0" y="0">
<!-- Creating a Polygon. -->
<geometry:Polyline stroke="{black}">
<geometry:data>0,0 0,20 20,20 20,40 40,40 40,60</geometry:data>
</geometry:Polyline>
</degrafa:GeometryGroup>
<!--自定义曲线-->
<degrafa:GeometryGroup x="0" y="100" id="geopolytl"/>
</degrafa:Surface>
<mx:Button click="deletepolyline()" label="deletepolyline" x="100" y="0"/>
<mx:Script>
<![CDATA[
import com.degrafa.GraphicText;
import com.degrafa.IGeometry;
public function deletepolyline():void
{
for each(var g:GeometryGroup in asur.graphicsCollection.items)
{
g.target = null;
g.visible = false;
for each(var o:IGeometry in g.geometryCollection.items)
{
o.data = "";
g.geometryCollection.removeItem(o);
}
g.geometry.length = 0;
g = null;
}
asur.graphicsCollection.items.length = 0;
}
public function inipolyline():void
{
var polytl: DashedPolylinetl= new DashedPolylinetl();
polytl.dash=10;
polytl.gap=4;
polytl.style=2;
var datastl:String="0,0 0,20 20,20 20,40 40,40 40,60 60,60 60,0 ";
polytl.data=datastl;
polytl.colour=0x1f1fd5;
geopolytl.geometryCollection.addItem(polytl);
}
]]>
</mx:Script>
</mx:Application>
自定义的类dashpolylinet1
package
{
import com.degrafa.core.collections.GraphicPointCollection;
import com.degrafa.geometry.Polyline;
import flash.display.Graphics;
import flash.geom.Rectangle;
import mx.events.PropertyChangeEvent;
public class DashedPolylinetl extends Polyline
{
/**
* 构造函数,其中定义了style属性的change事件
* */
public function DashedPolylinetl(points:Array=null)
{
super(points);
addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,redraw);
}
/**
* commandstack用于存储直线绘制信息,主要是moveto和lineto命令
**/
public var commandstack:Array = new Array();
private var _points:GraphicPointCollection;
public var _bounds:Rectangle=new Rectangle();
override public function get points():Array{
if(!_points){_points = new GraphicPointCollection();}
return _points.items;
}
override public function set points(value:Array):void{
if(!_points){_points = new GraphicPointCollection();}
_points.items = value;
//add a listener to the collection
if(_points && enableEvents){
_points.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
}
invalidated = true;
}
/**
* 计算dashpolyline的外接矩形
**/
private function calcBounds():void{
var boundsMaxX:Number =0;
var boundsMaxY:Number =0;
var boundsMinX:Number =Number.MAX_VALUE;
var boundsMinY:Number =Number.MAX_VALUE;
for (var i:int = 0;i< _points.items.length; i++)
{
boundsMaxX = Math.max(boundsMaxX, _points.items[i].x);
boundsMaxY = Math.max(boundsMaxY, _points.items[i].y);
boundsMinX= Math.min(boundsMinX, _points.items[i].x);
boundsMinY= Math.min(boundsMinY, _points.items[i].y);
}
_bounds = new Rectangle(boundsMinX,boundsMinY,boundsMaxX-boundsMinX,boundsMaxY-boundsMinY);
}
public var length:Number;
private var _dash:Number;
/**
* 每段直线的长度,默认值为0
**/
public function get dash():Number
{
if (!_dash)
return 0;
return _dash;
}
public function set dash(value:Number):void
{
if (_dash != value)
{
_dash = value;
if (gap == 0)
gap = value;
invalidated = true;
}
}
private var _style:int;
public function get style():int
{ if(!_style)
return 0;
return _style;
}
/**
* 在style属性change之后分发PropertyChangeEvent事件
**/
public function set style(value:int):void
{
if(_style != value)
{
_style=value;
invalidated= true;
}
dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE,false,false, null,int,null,null,this.style));
}
private var _gap:Number;
/**
*每段直线之间的距离,默认值为0
**/
public function get gap():Number
{
if (!_gap)
return 0;
return _gap;
}
public function set gap(value:Number):void
{
if (_gap != value)
{
_gap = value;
invalidated = true;
}
}
private var _colour:uint;
/**
*线的颜色
**/
public function get colour():uint
{
if (!_colour)
return 0;
return _colour;
}
public function set colour(value:uint):void
{
if (_colour != value)
{
_colour = value;
invalidated = true;
}
}
/**
* 用于绘制之前的指令算法存储至commandstack数组中
* 根据style值,重组绘制线的数据;
* style=4,线形为直线,无论如何设置dash,gap,都按照原始data两点一连画直线;
* style=0,线形为虚线,dash为虚线线段长,gap为虚线间隔,根据二者对原始data进行重组,新的data数据点数大于原始data点个数;
* 要保证虚线效果,dash+gap必须小于线任意两点间隔或最小距离两点间的距离
* style=2,线形为虚线并且间隔中有两点,dash为虚线线段长,gap为虚线间隔,根据二者对原始data进行重组,新的data数据点数大于原始data点个数;
* 要保证效果,该线形适用于数据点任意两点距离大于20的data,线中dash+gap必须小于线任意两点间隔或最小距离两点间的距离,
* gap中画了两个点,其位置和gap,dash都有关系,两点距离为20时,dash=10,gap=10,能看到两点效果;算法需要继续改进
* style=3,线形为虚线并且间隔中有一点,dash为虚线线段长,gap为虚线间隔,根据二者对原始data进行重组,新的data数据点数大于原始data点个数;
* 要保证效果,该线形适用于数据点任意两点距离大于20的data,线中dash+gap必须小于线任意两点间隔或最小距离两点间的距离,
* gap中画了一个点,其位置和gap,dash都有关系,两点距离为20时,dash=5,gap=5,能看到效果;算法需要继续改进
* style=1,线形为铁路线,算法有问题,无法画出来效果图
**/
override public function preDraw():void
{
if(invalidated)
{
super.preDraw();
if(points.length==0){ return;}
commandstack.length=0;
commandstack.push({type:"m",x:points[0].x+x,y:points[0].y+y});
//如果style=4,即使设置了dash,gap,它们也不起作用
if (style==4)
{
for (var i:int = 0;i < points.length; i++)
{
commandstack.push({type:"l",x:points[i].x+x,y:points[i].y+y});
}
}
else
{
for (var j:int = 0;j < points.length-1; j++)
switch(style)
{
case 0:
addDashCommands0(commandstack, points[j].x+x, points[j].y+y,points[j+1].x+x, points[j+1].y+y);
break;
case 1:
addDashCommands1(commandstack, points[j].x+x, points[j].y+y,points[j+1].x+x, points[j+1].y+y);
break;
case 2:
case 3:
addDashCommands2(commandstack, points[j].x+x, points[j].y+y,points[j+1].x+x, points[j+1].y+y);
break;
default: break;
}
}
/**
* 用于封闭的polyline
* */
if(autoClose)
{
commandstack.push({type:"l",x:points[0].x+x,y:points[0].y+y});
}
calcBounds();
invalidated = false;
}
}
protected var leftOver:int = 0;
protected var leftOverCount:int = 0;
/**
*绘制虚线的commandstack命令
**/
protected function addDashCommands0(commandstack:Array, x1:int, y1:int, x2:int, y2:int):void
{
var length:Number = Math.abs(Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2))); //线段长度
var count:int = leftOverCount;
var currentLength:int = 0; //当前长度
var ratio:Number = 1; //比例
while (currentLength < length)
{
// 绘制直线
if (count % 2 == 0)
{
currentLength += dash - leftOver;
ratio = Math.min(1,(currentLength / length));
commandstack.push({type:"l",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
}
else
{
currentLength += gap - leftOver;
ratio = Math.min(1,(currentLength / length));
commandstack.push({type:"m",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
}
if (currentLength > length)
{
leftOver = ((count % 2 == 0) ? dash : gap) - (currentLength - length);
leftOverCount = count;
}
else
{
leftOver = 0;
leftOverCount = 0;
}
count++;
}
}
/**
* 绘制铁路线的commandstack命令
**/
protected function addDashCommands1(commandStack:Array, x1:int, y1:int, x2:int, y2:int):void
{
var length:Number = Math.abs(Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2))); //线段长度
var count:int = leftOverCount;
var currentLength:int = 0; //当前长度
var ratio:Number = 1; //比例
while (currentLength < length)
{
// dash
if (count % 2 == 0)
{
currentLength += dash - leftOver;
ratio = Math.min(1,(currentLength / length));
commandStack.push({type:"l",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
}
else
{
currentLength += gap - leftOver;
ratio = Math.min(1,(currentLength / length));
commandStack.push({type:"mm",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
}
if (currentLength > length)
{
leftOver = ((count % 2 == 0) ? dash : gap) - (currentLength - length);
leftOverCount = count;
}
else
{
leftOver = 0;
leftOverCount = 0;
}
count++;
}
}
/**
* 绘制单点线或者双点线的commandstack命令
**/
protected function addDashCommands2(commandstack:Array, x1:int, y1:int, x2:int, y2:int):void
{
length= Math.abs(Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2))); //线段长度
var count:int = leftOverCount;
var currentLength:int = 0; //当前长度
var ratio:Number = 1; //比例
while (currentLength < length)
{
// dash
if (count % 2 == 0)
{
currentLength += dash - leftOver;
ratio = Math.min(1,(currentLength / length));
commandstack.push({type:"l",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio),x0:x2-x1,y0:y2-y1,xd:((x2-x1)*ratio),yd:((y2-y1)*ratio)});
}
else
{
currentLength += gap - leftOver;
ratio = Math.min(1,(currentLength / length));
commandstack.push({type:"m",x:x1 + ((x2-x1)*ratio),y:y1 + (y2-y1)*ratio});
}
if (currentLength > length)
{
leftOver = ((count % 2 == 0) ? dash : gap) - (currentLength - length);
leftOverCount = count;
}
else
{
leftOver = 0;
leftOverCount = 0;
}
count++;
}
}
/**
* 根据style参数来绘制不同的线型
**/
private var item:Object;
private var lengths:Number;
private var sin:Number;
private var cos:Number;
private var xx0:Number;
private var yy0:Number;
private var xx:Number;
private var yy:Number;
private var dx:Number;
private var dy:Number;
override public function draw(graphics:Graphics,rc:Rectangle):void{
preDraw();
if(!rc)
super.draw(graphics,_bounds);
else
super.draw(graphics,rc);
for each (item in commandstack)
{
graphics.lineStyle(0.1,colour,1);
lengths=Math.abs(Math.sqrt(Math.pow(item.x0, 2) + Math.pow(item.y0, 2)))
sin=item.x0/lengths;//直线的sin值
cos=item.y0/lengths; //直线的cos值
xx0=item.x+dash*sin/4; //单点直线的x-coordinate起始位置
yy0=item.y+dash*cos/4; //单点直线的y-coordinate结束位置
xx=item.x+dash*sin/2; //双点直线的x-coordinate起始位置
yy=item.y+dash*cos/2; //双点直线的y-coordinate结束位置
dx=(item.x0==0?0:(item.x0)/Math.abs(item.x0));//中间变量,即点的x-coordinate移动距离(取值为0,1,-1)
dy=(item.y0==0?0:(item.y0)/Math.abs(item.y0));//中间变量,即点的y-coordinate移动距离(取值为0,1,-1)
if(item.type=="m")
graphics.moveTo(item.x,item.y);
else
switch(style)
{
//绘制虚线的算法
case 0:
//绘制实线的算法
case 4:
{
graphics.lineTo(item.x,item.y);
break;
}
case 1: //绘制铁路线(或者变色线的算法)
{
//graphics.moveTo(item.x,item.y);
if(item.type=="mm")
{
graphics.lineStyle(1,0xff0000,1,true);
graphics.lineTo(item.x,item.y);
}
else
{
graphics.lineStyle(1,0x000000,1,true);
graphics.lineTo(item.x,item.y);
}
break;
}
case 2: //绘制双点线型的算法
{
graphics.lineTo(item.x,item.y);
if((Math.abs(xx+dx)<=Math.max(Math.abs(item.x),Math.abs(item.x+item.x0-item.xd)))&&(Math.abs(yy+dy)<=Math.max(Math.abs(item.y),Math.abs(item.y+item.y0-item.yd))))
{
graphics.moveTo(xx0,yy0);
graphics.lineTo(xx0+dx,yy0+dy);//绘制单点,即利用lineto来绘制直线
graphics.moveTo(xx,yy);
graphics.lineTo(xx+dx,yy+dy); //绘制双点,即利用lineto来绘制直线
}
break;
}
case 3: //绘制单点线型的算法
{
graphics.lineTo(item.x,item.y); //设置线条样式,绘制直线
//判断点的绘制是否执行,当点直线x-coordinate和y-coordinate的起始位置在直线之内则绘制单点
if((Math.abs(xx)<=Math.max(Math.abs(item.x),Math.abs(item.x+item.x0-item.xd)))&&(Math.abs(yy)<=Math.max(Math.abs(item.y),Math.abs(item.y+item.y0-item.yd))))
{
graphics.moveTo(xx,yy);
graphics.lineTo(xx+dx,yy+dy); //绘制单点,即利用lineto来绘制直线
}
break;
}
}
}
super.endDraw(graphics);
}
/**
* 当style属性发生change则调用重绘函数,能够及时的响应线型改变进行重绘(由于会产生bug导致暂时屏蔽重绘功能,因为会报ss引用为Null)
* */
public function redraw(e:PropertyChangeEvent):void
{
// draw(ss.graphics,null);
}
public function commandstackclear():void
{
}
}
}