SharpMap在web上的应用
最近公司用SharpMap做了一个做桌面程序,它是一个开源的Gis项目,功能还可以,最大的特点就是简单易用,这里介绍下怎么在web下使用:
这次我们根据demo先了解一下如何show一个地图。这是最基本的步骤,也比较简单,希望能对刚入门的同学有所帮助。
我们使用SharpMap.UI.dll中的ajax控件 <smap:AjaxMapControl width="1600px" Height="600px" id="ajaxMap" runat="server"
OnClickEvent="MapClicked" onmouseout="toolTip();"; OnViewChange="ViewChanged" CssClass="Ly" UseCache="false"
OnViewChanging="ViewChanging" ZoomSpeed="1" /> 来展示地图,主要代码分析如下:
首先,初始化地图
public static SharpMap.Map InitializeMap(System.Drawing.Size size)
{
HttpContext.Current.Trace.Write("Initializing map"); //Initialize a new map of size 'imagesize'
SharpMap.Map map = new SharpMap.Map(size); //Set up the countries layer
SharpMap.Layers.VectorLayer layCountries = new SharpMap.Layers.VectorLayer("Countries");
//Set the datasource to a shapefile in the App_data folder
layCountries.DataSource = new SharpMap.Data.Providers.ShapeFile(HttpContext.Current.Server.MapPath(@"~\App_data\countries.shp"), true); //Set fill-style to green
layCountries.Style.Fill = new SolidBrush(Color.Green);
//Set the polygons to have a black outline
layCountries.Style.Outline = System.Drawing.Pens.Black;
layCountries.Style.EnableOutline = true;
layCountries.SRID = ; //Set up a river layer
SharpMap.Layers.VectorLayer layRivers = new SharpMap.Layers.VectorLayer("Rivers");
//Set the datasource to a shapefile in the App_data folder
layRivers.DataSource = new SharpMap.Data.Providers.ShapeFile(HttpContext.Current.Server.MapPath(@"~\App_data\rivers.shp"), true);
//Define a blue 1px wide pen
layRivers.Style.Line = new Pen(Color.Blue,);
layRivers.SRID = ; //Set up a river layer
SharpMap.Layers.VectorLayer layCities = new SharpMap.Layers.VectorLayer("Cities");
//Set the datasource to a shapefile in the App_data folder
layCities.DataSource = new SharpMap.Data.Providers.ShapeFile(HttpContext.Current.Server.MapPath(@"~\App_data\cities.shp"), true);
//Define a blue 1px wide pen
//layCities.Style.Symbol = new Bitmap(HttpContext.Current.Server.MapPath(@"~\App_data\icon.png"));
layCities.Style.SymbolScale = 0.8f;
layCities.MaxVisible = ;
layCities.SRID = ; //Set up a country label layer
SharpMap.Layers.LabelLayer layLabel = new SharpMap.Layers.LabelLayer("Country labels");
layLabel.DataSource = layCountries.DataSource;
layLabel.Enabled = true;
layLabel.LabelColumn = "Name";
layLabel.Style = new SharpMap.Styles.LabelStyle();
layLabel.Style.ForeColor = Color.White;
layLabel.Style.Font = new Font(FontFamily.GenericSerif, );
layLabel.Style.BackColor = new System.Drawing.SolidBrush(Color.FromArgb(,,,));
layLabel.MaxVisible = ;
layLabel.MinVisible = ;
layLabel.Style.HorizontalAlignment = SharpMap.Styles.LabelStyle.HorizontalAlignmentEnum.Center;
layLabel.SRID = ;
layLabel.MultipartGeometryBehaviour = SharpMap.Layers.LabelLayer.MultipartGeometryBehaviourEnum.Largest; //Set up a city label layer
SharpMap.Layers.LabelLayer layCityLabel = new SharpMap.Layers.LabelLayer("City labels");
layCityLabel.DataSource = layCities.DataSource;
layCityLabel.Enabled = true;
layCityLabel.LabelColumn = "Name";
layCityLabel.Style = new SharpMap.Styles.LabelStyle();
layCityLabel.Style.ForeColor = Color.Black;
layCityLabel.Style.Font = new Font(FontFamily.GenericSerif, );
layCityLabel.MaxVisible = layLabel.MinVisible;
layCityLabel.Style.HorizontalAlignment = SharpMap.Styles.LabelStyle.HorizontalAlignmentEnum.Left;
layCityLabel.Style.VerticalAlignment = SharpMap.Styles.LabelStyle.VerticalAlignmentEnum.Bottom;
layCityLabel.Style.Offset = new PointF(, );
layCityLabel.Style.Halo = new Pen(Color.Yellow, );
layCityLabel.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
layCityLabel.SmoothingMode = SmoothingMode.AntiAlias;
layCityLabel.SRID = ;
layCityLabel.LabelFilter = SharpMap.Rendering.LabelCollisionDetection.ThoroughCollisionDetection;
layCityLabel.Style.CollisionDetection = true; //Add the layers to the map object.
//The order we add them in are the order they are drawn, so we add the rivers last to put them on top
map.Layers.Add(layCountries);
map.Layers.Add(layRivers);
map.Layers.Add(layCities);
map.Layers.Add(layLabel);
map.Layers.Add(layCityLabel); //limit the zoom to 360 degrees width
map.MaximumZoom = ;
map.BackColor = Color.LightBlue; map.Zoom = ;
map.Center = new SharpMap.Geometries.Point(,); HttpContext.Current.Trace.Write("Map initialized");
return map;
}
这段代码中,
SharpMap.Layers.VectorLayer layCountries = new SharpMap.Layers.VectorLayer("Countries");
layCountries.DataSource = new SharpMap.Data.Providers.ShapeFile(HttpContext.Current.Server.MapPath(@"~\App_data\countries.shp"), true);
这两句话定义并初始化了一个map的一个层。一个map可能包含多个层,我们对map进行操作,其实就是对map的各个层进行操作,比如说道路层,建筑层等等。根据业务的复杂程度,可能有很多个层。一般来说,每个层都有各自的抽象特征(一类对象),可以进行一样的操作。各个层组合起来,就是一个map.
好,接着说初始化。这里为VectorLayer的构造函数提供了一个层的名称,然受设置了数据源。一个层的Datasource是一个IProvider类型的数据,而ShapeFile类正是实现了Iprovider接口的类。(这点很重要,以后有很多机会需要把一个datasource转换成ShapeFile)。
接下来是对这个层进行着色,呵呵 就是这个层上的对象如何填充颜色。这里因为是刚刚开始,我们就用最简单的办法,设置了一个
layCountries.Style.Fill = new SolidBrush(Color.Green);
这样,就把层上的对象都填充成了绿色。在以后的讲解中,我们会让大家了解到如何自定义theme,这样我们能根据实现设置的对象的类型填充不同的颜色,以实现自定义的样式,让地图多彩多姿。
然后我们看到label层。每一个map的layer都有自己的label层。
SharpMap.Layers.LabelLayer layLabel = new SharpMap.Layers.LabelLayer("Country labels");
layLabel.DataSource = layCountries.DataSource;
layLabel.Enabled = true;
layLabel.LabelColumn = "Name";
这里我们首先定义了一个label层,然后把countries层的datasource直接赋给label层的datasource就OK了。这样,这个新定义的label层就属于countries层了。然后我们给它制定一个labelColumn,这个是必须指定的。它表示countries层的每个对象应该显示什么内容。这个内容在ShapeFile(我们在MapWindow GIS中建立的shapefile文件)的attribute中进行增加和更新。
我想有必要说一下地图的对象。
地图上有很多点,线和多边形。这些都是对象。我们都可以对他们进行操作。每个对象有相应的属性,这些属性我们也可以添加,修改和删除。而上述的label的LabelColumn就是这些属性中的一个。我们在这里可以指定一个,也可以通过LabelStringDelegate来委托一个方法返回一个字符串(这个将在以后进行详细讲解)。
OK,在设置了label的字体颜色,大小和背景色之后,有两个个属性是特别值得我们注意的。
layLabel.MaxVisible = 90;
ayLabel.MinVisible = 30;
这两个值说明了我们在多大/多小的比例尺下可以看到这个label层。我就经常会忽略这个问题,以至于在放大或缩小比例尺的时候看不到label,也找不到原因。
在初始化的最后,我们把所有的层都加到地图中来,在设置一下最大的比例尺,背景色和中心点,就可以了
map.Layers.Add(layCountries);
map.Layers.Add(layRivers);
map.Layers.Add(layCities);
map.Layers.Add(layLabel);
map.Layers.Add(layCityLabel);
//limit the zoom to 360 degrees width
map.MaximumZoom = 360;
map.BackColor = Color.LightBlue;
最后,我们通过一个maphandler(ashx)把地图输出到页面上。
System.Drawing.Bitmap img = (System.Drawing.Bitmap)map.GetMap();
context.Response.ContentType = "image/png";
System.IO.MemoryStream MS = new System.IO.MemoryStream();
img.Save(MS, System.Drawing.Imaging.ImageFormat.Png);
// tidy up
img.Dispose();
byte[] buffer = MS.ToArray();
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
代码都来自www.codeplex.com/sharpmap的demo。
添加主题 更具一些特性:
private VectorStyle GetCountryStyle(FeatureDataRow row)
{
VectorStyle style = new VectorStyle();
switch (row["NAME"].ToString().ToLower())
{
case "denmark": //If country name is Danmark, fill it with green
style.Fill = Brushes.Green;
return style;
case "united states": //If country name is USA, fill it with Blue and add a red outline
style.Fill = Brushes.Blue;
style.Outline = Pens.Red;
return style;
case "china": //If country name is China, fill it with red
style.Fill = Brushes.Red;
return style;
default:
break;
}
//If country name starts with S make it yellow
if (row["NAME"].ToString().StartsWith("S"))
{
style.Fill = Brushes.Yellow;
return style;
}
// If geometry is a (multi)polygon and the area of the polygon is less than 30, make it cyan
else if (row.Geometry is IMultiPolygon && (row.Geometry as IMultiPolygon).Area < ||
row.Geometry is IPolygon && (row.Geometry as IPolygon).Area < )
{
style.Fill = Brushes.Cyan;
return style;
}
else //None of the above -> Use the default style
return null;
}
在经过第一篇的简单学习之后,我们开始了解一些稍微有点儿意思的东西,进一步掌握和学习利用sharpmap进行开发的技巧。
这次,我们主要是跟大家一起学习一下如何根据地图上的一个点,来查询这个点所在的对象的信息,并显示到点击的位置。这非常有用,比如说一个想把一个房子显示在地图上,我们用鼠标一点,便知道这个房子里住的什么人,干什么的,以及其它相关信息。
同样的,我们还是使用sharpmap提供的ajax控件,环境和第一篇一模一样。但是这里,我们要引用一个叫做NetTopologySuite的类库。它经常和SharpMap一起使用,这次我们只使用其中的一个小部分,废话不多说,开始做。
这里我们使用asp.net ajax 1.0,首先引用了dll,并且拖上scripmanager并设置为EnablePageMethods=true,这样我们就可以在页面中写静态方法来实现AJAX。
在MapClicked方法(AjaxMapControl控件提供的方法,直接写在js中即可,表示单击的时候发生一些事情)中,我们调用我们写的js,根据两个点来返回一个字符串。这个字符串就是拼好的html,直接显示出来。
function MapClicked(event,obj)
{
var mousePos = SharpMap_GetRelativePosition(event.clientX,event.clientY,obj.container);
var pnt = SharpMap_PixelToMap(mousePos.x,mousePos.y,obj);
var field = document.getElementById('dataContents');
//field.innerHTML = "You clicked map at: " + pnt.x + "," + pnt.y;
GetData(pnt.x, pnt.y);
}
这个方法里面的SharpMap_GetRelatiovePosition和 SharpMap_PixelToMap方法根据鼠标在屏幕上的坐标计算出鼠标点在地图上的坐标,再调用我们自己写的GetData方法即可。在GetData方法中,我们使用了PageMethods来调用一个后台方法,并返回一个字符串。
PageMethods.GetData(x, y, GetDataSuccess);
然后,在GetDataSuccess中调用一个写好的用来显示这些返回数据的方法(此方法来自网络,js源码如下)。
<script type="text/javascript">
<!--
var ns4 = document.layers;
var ns6 = document.getElementById && !document.all;
var ie4 = document.all;
offsetX = 0;
offsetY = 20;
var toolTipSTYLE = "";
function initToolTips() {
if (ns4 || ns6 || ie4) {
if (ns4) toolTipSTYLE = document.toolTipLayer;
else if (ns6) toolTipSTYLE = document.getElementById("toolTipLayer").style;
else if (ie4) toolTipSTYLE = document.all.toolTipLayer.style;
if (ns4) document.captureEvents(Event.MOUSEMOVE);
else {
toolTipSTYLE.visibility = "visible";
toolTipSTYLE.display = "none";
}
document.onclick = moveToMouseLoc;
}
}
function toolTip(msg, fg, bg) {
if (toolTip.arguments.length < 1) // hide
{
if (ns4) toolTipSTYLE.visibility = "hidden";
else toolTipSTYLE.display = "none";
}
else // show
{
if (!fg) fg = "#777777"; //fore color
if (!bg) bg = "#FFFFFF"; //bg color
var content = msg;
if (ns4) {
toolTipSTYLE.document.write(content);
toolTipSTYLE.document.close();
toolTipSTYLE.visibility = "visible";
}
if (ns6) {
document.getElementById("toolTipLayer").innerHTML = content;
toolTipSTYLE.display = 'block'
}
if (ie4) {
document.all("toolTipLayer").innerHTML = content;
toolTipSTYLE.display = 'block'
}
}
}
function moveToMouseLoc(e) {
if (ns4 || ns6) {
x = e.pageX;
y = e.pageY;
}
else {
x = event.x + document.body.scrollLeft;
y = event.y + document.body.scrollTop;
}
toolTipSTYLE.left = x + offsetX;
toolTipSTYLE.top = y + offsetY;
return true;
}
//-->
</script>
需要指出的是,这个效果需要做一些初始化的工作:
<div id="toolTipLayer" style="position:absolute;visibility: hidden;z-index:10000">
</div>
<script type="text/javascript">
initToolTips();
</script>
这样,我们在前台的工作就基本完成了。
当然,如果想要更好看一些,再写一个css帮助从后台传来的html进行淡化。
.clarity
{
filter:alpha(opacity=80,Style=0);
}
OK,现在转去后台。
在根据两个点查询对象数据时,我们首先要初始化需要初始化shapefile,也就是你要查询的那个层的数据源。
new SharpMap.Data.Providers.ShapeFile(filepath true);
然后遍历shapefile里面的每一个feature,对比传入的点和feature所在的Geometry,如果传入的点在feature所在Geometry之内(within方法)的话,就读取当前feature的一个attribute(通常是某个业务对象的ID),这样,根据这个ID就能取到业务对象的值,然后Build一下HTML,返回就OK了。主要代码如下:
public string GetInfo(double x, double y)
{
SharpMap.Data.Providers.ShapeFile oShape=(SharpMap.Data.Providers.ShapeFile)GetShapeFile(filepath);
if (!oShape.IsOpen)
{
oShape.Open();
}
uint iFeature = (uint)oShape.GetFeatureCount();
SharpMap.Geometries.Point oPoint = new SharpMap.Geometries.Point(x, y);
GisSharpBlog.NetTopologySuite.Geometries.Geometry oPt = SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(oPoint, new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory());
StringBuilder sb = new StringBuilder();
// find a record
string graveInfo = string.Empty;
for (uint i = 0; i < iFeature; i++)
{
GisSharpBlog.NetTopologySuite.Geometries.Geometry oPoly = SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(oShape.GetFeature(i).Geometry, new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory());
if (oPt.Within(oPoly))
{
if (oShape.GetFeature(i)[someId].ToString().Length > 0)
{
return BuildGraveInfoTable(name, value);
}
}
}
return string.emtpy;
}
这里把sharpfile的Geometry都转换成了NTS 的,这样,使用NTS的Within方法进行比较。sharpmap自己的方法在我的测试中是不能用的,希望大家在使用过程中做些尝试,看看是否是我自己的代码有问题,总之,我是用的NTS。
到这里,我们就实现了根据点来查询对象数据的功能,我们只需要在shapefile中存储一个attribute(比如对象的ID),然后取出来显示出去就OK了。
同理的,我们也可以实现根据一个用户ID来找到这个对象在地图中的位置,并显示在地图中间。
代码如下:
public SharpMap.Geometries.Point GetPointByID(string Id)
{
SharpMap.Data.Providers.ShapeFile oShape = (SharpMap.Data.Providers.ShapeFile)GetShapeFile(filePath);
oShape.Open();
uint i = 0;
uint iFeature = (uint)oShape.GetFeatureCount();
SharpMap.Geometries.Point oPt = null;
for (i = 0; i < iFeature; i++)
{
GisSharpBlog.NetTopologySuite.Geometries.Geometry oPoly = SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(oShape.GetFeature(i).Geometry, new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory());
if (oShape.GetFeature(i)["Id"].ToString() == Id)
{
oPt = new SharpMap.Geometries.Point(oPoly.InteriorPoint.X, oPoly.InteriorPoint.Y);
}
}
return oPt;
}
找到这个点之后,设置一下控件的地图的中心点,就OK了。
ajaxMap.Map.Center = pCenter;
虽然东西很简单,但是还是费了我很多功夫。很大一部分原因是因为sharpmap自己提供的方法不太完善,导致很多时间花费在了追踪问题上。不过这种追踪对理解开源的代码也是很有好处的。
在这个例子中,我使用了遍历地图中所有feature的方法来定位一个对象,这样非常的耗费资源,效率并不好。如果地图对象比较少还可以,一旦超过一定的数量级,可能会出现性能问题。以后我会在这个基础上进行改进,利用其它方法来实现这个功能(事实上我已经进行了一些尝试,只是还没有成功。如果有人成功了,希望给我一些建议,谢谢)。
今天就到这里,感谢大家的关注,希望多多拍砖,共同进步。
在下一篇中,我将和大家共同学习关于根据attribute的值来填充地图上对象的颜色,设置他们的样式以及一些有趣的小玩意儿。希望大家继续关注,谢谢。
每天学一天,每天都会进步一点儿。
我写的东西内容浅显,希望能给初学者一些帮助。至于深入研究sharpmap和GIS技术的大牛,请不吝赐教,给我们这些菜鸟多一些指导。
今天我们接着来聊sharpmap的基本使用技巧,根据attribute来填充地图对象的颜色,让用户更清晰的看到重点的业务对象对应在地图上的表示,以及如何自定义label层的显示内容,字体的大小等。所以,今天的主题主要是自定义:自定义theme,自定义label以及label字体。
首先,我们要为地图填充上不同的色彩,让他们看起来五颜六色,容易分辨。比如河流和湖泊要填成蓝色,草地要填充上绿色,房子要填充上白色,道路要填充上青色等等。怎么做呢?很简单,先看下代码:
SharpMap.Rendering.Thematics.CustomTheme iTheme = new SharpMap.Rendering.Thematics.CustomTheme(GetMyStyle);
在初始化Map的时候,加上上面的一行代码。它定义了一个自定义的Theme对象,这个对象的构造函数需要传入一个我们自己写的方法(委托),这个方法里面具体说明了这个 theme是如何定义的,方法代码如下:
{
SharpMap.Styles.VectorStyle style = new SharpMap.Styles.VectorStyle();
switch (row["Status"].ToString().ToLower())
{
case "available": //If status is interred, fill it with yellow
style.Fill = Brushes.Yellow;
return style;
default:
style.Fill = Brushes.Green;
return style;
}
}
这段简单代码大家都看得懂,这个委托定义需要传入一个FeatureDataRow,它的作用就是在初始化地图的过程中,每处理一个对象,都要到这个方法中来考察一下feature的值是多少以决定具体要填充哪些颜色。在这里,当status为available时,就填充黄色,否则就填充绿色。定义的VectorStyle用来返回给地图。是不是很简单呢?
地图填充完了,我们要在上面显示出到底他们是什么。在第一篇中,我们已经可以把对象的一个属性显示出来,但是当地图扩大到一定比例时,仅仅显示名字这一种信息已经不足以满足用户的需要了。比如说一栋房子,在很远处看它时,我们只需要看到他的颜色就行了。但是当我们离的很近的时候,难道看到的是全白色吗?显然不是,我们还可以看到门牌号,窗户上的贴纸以及其它详细信息。地图也一样,当比例尺改变以后,应该有更详细的信息被列出来。老规矩,先贴代码:
SharpMap.Layers.LabelLayer myLabel = new SharpMap.Layers.LabelLayer("labels");
myLabel .DataSource = myLayer.DataSource;
myLabel.LabelStringDelegate= new SharpMap.Layers.LabelLayer.GetLabelMethod(GetLabelString);
在这里,首先定义了一个label(就像在初始化地图里一样,或者就在初始化地图里做),然后把你所要显示的图层的数据源赋值给这个label的数据源,接着为label层的LabelStringDelegate指定一个方法(这个方法传入一个FeatureDataRow,返回一个字符串),最后去实现这个方法,代码如下:
{
string field1= string.Empty;
string field2= string.Empty;
string field13= string.Empty;
if (dr["HouseNumber"] != null)
{
field1= dr["HouseNumber"].ToString();
}
if (dr["HostName"] != null)
{
field2= dr["HostName"].ToString();
}
if (dr["Memo"] != null)
{
field3= dr["Memo"].ToString();
}
StringBuilder sb = new StringBuilder();
sb.Append(field1);
sb.Append(": ");
sb.Append(field2);
sb.Append("\r\n" + field3);
return sb.ToString();
}
代码简单的要死,不再详述,值得注意的是:如果要换行,请使用“\r\n”, 这里不支持html拼的字符串。哈,又解决一个问题。爽吧?
然后,新的问题又来了,字体一直都是那么大,或者一直都是那么小,这可怎么办呢?看起来也相当不舒服啊。如果字体能随着比例尺的变化而变化就好了。这个没问题,我们马上就搞定它。看代码:
{
SharpMap.Layers.LabelLayer labelLayer = (SharpMap.Layers.LabelLayer)iLayer;
if (Zoom < 800 && Zoom > 400)
{
((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 6);
}
else if (Zoom < 400 && Zoom > 140)
{
((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 8);
}
else if (Zoom < 140.00 && Zoom > 20)
{
((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 16);
}
else if (Zoom < 20.00)
{
((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 48);
}
else
{
((SharpMap.Layers.LabelLayer)labelLayer).Style.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSerif, 70);
}
}
这个方法传入了一个Zoom值和一个ILayer,没有返回值,直接修改ILayer就可以了。
相信大家都看得懂吧?值得注意的问题是:AjaxMap上面的map对象有个属性叫做zoomAmount,这是个javascript的属性需要在前台指定,它说明了地图放大或缩小的比例尺倍数。Demo中是在RadioButtonList的ListItem中指定的。这个过程是这样的:当点击Zoom In这个button,自动执行了一段javascript:
ajaxMapObj.disableClickEvent(); ajaxMapObj.zoomAmount = 3;
然后当我们点击地图,click事件已经被禁止,系统刷新地图,此时在handler里接受到了地图的新的参数(zoom等),然后重新绘制了地图。所以,我们在handler里取得zoom参数,并且使用GetLayerByName(“”)方法来取得label层
ChangeFontSize(Zoom, map.GetLayerByName("mylabels"));
这样,就实现了字体随着比例尺变化儿变化。有同学可能问:那如何让label的内容随着比例尺变化而变化呢?只需要把刚才那句话
myLabel.LabelStringDelegate= new SharpMap.Layers.LabelLayer.GetLabelMethod(GetLabelString);
放到相应的if。。。else语句里就行了。简单吧?
今天就到这里。
这些都是些小技巧,在大牛眼里也许不值一提,但是我希望能给初学者带来一些帮助,希望大家工作愉快,天天好心情。
最后欢迎拍砖。
SharpMap在web上的应用的更多相关文章
- 前端之web上传文件的方式
前端之web上传文件的方式 本节内容 web上传文件方式介绍 form上传文件 原生js实现ajax上传文件 jquery实现ajax上传文件 form+iframe构造请求上传文件 1. web上传 ...
- 在web上逐行输出较大的txt文件
在某些场景下,需要在web上展示一些日志文件,这些日志文件是放在文件服务器上的一些txt. 当日志文件很大时,下载日志会导致页面长时间卡住,一直在loading状态,而且下载完日志之后分析日志并生成d ...
- 我需要在Web上完成一个图片上传的功能
我需要在Web上完成一个图片上传的功能. 这个页面需要能从手机中选择图片上传. 首先,这个页面是从微信上面触发的,所以修改了微信的的入口地址,增加了身份识别号作为传参. 跳转到页面的时候,页面先检查身 ...
- AS与.net的交互——加载web上的xml
最近搞了个私活,需要用as去加载一个网站的xml,不过本人as也不咋滴,就去看看怎么玩,看完之后也蛮简单的. 由于业务上比较复杂,就随便说个小例子吧. 很多时候,为了页面区域更加灵活,生动,有吸引力, ...
- Android项目,从web上取下汉字,中文部分乱码
Android项目,从web上取下汉字,中文部分乱码. 常见问题,搜索一下,网上有很多办法解决.如果还没有试过这个办法,可以尝试一下. BufferedReader in = new Buffered ...
- C#之读取web上的xml
一.使用LINQ读取使用Xdocument上的Load方法,可以快速的加载一个XML文档,然后使用LINQ对 加载XML文档进行查询或其他操作,这里仅简单偏历.所以,一旦查询一组元素有返回元素集,就可 ...
- 实现Web上的用户登录功能
关于如何实现web上的自动登录功能 文章来源http://coolshell.cn/articles/5353.html Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能 ...
- 第九篇:web之前端之web上传文件的方式
前端之web上传文件的方式 前端之web上传文件的方式 本节内容 web上传文件方式介绍 form上传文件 原生js实现ajax上传文件 jquery实现ajax上传文件 form+iframe构 ...
- 你会做Web上的用户登录功能吗?
Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做用户登录功能.下面的文章告诉大家这个功能可能并没有你所想像的那么简单,这是一个关 ...
随机推荐
- 01-Redhat/Centos7网卡命名介绍及修改方式
1. Redhat/Centos7网卡命名介绍 1.1 网络设备命名 Redhat/Centos7提供在网络接口中使用新的网络设备命名方法.这些功能会更改系统中的网络接口名称,以便定位和区分这些接口. ...
- Mysql中的explain和desc
查询分析器 desc 和 explain 作用基本一样,explain速度快一点 explain 一条SQL语句出出现以下参数, 其中id,select_type,table 用于定位查询,表示本行参 ...
- array_map、array_walk、array_reduce
不同情境下替换foreach,且效果更佳 array_map 遍历原数组,array_map()参数中有几个数组,自定义函数就接收几个参数, 在每个值上进行自定义函数处理,具有返回值,需要一个新数组 ...
- [转帖]Qemu 简述
Qemu 简述 记得KVM 就是 底层用的qemu https://www.cnblogs.com/bakari/p/7858029.html 本文首发于我的公众号 Linux云计算网络(id: cl ...
- Virtual DOM 系列一:认识虚拟DOM
1. 什么是Virtual DOM? Virtual DOM(虚拟DOM)是指用JS模拟DOM结构.本质上来讲VD是一个JS对象,并且至少包含三个属性:tag(html标签),props(标签的属性, ...
- Quill 富文本编辑器
Quill 富文本编辑器 https://quilljs.com/ https://github.com/quilljs/quill https://github.com/quilljs/awesom ...
- EL和 JSTL? 在JSP中简化 java代码的写法!
一.servlet部分 package com.aaa.servlet; import com.aaa.dao.IStudentDAO; import com.aaa.dao.Impl.Student ...
- django xadmin(2) 在xadmin基础上完成自定义页面
1.在xadmin.py,GlobalSettings中自定义菜单 2.自定义视图函数,并获取原来的菜单等一下信息(主要是为了用xadmin的模板),具体的自己看xadmin源码 3.在adminx. ...
- Android Intent 传递数据注意事项
不要通过 Intent 在 Android 基础组件之间传递大数据(binder transaction缓存为 1MB),可能导致 OOM.
- <TCP/IP原理> (三) 底层网络技术
传输介质 局域网(LAN) 交换(Switching) 广域网(WAN) 连接设备 第三章 底层网络技术 引言 1)Interne不是一种新的网络 建立在底层网络上的网际网 底层网络——“物理网”,网 ...