Creating a DHTML scale bar with the .NET Web ADF

本文介绍如何使用.NET WebADF及JavaScript库在客户端创建一个响应式的DHTML比例尺,该比例尺能够随着地图范围的变化自动调整大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Creating a DHTML scale bar with the .NET Web ADF

At the 9.3 release, the .Net Web ADF’s JavaScript library exposes a lot of logic to the client side, allowing you to create a more responsive UI without the need for making calls back to the server. You can get the Web ADF JavaScript library help on the ArcGIS Server Resource Center. This post will show you how to use the JavaScript library to create a pure client-side scale bar using the Microsoft AJAX Client Library patterns.

The Web ADF’s scale bar is generated by the primary map resource using a dynamically generated image. Since the scale potentially can change on every pan, the scale bar image has to be updated frequently, adding additional overhead to the server requests for rendering and fetching these images. Furthermore, if the primary map resource doesn’t support rendering a scale bar, no scale bar is available at all. ArcIMS ArcMap Services don’t support rendering a scale bar. The approach described in this post is the recommended pattern for displaying a scale bar for ArcIMS ArcMap Services.

We can scale a standard <div> box dynamically on the client using JavaScript, and completely eliminate the extra callback, because the map control allows you to listen for and get the current extent of the map. We simply add a handler to the Map’s 'extentChanged' event. To do this, we first get a reference to the map object using the $find method parsing in the ClientID of the map as a parameter:

var map = $find('Map1');

Next we add the handler which will be executed every time the extent of the map has changed:

map.add_extentChanged(myExtentChangedHandler);

However, we need to ensure that this handler is not created until the Map has been instantiated on the client. The Microsoft AJAX framework also exposes several life-cycle events, for listening when the page has been fully loaded. So we wrap the above code in an application init event handler and place it right before the </body> tag. Notice how the pattern for adding event handlers is similar to adding handlers to the map. The full example could look something like this:

<script type="text/javascript" language="javascript" >
	function myExtentChangedHandler(sender, args) {
		   alert(sender.get_id() + ' changed extent to: ' + args.current.toString());
	}
	Sys.Application.add_init(function() {
		   var map = $find('Map1');
		   map.add_extentChanged(myExtentChangedHandler);
	});
</script>

Every time you pan the map, you will see a popup window like this:

Message that appears on pan

This gives us the framework for creating a simple scale bar. The next step is to place a box on the page that we can use as a scale bar by changing the width as the pixel size changes.

<div><div id="scalebar" style="background-color: #000000; width: 200px; height: 10px;"></div><span id="scalebarText">100 units</span></div>

<script type="text/javascript" language="javascript" >

function resizeScalebar(sender, args) { //resize event handler
  var pixelSize = sender.get_pixelSize(); //Gets the size on one pixel in map units
  var scalebarWidthInMapUnits = 0.001; //The initial size of the scalebar in map units
  //width in pixels of a scalebar with the current 
  //scalebarWidthInMapUnits value and map's pixelsize
  var width = scalebarWidthInMapUnits / pixelSize;
  while(width<20) {
    //keep increasing scalebar size until we have a reasonable and visible size
    scalebarWidthInMapUnits *= 10;
    width = scalebarWidthInMapUnits / pixelSize;
  }
  $get('scalebar').style.width = width + 'px';
  $get('scalebarText').innerHTML = scalebarWidthInMapUnits + ' units';
}
//Hook up the handlers during init
Sys.Application.add_init(function() {
  var map = $find('Map1');
  map.add_extentChanged(resizeScalebar); //fired when extent has changed
  map.add_extentChanging(resizeScalebar); //fired while map is zooming/panning
  resizeScalebar(map,null); //Force initial update of scalebar
});

</script>

This will generate a very simple scale bar that looks something like this:

Simple scale bar

It will automatically adjust its width between 20 and 200 px and show the corresponding width in map units next to it.

The next step is to componentize this into a real client side control that can easily be reused. The Microsoft AJAX Client Library already has a framework in place for creating controls that can inherit from each other and be extended.

A component requires a constructor, and a prototype. In the constructor you define the default properties of the control, and in the prototype you define the properties and methods, including initialize and dispose. Lastly you register the control and optionally the type you derive from, in this case Sys.UI.Control.

Type.registerNamespace('ADF.Samples');

