2014年12月7日,星期日,天气,晴,是个好日子,闲来无事,将selectToUISlider与Arcgis for JS结合起来,做了一个类似于历史影像对比的东西,共享出来给大家,希望对大家有所帮助。
首先,看看实现的效果:
初始化状态
在实例中,因为没有实际的做好的影像的切片,就用这个代替了,在实际实现的过程中可根据自己的实际需求去修改。
接下来,讲讲我的实现思路。
想要实现历史影像的对比,需要考虑以下两点问题:
1、数据源。
一般来说,为了操作方便,同时也为了展示方便,很多人的解决思路是直接用tif或者JPG的图片作为数据源。这种方式可以展示出变化,但是脱离了地图。
2、存储方式
直接用图片作为数据源的时候,你的数据怎么存储?文件的形式还是入库?当为地图服务的时候,切片?
有了数据源和存储方式,我们就可以继续讨论怎么实现了。在本文中是通过切片的方式做的,选择切片,原因有:1、能够与地图紧密的结合起来去展示;2、切片提高数据的访问效率与速度。
影像之间的切换是先将原来的图层remove掉,再重新实例化图层,再添加到map中去。
关键代码:
1、selectToUISlider.jQuery.js
jQuery.fn.selectToUISlider = function(settings){ var selects = jQuery(this); //accessible slider options var options = jQuery.extend({ labels: 3, //number of visible labels tooltip: true, //show tooltips, boolean tooltipSrc: 'text',//accepts 'value' as well labelSrc: 'value',//accepts 'value' as well , sliderOptions: null, step:1, selectshow:true, orientation:"horizontal", baseUrl:"" }, settings); //handle ID attrs - selects each need IDs for handles to find them var handleIds = (function(){ var tempArr = []; selects.each(function(){ tempArr.push('handle_'+jQuery(this).attr('id')); }); return tempArr; })(); //array of all option elements in select element (ignores optgroups) var selectOptions = (function(){ var opts = []; selects.eq(0).find('option').each(function(){ opts.push({ value: jQuery(this).attr('value'), text: jQuery(this).text() }); }); return opts; })(); //array of opt groups if present var groups = (function(){ if(selects.eq(0).find('optgroup').size()>0){ var groupedData = []; selects.eq(0).find('optgroup').each(function(i){ groupedData[i] = {}; groupedData[i].label = jQuery(this).attr('label'); groupedData[i].options = []; jQuery(this).find('option').each(function(){ groupedData[i].options.push({text: jQuery(this).text(), value: jQuery(this).attr('value')}); }); }); return groupedData; } else return null; })(); //check if obj is array function isArray(obj) { return obj.constructor == Array; } //return tooltip text from option index function ttText(optIndex){ return selectOptions[optIndex].text; } <strong>function changeMap(optIndex){ require([ "esri/layers/FeatureLayer" ], function(FeatureLayer){ map.removeLayer(fch); var fchUrl = options.baseUrl+selectOptions[optIndex].value; fch = new FeatureLayer(fchUrl); map.addLayer(fch); }); }</strong> //plugin-generated slider options (can be overridden) var sliderOptions = { step: options.step, min: 0, orientation: options.orientation, max: selectOptions.length-1, range: selects.length > 1,//multiple select elements = true slide: function(e, ui) {//slide function var thisHandle = jQuery(ui.handle); //handle feedback var textval = ttText(ui.value); thisHandle .attr('aria-valuetext', textval) .attr('aria-valuenow', ui.value) .find('.ui-slider-tooltip .ttContent') .text( textval ); //control original select menu var currSelect = jQuery('#' + thisHandle.attr('id').split('handle_')[1]); currSelect.find('option').eq(ui.value).attr('selected', 'selected'); <strong>changeMap(ui.value);</strong> }, values: (function(){ var values = []; selects.each(function(){ values.push( jQuery(this).get(0).selectedIndex ); }); return values; })() }; //slider options from settings options.sliderOptions = (settings) ? jQuery.extend(sliderOptions, settings.sliderOptions) : sliderOptions; //select element change event selects.bind('change keyup click', function(){ var thisIndex = jQuery(this).get(0).selectedIndex; var thisHandle = jQuery('#handle_'+ jQuery(this).attr('id')); var handleIndex = thisHandle.data('handleNum'); thisHandle.parents('.ui-slider:eq(0)').slider("values", handleIndex, thisIndex); }); //create slider component div var sliderComponent = jQuery('<div></div>'); //CREATE HANDLES selects.each(function(i){ var hidett = ''; //associate label for ARIA var thisLabel = jQuery('label[for=' + jQuery(this).attr('id') +']'); //labelled by aria doesn't seem to work on slider handle. Using title attr as backup var labelText = (thisLabel.size()>0) ? 'Slider control for '+ thisLabel.text()+'' : ''; var thisLabelId = thisLabel.attr('id') || thisLabel.attr('id', 'label_'+handleIds[i]).attr('id'); if( options.tooltip == false ){hidett = ' style="display: none;"';} jQuery('<a '+ 'href="#" tabindex="0" '+ 'id="'+handleIds[i]+'" '+ 'class="ui-slider-handle" '+ 'role="slider" '+ 'aria-labelledby="'+thisLabelId+'" '+ 'aria-valuemin="'+options.sliderOptions.min+'" '+ 'aria-valuemax="'+options.sliderOptions.max+'" '+ 'aria-valuenow="'+options.sliderOptions.values[i]+'" '+ 'aria-valuetext="'+ttText(options.sliderOptions.values[i])+'" '+ '><span class="screenReaderContext">'+labelText+'</span>'+ '<span class="ui-slider-tooltip ui-widget-content ui-corner-all"'+ hidett +'><span class="ttContent"></span>'+ '<span class="ui-tooltip-pointer-down ui-widget-content"><span class="ui-tooltip-pointer-down-inner"></span></span>'+ '</span></a>') .data('handleNum',i) .appendTo(sliderComponent); }); //CREATE SCALE AND TICS //write dl if there are optgroups if(groups) { var inc = 0; var scale = sliderComponent.append('<dl class="ui-slider-scale ui-helper-reset" role="presentation"></dl>').find('.ui-slider-scale:eq(0)'); jQuery(groups).each(function(h){ scale.append('<dt style=" '+ (100/groups.length).toFixed(2) +'%' +'; left:'+ (h/(groups.length-1) * 100).toFixed(2) +'%' +'"><span>'+this.label+'</span></dt>');//class name becomes camelCased label var groupOpts = this.options; jQuery(this.options).each(function(i){ var style = (inc == selectOptions.length-1 || inc == 0) ? 'style="display: none;"' : '' ; var labelText = (options.labelSrc == 'text') ? groupOpts[i].text : groupOpts[i].value; scale.append('<dd style="left:'+ leftVal(inc) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></dd>'); inc++; }); }); } //write ol else { var scale = sliderComponent.append('<ol class="ui-slider-scale ui-helper-reset" role="presentation"></ol>').find('.ui-slider-scale:eq(0)'); jQuery(selectOptions).each(function(i){ var style = (i == selectOptions.length-1 || i == 0) ? 'style="display: none;"' : '' ; var labelText = (options.labelSrc == 'text') ? this.text : this.value; scale.append('<li style="left:'+ leftVal(i) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></li>'); }); } function leftVal(i){ return (i/(selectOptions.length-1) * 100).toFixed(2) +'%'; } function onChange(value){ ttText(value); } //show and hide labels depending on labels pref //show the last one if there are more than 1 specified if(options.labels > 1) sliderComponent.find('.ui-slider-scale li:last span.ui-slider-label, .ui-slider-scale dd:last span.ui-slider-label').addClass('ui-slider-label-show'); //set increment var increm = Math.max(1, Math.round(selectOptions.length / options.labels)); //show em based on inc for(var j=0; j<selectOptions.length; j+=increm){ if((selectOptions.length - j) > increm){//don't show if it's too close to the end label sliderComponent.find('.ui-slider-scale li:eq('+ j +') span.ui-slider-label, .ui-slider-scale dd:eq('+ j +') span.ui-slider-label').addClass('ui-slider-label-show'); } } //style the dt's sliderComponent.find('.ui-slider-scale dt').each(function(i){ jQuery(this).css({ 'left': ((100 /( groups.length))*i).toFixed(2) + '%' }); }); //inject and return sliderComponent .insertAfter(jQuery(this).eq(this.length-1)) .slider(options.sliderOptions) .attr('role','application') .find('.ui-slider-label') .each(function(){ jQuery(this).css('marginLeft', -jQuery(this).width()/2); }); //update tooltip arrow inner color sliderComponent.find('.ui-tooltip-pointer-down-inner').each(function(){ var bWidth = jQuery('.ui-tooltip-pointer-down-inner').css('borderTopWidth'); var bColor = jQuery(this).parents('.ui-slider-tooltip').css('backgroundColor') jQuery(this).css('border-top', bWidth+' solid '+bColor); }); var values = sliderComponent.slider('values'); if(isArray(values)){ jQuery(values).each(function(i){ sliderComponent.find('.ui-slider-tooltip .ttContent').eq(i).text( ttText(this) ); }); } else { sliderComponent.find('.ui-slider-tooltip .ttContent').eq(0).text( ttText(values) ); } if(!options.selectshow){ this.css("display","none"); } return this; }代码中,加粗的为重点代码。
2、map.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/> <title></title> <link rel="stylesheet" href="jquery-slider/css/redmond/jquery-ui-1.7.1.custom.css" type="text/css" /> <link rel="Stylesheet" href="jquery-slider/css/ui.slider.extras.css" type="text/css" /> <link rel="stylesheet" href="http://localhost/arcgis_js_api/library/3.9/3.9/js/esri/css/esri.css"> <style type="text/css"> html, body, #map { height: 100%; margin: 0; padding: 0; font-size: 62.5%; font-family:"Segoe UI","Helvetica Neue",Helvetica,Arial,sans-serif; } fieldset { background: #fff; border:0; margin: 0em 4em; height: 4em; } label { font-weight: normal; float: left; margin-right: .5em; font-size: 1.1em; } select { margin-right: 1em; float: left; } </style> <script src="jquery-slider/jquery-1.8.3.js"></script> <script src="jquery-slider/jquery-ui-1.7.1.custom.min.js"></script> <script src="jquery-slider/selectToUISlider.jQuery.js"></script> <script src="http://localhost/arcgis_js_api/library/3.9/3.9/init.js"></script> <script type="text/javascript"> var map, fch; require([ "esri/map", "esri/layers/ArcGISTiledMapServiceLayer", "esri/layers/FeatureLayer", "esri/geometry/Point", "dojo/domReady!"], function(Map, Tiled, FeatureLayer, Point) { map = new Map("map",{logo:false}); var tiled = new Tiled("http://localhost:6080/arcgis/rest/services/image/MapServer"); map.addLayer(tiled); var mapCenter = new Point(103.847, 36.0473, map.spatialReference); map.centerAndZoom(mapCenter,4); <strong> map.on("load",function(){ fch = new FeatureLayer("http://localhost:6080/arcgis/rest/services/china/MapServer/6"); map.addLayer(fch); $('select#layers').selectToUISlider({ labels:6, tooltip:true, step:1, selectshow:false, baseUrl:"http://localhost:6080/arcgis/rest/services/china/MapServer/", orientation:"horizontal"//vertical,horizontal }); });</strong> }); </script> </head> <body> <div id="map"> <div style="position: absolute; bottom: 0px; left:35%; 600px;z-index: 99;"> <strong><fieldset> <select name="layers" id="layers"> <optgroup label="省级"> <option value="6">省会城市</option> <option value="0">省级行政区</option> </optgroup> <optgroup label="市级"> <option value="4">地级市</option> <option value="1">地州界</option> </optgroup> <optgroup label="县级"> <option value="3">县城驻地</option> <option value="2">市县界</option> </optgroup> </select> </fieldset></strong> </div> </div> </body> </html>在本实例中由于数据的关系是通过FeatureLayer来实现的,你可以通过ArcGISTiledMapServiceLayer来实现。
如有疑问,请联系:
QQ:1004740957
Email:niujp08@qq.com
加我或者来邮件请说明来意,谢谢!