在气象行业的等值线标注中可能会有这样的需求,在客户端对等值线进行标注,按照一点的间隔并且需要对文字做旋转角度的处理,那么在FLEX客户端应该做如何处理呢。
总体思路如下:
LabelSymbol.as继承TextSymbol
public class LabelSymbol extends TextSymbol
{
public function LabelSymbol(text:String=null, htmlText:String=null, color:uint=0, alpha:Number=1, border:Boolean=false, borderColor:uint=0, background:Boolean=false, backgroundColor:uint=16777215, placement:String="middle", angle:Number=0, xoffset:Number=0, yoffset:Number=0, textFormat:TextFormat=null, textAttribute:String=null, textFunction:Function=null)
{
super(text, htmlText, color, alpha, border, borderColor, background, backgroundColor, placement, angle, xoffset, yoffset, textFormat, textAttribute, textFunction);
}
private var _sText:String;
public function get sText():String
{
return _sText;
}
public function set sText(value:String):void
{
_sText = value;
this.text=value;
}
public function get TextRotation():Number
{
return _TextRotation;
}
public function set TextRotation(value:Number):void
{
_TextRotation = value;
this.angle=value;
}
private var _TextRotation:Number;
}
IsolineTextLabels.as线上标注点的获取以及文字角度的获取
package IDW
{
import com.esri.ags.FeatureSet;
import com.esri.ags.Graphic;
import com.esri.ags.geometry.Extent;
import com.esri.ags.geometry.MapPoint;
import com.esri.ags.geometry.Polyline;
import flash.text.TextFormat;
public class IsolineTextLabels
{
public function IsolineTextLabels()
{
}
private static var _wayBeforeText:Number = 0.1;
public static function get wayBeforeText():Number
{
return _wayBeforeText;
}
public static function set wayBeforeText(value:Number):void
{
_wayBeforeText = value;
}
/**
* 返回两点距离
* @param x1
* @param y1
* @param x2
* @param y2
* @return
*
*/
public static function GetDistance( x1:Number, y1:Number,x2:Number,y2:Number):Number
{
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
/**
* 根据角度象限返回文本旋转角度
* @param x1
* @param y1
* @param x2
* @param y2
* @return
*
*/
public static function GetTxtRotation(x1:Number,y1:Number,x2:Number,y2:Number):Number
{
var dx:Number = Math.abs(x2 - x1);
var dy:Number = Math.abs(y2 - y1);
var r:Number = (Math.atan2(dy, dx) * 180 / Math.PI);
if (x1 <= x2 && y1 <= y2) //1
{
r = 360 - r;
}
else if (x1 >= x2 && y1 <= y2) //2
{
}
else if (x1 >= x2 && y1 >= y2)//3
{
r = 360 - r;
}
else if (x1 <= x2 && y1 <= y2)//4
{
}
return r;
}
public static function Annotate(lines:FeatureSet, visible:Extent):Vector.<Graphic>
{
var res:Vector.<Graphic> = new Vector.<Graphic>();
for each (var pc:Graphic in lines.features)
{
var way:Number = 0;
var tem:Polyline=Polyline(pc.geometry);
for each(var arr:Array in tem.paths)
{
for (var i:int = 1; i <arr.length;i++)
{
var length:Number=GetDistance(arr[i-1].x,arr[i-1].y,arr[i].x,arr[i].y);
way =way+length;
if (way > visible.width * wayBeforeText)
{
way = 0;
var _G:Graphic = new Graphic();
_G.geometry=arr[i];
var Symbol:LabelSymbol= new LabelSymbol();
Symbol.sText=(arr[i] as MapPoint).z.toFixed(2);
var txtf:TextFormat=new TextFormat();
txtf.font="Arial";
txtf.size=10;
Symbol.textFormat=txtf;
Symbol.background=true;
Symbol.backgroundColor=0xffffff;
Symbol.TextRotation=GetTxtRotation(arr[i-1].x, arr[i-1].y, arr[i].x, arr[i].y)
_G.symbol=Symbol;
var obj:Object=new Object();
obj.Z=(arr[i] as MapPoint).z;
_G.attributes=obj;
res.push(_G);
}
}
}
}
return res;
}
}
}
IoslineSymbolGraphicsLayer继承GraphicsLayer用户最终展示
package IDW
{
import com.esri.ags.FeatureSet;
import com.esri.ags.Graphic;
import com.esri.ags.events.ExtentEvent;
import com.esri.ags.geometry.Polyline;
import com.esri.ags.layers.GraphicsLayer;
import mx.events.FlexEvent;
import mx.formatters.DateFormatter;
public class IoslineSymbolGraphicsLayer extends GraphicsLayer
{
public var SoureFeatureSet:FeatureSet;
private static var UpdateCount:uint=1;
public function IoslineSymbolGraphicsLayer(fs:FeatureSet)
{
SoureFeatureSet=fs;
super();
this.addEventListener(FlexEvent.INITIALIZE,IsolineGraphicLayer_Initialized);
}
private function IsolineGraphicLayer_Initialized(event:FlexEvent):void
{
var df:DateFormatter=new DateFormatter();
df.formatString="YYYY-MM-DD JJ:NN:SS:QQQ";
trace("第一次开始"+df.format(new Date()));
UpdateLabel();
trace("第一次结束"+df.format(new Date()));
this.map.addEventListener(ExtentEvent.EXTENT_CHANGE,Map_ExtentChanged);
}
private function Map_ExtentChanged(event:ExtentEvent):void
{
UpdateCount=UpdateCount+1;
var df:DateFormatter=new DateFormatter();
df.formatString="YYYY-MM-DD JJ:NN:SS:QQQ";
trace("第"+UpdateCount+"次更新开始"+df.format(new Date()));
UpdateLabel();
trace("第"+UpdateCount+"次更新结束"+df.format(new Date()));
}
private function UpdateLabel():void
{
this.clear();
var fs:FeatureSet=SoureFeatureSet;
var labels:Vector.<Graphic> = IsolineTextLabels.Annotate(fs, this.map.extent);
for each (var _G2:Graphic in labels)
{
this.add(_G2);
}
}
}
}
FlexIosSymbol.mxml 测试客户端
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:esri="http://www.esri.com/2008/ags" xmlns:IDW="IDW.*">
<fx:Script>
<![CDATA[
import IDW.IoslineSymbolGraphicsLayer;
import com.esri.ags.FeatureSet;
import com.esri.ags.events.MapEvent;
import com.esri.ags.geometry.MapPoint;
import mx.collections.ArrayCollection;
protected function button1_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
var fs:FeatureSet= new FeatureSet();
var arr:Array=new Array();
for (var i:int;i<flayer.graphicProvider.length;i++)
{
arr.push(flayer.graphicProvider[i]);
}
fs.features=arr;
var ioslayer:IoslineSymbolGraphicsLayer=new IoslineSymbolGraphicsLayer(fs);
myMap.addLayer(ioslayer);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:Button label="测试" click="button1_clickHandler(event)">
</s:Button>
<esri:Map id="myMap" top="30" >
<esri:ArcGISDynamicMapServiceLayer url="http://localhost:6080/arcgis/rest/services/MyMap/MapServer">
</esri:ArcGISDynamicMapServiceLayer>
<esri:FeatureLayer id="flayer" url="http://localhost:6080/arcgis/rest/services/MyMap/MapServer/0">
</esri:FeatureLayer>
</esri:Map>
</s:Application>
最终测试效果如下: