本例主要实现在APP中解析GML数据并显示
GML,地理标记语言(外语全称:Geography MarkupLanguage、外语缩写:GML),它由开放式地理信息系统协会(外语缩写:OGC)于1999年提出,并得到了许多公司的大力支持,如Oracle、Galdos、MapInfo、CubeWerx等。GML能够表示地理空间对象的空间数据和非空间属性数据
实现思路
GML文档解析
GML文档的本质还是Xml文档,所以可以用Xml解析器进行解析,在Android中可以使用自带的XmlPullParser进行解析,当然你也可以用SAX解析器可DOM解析器。在GML文档中有两种属性,一类是空间属性,另外一个就是非空间属性。其中空间属性是至关重要的,因为要进行地图显示必须要用空间属性;而非空间属性可以不用,但是由于要进行查询操作,所以我将非空间属性也进行存储。
在读GML文档时,首先读取图层,然后判断图层中的属性都有哪些,如果是非空间属性,将其存储起来(我用的是Sqlite数据库),如果是空间属性,那么第一个空间属性肯定是关于图层类型的,即他是Polygen,Polyline或是Point,然后在或标签下存储的位置信息,将位置信息存储起来即可。
以上就是大致的读取GML文档的思路。
地图显示
地图显示的方法有很多种,我简单介绍两种,一种是使用画布canvas进行绘制,另外一种就是使用SVG进行显示。由于我的水平有限,想不出解决canvas加载重绘时卡顿的问题,所以我就使用svg进行显示,使用svg最大的好处就是只在首次使用的时候生成SVG文件而花费的时间较长,而在之后的使用中加载时间在1s以内;另外就是使用svg进行功能实现时不会出现卡顿或者说是卡顿比前一种方法小的多。(在文件夹中包含的使用canvas绘制的工程是我找我的学长要的,哈哈)。
关于SVG大家有不明白的直接去百度,那里面比我讲的清楚的多,在写SVG的时候注意下面几个事项就行:
由于GML文件里面位置数据过大,所以需要在SVG中设置ViewBox保证地图能够全部显示(关于ViewBox也去百度吧)。
坐标转换,在GML中默认的坐标原点是左下角,而SVG的坐标原点是左上角,这点我想大家都因应该在之前接触过,所以需要进行坐标转换,就是进行垂直翻转而已。最初我使用的方法是将每个坐标的纵坐标变成相反数,然后就导致写SVG文件花了2分钟……。这样当然不行啊,找别的方法吧,后来终于找到个好办法,用矩阵变换,就是SVG里面的matrix属性,一下就变成10s以内,真是……
图层顺序,写SVG的时候图层显示应该按照面线点文字的顺序,这样可以保证所有图层都能够显示
参考链接
理解SVG坐标系统和变换: transform属性 - 推酷
功能实现
因为我用的SVG,所以没必要再进行SVG解析,直接用浏览器就可以查看,所以我只需要实现一个浏览器的功能就行了,用WebView控件,由于SVG的放大缩小平移可以用Javascript实现,所以我的所有功能都是在Javascript中的。但是在Android里面直接加载SVG文件会导致Javascript失效,所以用html内联SVG,这个也不再多说,大家参考html文件即可。
放大缩小:放大缩小的功能就是变化ViewBox即可,大家可以参考文件夹里面的js文件。
平移:平移功能要重写WebView的ontouch事件,然后再调用Javascript函数,具体也不多说,大家自己看吧。
搜索:搜索分为两部分,首先是从数据库中按照搜索条件查询出对象的ID,然后调用Javascript搜索的相关函数搜索出SVG中对应的对象。
参考链接
Android WebView 开发详解(一) - typename 记录点滴 - 博客频道 - CSDN.NET
实现
第一次进入应用时,先解析GML,将数据存储在数据库中,生成SVG,用webView显示HTML来显示SVG,在里面用JS实现一些功能控制,第二次进入时直接加载SVG即可
主Activity
package com.gmlmap.activity;import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;import com.gmlmap.data.LayerInfo;
import com.gmlmap.readfile.GmlPullParser;
import com.gmlmap.readfile.SvgWrite;
import com.gmlmap.util.SetViewHeight;
import com.gmlmap.util.SharedUtils;
import com.gmlmap.view.DrawerGarment;
import com.gmlmap.view.DrawerGarment.IDrawerCallbacks;import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;public class Activity_Main extends Activity {private ProgressDialog dialog;private WebView m_webview;private Button m_btzoomin;private Button m_btzoomout;private Button m_btser;private EditText m_edit;private GestureDetector mGestureDetector;//抽屉使用private DrawerGarment mDrawerGarment;private TextView mButton;private TextView m_text;private ListView m_listview;private MAdapter m_adapter;private ArrayList<LayerInfo> m_layers;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.activity_main);getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title); //titlebar为自己标题栏的布局getSvg();}private void InitCtView(){mDrawerGarment = new DrawerGarment(this, R.layout.drawer);m_layers=SharedUtils.getLayers(getApplicationContext(), "TestData");m_text=(TextView)this.findViewById(R.id.textView1);m_text.setText("图层");m_listview=(ListView)this.findViewById(R.id.listview);m_adapter=new MAdapter(this,m_layers);m_listview.setAdapter(m_adapter);SetViewHeight.setLvHeight(m_listview);mDrawerGarment.setDrawerCallbacks(new IDrawerCallbacks() {@Overridepublic void onDrawerOpened() {}@Overridepublic void onDrawerClosed() {}});mButton = (TextView) findViewById(R.id.bt_chou);mButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mDrawerGarment.toggleDrawer();}});}String move="";@SuppressLint("SetJavaScriptEnabled")private void initwebview() {m_webview = (WebView) findViewById(R.id.webview);WebSettings webSettings = m_webview.getSettings();webSettings.setLoadWithOverviewMode(true);webSettings.setJavaScriptEnabled(true);m_webview.setWebViewClient(new WebViewClient());m_webview.setWebChromeClient(new WebChromeClient());// SVG图所在路径String svg_path="file:///mnt/sdcard/GmlParser/TestData/index.html";m_webview.loadUrl(svg_path);mGestureDetector = new GestureDetector(this, new MyOnGestureListener());m_webview.setOnTouchListener(new OnTouchListener(){@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubmGestureDetector.onTouchEvent(event);return true;}});m_edit=(EditText)this.findViewById(R.id.edittext);m_btzoomin=(Button)this.findViewById(R.id.mapzoomin);m_btzoomout=(Button)this.findViewById(R.id.mapzoomout);m_btser=(Button)this.findViewById(R.id.bt_search);m_btser.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString co=m_edit.getText().toString();if(co.equals(""))Toast.makeText(getApplicationContext(), "输入不能为空",Toast.LENGTH_SHORT).show();else{String id=SharedUtils.getOid(getApplicationContext(), "TestData", co);if(id.equals(""))Toast.makeText(getApplicationContext(), "没有搜索到结果",Toast.LENGTH_SHORT).show();elsem_webview.loadUrl("javascript:searchByid('"+id+"')");m_edit.setText("");}}});m_btzoomin.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubm_webview.loadUrl("javascript:ZoomIn()");}});m_btzoomout.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubm_webview.loadUrl("javascript:ZoomOut()");}});}private boolean GmlRead() {boolean result = false;try {InputStream is = getAssets().open("TestData.gml");result = GmlPullParser.parse(is, "TestData", this);} catch (IOException e) {// TODO Auto-generated catch blockresult = false;}return result;}// Handler@SuppressLint("HandlerLeak")Handler handler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 0:initwebview();InitCtView();break;case 1:Toast.makeText(getApplicationContext(), "Gml解析发生错误", Toast.LENGTH_SHORT).show();break;case 2:Toast.makeText(getApplicationContext(), "Svg生成发生错误", Toast.LENGTH_SHORT).show();break;}dialog.dismiss();}};class mainThread implements Runnable {@Overridepublic void run() {Message msg = handler.obtainMessage();if (GmlRead()) {SvgWrite m_writer = new SvgWrite(Activity_Main.this);if (m_writer.Write())msg.what = 0;// SVG生成成功elsemsg.what = 2;// svg生成失败} elsemsg.what = 1;// gml解析失败handler.sendMessage(msg);}}private void getSvg() {if (SharedUtils.getBooleanValue(Activity_Main.this, "isStored", false)&& SharedUtils.getBooleanValue(Activity_Main.this, "isSvg",false)) {initwebview();InitCtView();}else {Toast.makeText(getApplicationContext(), "首次进入系统会花费5~20秒的时间进行数据解析,请勿退出~!",Toast.LENGTH_LONG).show();/*** 进度条*/dialog = new ProgressDialog(Activity_Main.this,ProgressDialog.THEME_HOLO_LIGHT);dialog.setMessage("正在解析GML并生成SVG,请稍后……");dialog.setCanceledOnTouchOutside(false);dialog.show();Thread mainThread = new Thread(new mainThread());// CheckNetworkState();mainThread.start();}}public class MAdapter extends BaseAdapter {private ArrayList<LayerInfo> layers;private ArrayList<Boolean> status;private LayoutInflater m_listContainer; // 视图容器private Context context;class Views{CheckBox m_check;LinearLayout button;}public MAdapter(Context context,ArrayList<LayerInfo> mlayers){this.context=context;layers=mlayers;status=new ArrayList<Boolean>();m_listContainer = LayoutInflater.from(context); // 创建视图容器并设置上下文}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn layers.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn layers.get(arg0);}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn arg0;}@Overridepublic View getView(int arg0, View arg1, ViewGroup arg2) {// TODO Auto-generated method stubViews m_views;if (arg1 == null) {arg1 = m_listContainer.inflate(R.layout.listdetail,null);m_views=new Views();m_views.m_check = (CheckBox) arg1.findViewById(R.id.checkbox);//m_views.button=(LinearLayout)arg1.findViewById(R.id.bt_attr);m_views.m_check.setText(layers.get(arg0).Lname);m_views.m_check.setTag(arg0);//m_views.button.setTag(layers.get(arg0).Lid);status.add(false);arg1.setTag(m_views);} else {m_views = (Views) arg1.getTag();}m_views.m_check.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {m_webview.loadUrl("javascript:changeVisible('L_"+v.getTag()+"')");}});/*m_views.button.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubIntent intent=new Intent(Activity_Main.this,Activity_attr.class);intent.putExtra("name", "L_"+v.getTag());startActivity(intent);}});*/return arg1;}}class MyOnGestureListener extends SimpleOnGestureListener{//滑动 Drag@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {m_webview.loadUrl("javascript:scrool("+distanceX+","+distanceY+")");return false;}@Overridepublic boolean onDoubleTap(MotionEvent e) {m_webview.loadUrl("javascript:ZoomIn()");return false;}//抬起@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return false;}@Overridepublic void onShowPress(MotionEvent e) {}@Overridepublic boolean onDown(MotionEvent e) {return false;}}}
首先解析GML
package com.gmlmap.readfile;import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;import com.gmlmap.data.LayerInfo;
import com.gmlmap.data.PosInfo;
import com.gmlmap.util.SharedUtils;import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Xml;public class GmlPullParser {public static String GML_PREFIX="http://www.opengis.net/gml" ;public final static int CASE_NORMAL=0; //一般情况,不进行任何操作,直接跳public final static int CASE_FIRSTREAD=1; //第一次读featureMember,即读取图层的第一个要素public final static int CASE_READ=2; //读取图层的第二个以后的要素public final static int CASE_READLNAME=3; //读取图层名称public static String SQL_NORMAL_INSERT="insert into";public static String SQL_NORMAL_CREATE="CREATE TABLE";public static boolean parse(InputStream is,String filename,Context context){boolean result=false;SharedUtils.StorePreferences(context, "filename", filename);ArrayList<String> AttrNames=new ArrayList<String>();LayerInfo m_layerinfo=new LayerInfo();PosInfo m_posinfo=new PosInfo();int m_curCondition=CASE_NORMAL;//当前位置//打开或创建数据库 SQLiteDatabase db = context.openOrCreateDatabase(filename+".db", Context.MODE_PRIVATE, null); db.beginTransaction();db.execSQL("DROP TABLE IF EXISTS LayersInfo"); db.execSQL("create table LayersInfo (Lid INTEGER primary key,Lname VARCHAR(20),Ltype INTEGER)");db.execSQL("DROP TABLE IF EXISTS FeaturePositon"); db.execSQL("create table FeaturePositon (Pid INTEGER primary key,Lid INTEGER,OBJECTID INTEGER,Pos TEXT)");//创建xml pull解析器XmlPullParser parser = Xml.newPullParser();try {parser.setInput(is, "UTF-8");int eventType = parser.getEventType();while (eventType!=XmlPullParser.END_DOCUMENT) {switch (eventType) {case XmlPullParser.START_DOCUMENT:break;case XmlPullParser.START_TAG:if (parser.getName().equals("featureMember")) {m_curCondition=CASE_READLNAME;}else if(parser.getName().equals("lowerCorner")){eventType=parser.next();SharedUtils.StorePreferences(context,"lowerCorner",parser.getText());}else if(parser.getName().equals("upperCorner")){eventType=parser.next();SharedUtils.StorePreferences(context,"upperCorner",parser.getText());}else if(m_curCondition!=CASE_NORMAL && parser.getNamespace().equals(GML_PREFIX)){m_layerinfo.Ltype=getLayerType(parser.getName());eventType = parser.next();while (eventType!=XmlPullParser.END_DOCUMENT) {if(parser.getName()!=null && parser.getName().contains("pos")){eventType = parser.next();m_posinfo.Pos=parser.getText();db.execSQL(m_posinfo.insertData());m_posinfo.Pid++;break;}elseeventType = parser.next();}} else{switch(m_curCondition){case CASE_READLNAME:if(!parser.getName().equals(m_layerinfo.Lname)){m_layerinfo.Lid++;m_layerinfo.Ltype=-1;m_posinfo.Lid=m_layerinfo.Lid;m_layerinfo.Lname=parser.getName();m_curCondition=CASE_FIRSTREAD;AttrNames.removeAll(AttrNames);}elsem_curCondition=CASE_READ;m_layerinfo.InitInfo();break;case CASE_FIRSTREAD:boolean ifObj=false;m_layerinfo.AddInsertName(parser.getName());AttrNames.add(parser.getName());if(parser.getName().equals("OBJECTID"))ifObj=true;elsem_layerinfo.AddCreate(parser.getName());eventType = parser.next();m_layerinfo.AddInsertValue(parser.getText());if(ifObj)m_posinfo.OBJECTID=Integer.parseInt(parser.getText());break;case CASE_READ:if(AttrNames.contains(parser.getName())){boolean ifObj2=false;if(parser.getName().equals("OBJECTID"))ifObj2=true;m_layerinfo.AddInsertName(parser.getName());eventType = parser.next();m_layerinfo.AddInsertValue(parser.getText());if(ifObj2)m_posinfo.OBJECTID=Integer.parseInt(parser.getText());}break;}}break;case XmlPullParser.END_TAG:if (parser.getName().equals("featureMember")) {if(m_curCondition==CASE_FIRSTREAD){db.execSQL("DROP TABLE IF EXISTS L_"+m_layerinfo.Lid);db.execSQL(m_layerinfo.getCreateInfo());db.execSQL(m_layerinfo.insertData());}db.execSQL(m_layerinfo.getInsertInfo());}break;case XmlPullParser.END_DOCUMENT:break;}eventType = parser.next();}//关闭当前数据库 db.setTransactionSuccessful(); db.endTransaction(); db.close(); result=true;SharedUtils.StorePreferences(context, "isStored", true);} catch (XmlPullParserException e) {// TODO Auto-generated catch blockdb.close();result=false;} catch (IOException e) {// TODO Auto-generated catch blockdb.close();result=false;} return result;}/** 获取图层的类型,-1表示非空间信息,0表示Point,1表示PolyLine,2表示PolyGen*/private static int getLayerType(String name){name=name.toLowerCase();int result=-1;if(name.contains("point"))result=0;else if(name.contains("curve") || name.contains("line") || name.contains("polyline"))result=1;else if(name.contains("surface") || name.contains("polygon"))result=2;return result;}}
生成SVG
package com.gmlmap.readfile;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;import com.gmlmap.activity.Activity_Main;
import com.gmlmap.data.LayerInfo;
import com.gmlmap.util.SharedUtils;
import com.gmlmap.util.SvgUtils;import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.widget.Toast;public class SvgWrite {private Context context;private StringBuilder m_buffer = null;private List<LayerInfo> m_layerinfos;private String folderName = "";public SvgWrite(Context context) {this.context = context;}/** 创建文件夹*/private void createFolder(String foldername) {String pathUrl = Environment.getExternalStorageDirectory().getPath()+ "/GmlParser/" + foldername;File file = new File(pathUrl);if (!file.exists())file.mkdirs();copy("htmfuc.js", pathUrl);copy("index.html", pathUrl);}/*** * @param ASSETS_NAME* 要复制的文件名* @param savePath* 要保存的路径 testCopy(Context context)是一个测试例子。*/private void copy(String ASSETS_NAME, String savePath) {String filename = savePath + "/" + ASSETS_NAME;File dir = new File(savePath);// 如果目录不中存在,创建这个目录if (!dir.exists())dir.mkdir();try {if (!(new File(filename)).exists()) {InputStream is = context.getResources().getAssets().open(ASSETS_NAME);FileOutputStream fos = new FileOutputStream(filename);byte[] buffer = new byte[7168];int count = 0;while ((count = is.read(buffer)) > 0) {fos.write(buffer, 0, count);}fos.close();is.close();}} catch (Exception e) {e.printStackTrace();}}public void deleteFile(File file) {if (file.exists()) { // 判断文件是否存在if (file.isFile()) { // 判断是否是文件file.delete(); // delete()方法 你应该知道 是删除的意思;}} }/** 创建文件*/public boolean createFile(String foldername) {boolean result = false;File fileRoot = new File(Environment.getExternalStorageDirectory().getPath() + "/GmlParser");if (!fileRoot.exists()) {fileRoot.mkdir();}createFolder(foldername);File file = new File(Environment.getExternalStorageDirectory().getPath() + "/GmlParser/" + foldername + "/map.svg");if (file.exists()) file.delete();try {file.createNewFile();result = true;} catch (IOException e) {// TODO Auto-generated catch blockresult = false;} return result;}public Boolean Write() {boolean result = false;SvgUtils m_svg = new SvgUtils(context);AddContent(m_svg.getDocumentStart());folderName = SharedUtils.getStringValue(context, "filename", "TestData");// 打开或创建数据库SQLiteDatabase db = context.openOrCreateDatabase(folderName + ".db",Context.MODE_PRIVATE, null);if (m_layerinfos == null)m_layerinfos = new ArrayList<LayerInfo>();Cursor c = db.rawQuery(getLinfoSelect(), null);while (c.moveToNext()) {LayerInfo ainfo = new LayerInfo();ainfo.Lid = c.getInt(c.getColumnIndex("Lid"));ainfo.Lname = c.getString(c.getColumnIndex("Lname"));ainfo.Ltype = c.getInt(c.getColumnIndex("Ltype"));Random random = new Random();ainfo.Lstyle = random.nextInt(3);m_layerinfos.add(ainfo);}c.close();for (int i = 0; i < m_layerinfos.size(); i++) {int Lid = m_layerinfos.get(i).Lid;if (m_layerinfos.get(i).Ltype != -1) {AddContent(m_svg.SetLayerStart(Lid));c = db.rawQuery(getPinfoSelect(Lid), null);while (c.moveToNext()) {String PosList = c.getString(c.getColumnIndex("Pos"));AddContent(m_svg.Draw(PosList, m_layerinfos.get(i).Ltype,m_layerinfos.get(i).Lstyle));}c.close();}else{AddContent("</g>"+m_svg.SetLayerStart(Lid));c = db.rawQuery(getTinfoSelect(Lid), null);while (c.moveToNext()) {String PosList = c.getString(c.getColumnIndex("Pos"));String Name=c.getString(c.getColumnIndex("Name"));String Oid="O_"+c.getInt(c.getColumnIndex("Oid"));AddContent(m_svg.DrawText(PosList, Name,Oid));}c.close();}AddContent(SvgUtils.SVG_LAYER_ENDTAG);}AddContent(SvgUtils.SVG_LAYER_ENDTAG + SvgUtils.SVG_ENDDOUCUMENT);result = WriteContent(this.m_buffer.toString());if (result)SharedUtils.StorePreferences(context, "isSvg", result);return result;}private void AddContent(String str) {if (m_buffer == null)m_buffer = new StringBuilder();m_buffer.append(str);}// 向已创建的文件中写入数据库中存储的数据private boolean WriteContent(String str) {boolean result = false;try {createFile(folderName);FileWriter fw = null;BufferedWriter bw = null;fw = new FileWriter(Environment.getExternalStorageDirectory().getPath() + "/GmlParser/" + folderName + "/map.svg", true);//// 创建FileWriter对象,用来写入字符流bw = new BufferedWriter(fw); // 将缓冲对文件的输出bw.write(str); // 写入文件bw.newLine();bw.flush(); // 刷新该流的缓冲bw.close();fw.close();result = true;} catch (IOException e) {// TODO Auto-generated catch blockresult = false;}return result;}/** 获取图层信息的select语句*/private String getLinfoSelect() {return "select * from LayersInfo order by Ltype DESC";}private String getPinfoSelect(int Lid) {return "select Pos from FeaturePositon where Lid=" + Lid;}//文字private String getTinfoSelect(int Lid){//String result="select name.TextString Name,pos.Pos Pos from ";//String name="(Select FeatureId,TextString From L_"+Lid+" ) name,FeaturePositon pos";//return result+name+"where name.FeatureId=pos.OBJECTID";return "select name.TextString Name,name.OBJECTID Oid,pos.Pos Pos from (Select OBJECTID,FeatureId,TextString From L_4 ) name,FeaturePositon pos where name.FeatureId=pos.OBJECTID";}
}
其中要用到SvgUtils
package com.gmlmap.util;import java.util.Random;import android.content.Context;public class SvgUtils {public static String[] PolygenColors={"#dfeafc","#faf3df","#fce3e3","#fed4cc"};public static String[] PolylineColors={"#0c343d","#274e13","#783f04","#073763"};public static String[] PointColors={"#ff0000","#ff9900","#00ff00","#ffff00"};public static String[] Stroks={"#330000","#003300","#660000","#000080","#FFD700"};public static String XML_BASE="<?xml version=\"1.0\" encoding=\"utf-8\"?>";public static String SVG_BASE="<svg id=\"root\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ";public static String SVG_LAYERS="<g id=\"layers\"><g transform=\"matrix(1,0,0,-1,0,0)\">";public static String SVG_LAYER_STARTTAG="<g id=\"L_";public static String SVG_LAYER_ENDTAG="</g>";public static String SVG_ENDDOUCUMENT="</svg>";private double LOWER_X;private double LOWER_Y;private double UPPER_X;private double UPPER_Y;private Context m_context;public SvgUtils(Context context){this.m_context=context;SharedUtils.StorePreferences(context,"lowerCorner","585305.346019984 3338389.98497472");SharedUtils.StorePreferences(context,"upperCorner","596424.775248615 3345263.17995185");String lowerCorner=SharedUtils.getStringValue(m_context, "lowerCorner", "0 0");String upperCorner=SharedUtils.getStringValue(m_context, "upperCorner", "1000 1000");String poslist1[]=lowerCorner.split(" ");String poslist2[]=upperCorner.split(" ");LOWER_X=Double.parseDouble(poslist1[0]);LOWER_Y=Double.parseDouble(poslist1[1]);UPPER_X=Double.parseDouble(poslist2[0]);UPPER_Y=Double.parseDouble(poslist2[1]);}public String getDocumentStart(){return XML_BASE+SVG_BASE+" width=\"100%\" height=\"100%\" viewBox=\""+LOWER_X+",-"+UPPER_Y+","+(UPPER_X-LOWER_X)+","+(UPPER_Y-LOWER_Y)+"\">"+SVG_LAYERS;}public String SetLayerStart(int Lid){return SVG_LAYER_STARTTAG+Lid+"\">";}public String Draw(String PosList,int Ltype,int Lstyle){String result="";switch(Ltype){case 0:result=DrawPoint(PosList,PointColors[Lstyle]);break;case 1:result=DrawPolyLine(PosList,PolylineColors[Lstyle]);break;case 2:{Random random = new Random();result=DrawPolyGen(PosList,PolygenColors[Lstyle],Stroks[ random.nextInt(4)]);}break;}return result;}//根据点集确定text位置private String getTextPos(String Pos){String result="";double lowerx=0,upperx=0,lowery=0,uppery=0;String[] poslist=Pos.split(" ");for(int i=0;i<poslist.length;i++){//x? y:zif(i%2==0){double x=Double.parseDouble(poslist[i]);if(i==0)lowerx=x;elselowerx=(lowerx>x)?x:lowerx;upperx=(upperx<x)?x:upperx;}else{double y=Double.parseDouble(poslist[i]);if(i==1)lowery=y;elselowery=(lowery>y)?y:lowery;uppery=(uppery<y)?y:uppery;}}result="x=\""+(lowerx+(upperx-lowerx)/4)+"\" y=\"-"+((uppery)-(uppery-lowery)/2)+"\" ";return result;}public String DrawText(String Pos,String name,String Oid){String result="";result="<text id=\""+Oid+"\" "+getTextPos(Pos)+"fill=\"black\" font-size=\"260\">"+name+"</text>";return result;}public String DrawPoint(String Pos,String Color){String Poss[]=Pos.split(" ");String result="<circle cx=\""+Poss[0]+"\" cy=\""+Poss[1]+"\" r=\"15\" fill=\""+Color+"\"/>";return result;}public String DrawPolyLine(String Pos,String lineColor){String result="<polyline points=\" "+Pos+"\" style=\"fill:none;stroke:"+lineColor+";stroke-width:1.5\" />";return result;}public String DrawPolyGen(String Pos,String fillColor,String strokeColor){String result="<polygon points=\""+Pos+"\" style=\"fill:"+fillColor+";stroke:"+strokeColor+";stroke-width:1.5\"/>";return result;}/** 坐标转换*/private String convertCoorX(String x){return Double.parseDouble(x)-LOWER_X+"";}private String convertCoorY(String y){return Double.parseDouble(y)-LOWER_Y+"";}
}
HTML文件
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title> map </title>
<script src="htmfuc.js" type="text/javascript" ></script>
<style>
.div-a{ position:absolute; left:0px; top:0px;background-color:transparent;width:100%; height:100% }
</style>
</head><body onload="Init()">
<div class="div-a" filter:alpha(opacity=100,finishopacity=0,style=2></div>
<embed id="map" src="./map.svg" left="0px" top="0px"; width="100%" height="100%" type="image/svg+xml" >
</body>
</html>
JS文件控制
var htmlObj, SVGDoc, SVGRoot, viewBox, goLeft, goRight, innerSVG;
var currentSize, currentPosition, currentRoomId, currentRoomLabel;
var svgns = "http://www.w3.org/2000/svg";
var S_Width,S_Height;
var curtype=0;function Init()
{htmlObj = document.getElementById("map");SVGDoc = htmlObj.getSVGDocument();SVGRoot = SVGDoc.documentElement;S_Width=screen.width;S_Height=screen.height;
}function changeVisible(tagname){var tag=SVGDoc.getElementById(tagname);if(!tag){return;}var visible=tag.getAttribute("visibility");if(visible=="hidden"){tag.setAttribute("visibility","visible");}else{tag.setAttribute("visibility","hidden"); }} function ZoomIn()
{if(curtype<5)
{
curtype=curtype+1;var rootElement=SVGDoc.getElementById("root");var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.var viewBoxValues = viewBox.split(',');viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdith
viewBoxValues[3] = parseFloat(viewBoxValues[3]);viewBoxValues[0]=getLower(viewBoxValues[0],viewBoxValues[2],viewBoxValues[2]/2);viewBoxValues[1]=getLower(viewBoxValues[1],viewBoxValues[3],viewBoxValues[3]/2);viewBoxValues[2] = viewBoxValues[2]/2;
viewBoxValues[3] = viewBoxValues[3]/2;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}
}function ZoomOut()
{
if(curtype>-2)
{
curtype=curtype-1;var rootElement=SVGDoc.getElementById("root");var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.var viewBoxValues = viewBox.split(',');viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[3] = parseFloat(viewBoxValues[3]);viewBoxValues[0]=getLower(viewBoxValues[0],viewBoxValues[2],viewBoxValues[2]*2);viewBoxValues[1]=getLower(viewBoxValues[1],viewBoxValues[3],viewBoxValues[3]*2);viewBoxValues[2] = viewBoxValues[2]/0.5;
viewBoxValues[3] = viewBoxValues[3]/0.5;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}
}function getLower(oldLower,oldValue,newValue)
{return oldLower+oldValue/2-newValue/2;
}function searchByid(tname)
{var oElement=SVGDoc.getElementById(tname);var x=parseFloat(oElement.getAttribute('x'));var y=parseFloat(oElement.getAttribute('y'));var rootElement=SVGDoc.getElementById("root"); var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.var viewBoxValues = viewBox.split(',');viewBoxValues[2]=parseFloat(viewBoxValues[2]);viewBoxValues[3]=parseFloat(viewBoxValues[3]);viewBoxValues[0]=x-viewBoxValues[2]/2;viewBoxValues[1]=y-viewBoxValues[3]/2;rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}function Pan()
{var panRate = 10;var rootElement=SVGDoc.getElementById("root");var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.var viewBoxValues = viewBox.split(',');viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[0] += panRate*viewBoxValues[2] /S_Width;rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}function scrool(distanceX,distanceY)
{var rootElement=SVGDoc.getElementById("root");var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.var viewBoxValues = viewBox.split(',');viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[3] = parseFloat(viewBoxValues[3]); // Uheight viewBoxValues[0] += parseFloat(distanceX)*viewBoxValues[2] /S_Width;viewBoxValues[1] += parseFloat(distanceY)*viewBoxValues[3] /S_Height;rootElement.setAttribute('viewBox', viewBoxValues.join(','));}function Zoom(x,y)
{if ( evt.detail ==2 ){var panRate = 10;var rootElement=SVGDoc.getElementById("root");var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.var viewBoxValues = viewBox.split(',');x=parseFloat(x);y=parseFloat(y);viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[3] = parseFloat(viewBoxValues[3]);viewBoxValues[0]= getBasecor(getTruecorX(x,viewBoxValues[0],viewBoxValues[2] ),viewBoxValues[2]/2);viewBoxValues[1]= getBasecor(getTruecorY(y,viewBoxValues[1],viewBoxValues[3] ),viewBoxValues[3]/2); viewBoxValues[2] = viewBoxValues[2]/2;viewBoxValues[3] = viewBoxValues[3]/2;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));}
}function getTruecorX(CorX,LowerX,Width)
{return LowerX+Width/S_Width*CorX;
}function getTruecorY(CorY,LowerY,Height)
{return LowerY+Height/S_Height*CorY;
}function getBasecor(Cor,value)
{return Cor-value/2;
}
参考链接
Gml解析并显示(Android) - 下载频道 - CSDN.NET