ADF.Samples.DhtmlScaleBar = function(element) {
  ADF.Samples.DhtmlScaleBar.initializeBase(this, [element]);
  this._map = null; //Reference to the map
  this._minWidth = 20; //minimum width of the bar before changing units
}
ADF.Samples.DhtmlScaleBar.prototype = {
  initialize : function () {
    ADF.Samples.DhtmlScaleBar.callBaseMethod(this, 'initialize'); //Call base initialize
    if(this._map === null) { throw Error.argumentNull('map'); }
    this._extentChangedHandler = Function.createDelegate(this,this._updateScalebar);
    //Add listener for when the map is animating its extent
    this._map.add_extentChanging(this._extentChangedHandler);
    //Add listener for when the map has changed its extent
    this._map.add_extentChanged(this._extentChangedHandler); 
    this._createBars(); // Creates the bar and text elements
    this._updateScalebar(this._map); //Update the scalebar now
  },
  dispose : function() {
    ADF.Samples.DhtmlScaleBar.callBaseMethod(this, 'dispose');
    if(this._extentChangedHandler && this._map) { 
      this._map.remove_extentChanging(this._extentChangedHandler);
      this._map.remove_extentChanged(this._extentChangedHandler);
    }
    if(this._scaleBar) { this.get_element().removeNode(this._scaleBar);}
    if(this._scaleBarText) { this.get_element().removeNode(this._scaleBarText); }
    this._extentChangedHandler = null;
    this._map = null;
    this._scaleBar = null;
    this._scaleBarText = null;
  },
  _createBars : function() { //Create the bar and text
    this._scaleBar = document.createElement('div');
    this._scaleBar.style.backgroundColor = '#000000';
    this._scaleBar.style.float = 'left';
    this.get_element().appendChild(this._scaleBar);
    this._scaleBarText = document.createElement('span');
    this._scaleBarText.style.float = 'left';
    this.get_element().appendChild(this._scaleBarText);
  },
  _updateScalebar : function(sender,args) {
    var pixelSize = sender.get_pixelSize(); //Gets the size of one pixel in map units
    var scalebarWidthInMapUnits = 0.001; //The initial size of the scalebar in map units
    //width in pixels of a scalebar with the current
    //scalebarWidthInMapUnits value and map's pixelsize
    var width = scalebarWidthInMapUnits / pixelSize;
    while(width<this._minWidth) {
      //keep increasing scalebar size until we have a reasonable and visible size
      scalebarWidthInMapUnits *= 10;
      width = scalebarWidthInMapUnits / pixelSize;
    }
    this._scaleBar.style.width = width + 'px';
    this._scaleBarText.innerHTML = scalebarWidthInMapUnits + ' units';		
  },
  //Properties:
  get_map : function() { return this._map; },
  set_map : function(value) { this._map = value; },
  get_minWidth : function() { return this._minWidth; },
  set_minWidth : function(value) { this._minWidth = value; }
}
//Register class:
ADF.Samples.DhtmlScaleBar.registerClass('ADF.Samples.DhtmlScaleBar', Sys.UI.Control);

If we add this script to the page, we can now simply create a scale bar using the $create method. The parameters are:

  • Type
  • Object list of properties
  • Object list of event handlers (we don’t have any events here so we use null)
  • Object list of component properties. In our case the map – this ensures that the scale bar is not initialized until the map has been initialized.

Example:

<div id="bar"></div>
<script type="text/javascript" language="javascript" >
Sys.Application.add_init(function() {
  $create(ADF.Samples.DhtmlScaleBar,{"minWidth":20},null,{"map":"Map1"},$get('bar'));
});
</script>

At our code gallery you can download the scale bar control. It has been expanded to look a little better than just a black bar, and it also has a server-side web control that renders the above script to the page. It will analyze the primary map resource and fetch the unit of the map, and allow you to convert it to any display unit you would like on the fly. Finally, there's some extra logic which will get the scale bar to attempt to use some nice rounded intervals. The final result will look something like below, and will even resize while the zoom animation plays or while you pan toward the poles where the scale changes. You can style the control using the web control style properties like background color, border, font-size etc.

Final scale bar

Click here to get the source code from the Code Gallery

Click here to view a demo of the scale bar

Contributed by Morten Nielsen of the ArcGIS Server .NET software development team

Published Wednesday, October 29, 2008 9:20 AM by sterlingdq
Filed under: .NET, JavaScript, 9.3

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Creating a DHTML scale bar with the .NET Web ADF
In OMD pdf there is clearGraphics() in MapBase but in js it's defined.
Saturday, December 06, 2008 10:32 AM by NicoGis
# re: Creating a DHTML scale bar with the .NET Web ADF
Will you please give us a sample or any solotions with the java web ADF? Thanks a lot; my mailbox: ntntime@vip.qq.com
Tuesday, March 24, 2009 7:11 PM by NT.NTIME
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值