一、模块定义
1、定义只含值对,没有任何依赖的模块(moudle1.js)
define({
color: "black",
size: "unisize"
});
2、定义没有任何依赖,但是需要一个准备活动的函数(moudle2.js)
define(function () {
//在这里可以一些准备工作
return {
color: "black",
size: "unisize"
}
//return 是模块的返回值
});
3、如果模块存在依赖,假设模块依赖需要用到dojo/dom模块(moudle3.js)
//该模块提供了一个方法,可以改变dom元素的innerHTML
define(["dojo/dom"], function(dom) {
return {
change: function(id,text) {
dom.byId(id).innerHTML=text
}
}
}
);
4、将模块定义为函数(moudle4.js)
define(function() {
return function(text) {
//弹出一下text文本
alert(text);
}
}
);
二、定义模块所处的位置
将每个js文件看做一个模块,通过dojoConfig去添加我们自己的配置,告诉dojo框架自定义模块所处的位置用的是packages属性,如下
<script>var dojoConfig={packages: [{name: "js",//模块的名字location: location.pathname.replace(/\/[^/]*$/, '') + '/js'//模块所处的路径}]} </script>
dojo部署配置:
<link rel="stylesheet" type="text/css" href="arcgis_js_v317_api/arcgis_js_api/library/3.17/3.17/dijit/themes/tundra/tundra.css" /><link rel="stylesheet" type="text/css" href="arcgis_js_v317_api/arcgis_js_api/library/3.17/3.17/esri/css/esri.css" /><script type="text/javascript">var dojoConfig={baseUrl:"arcgis_js_v317_api/arcgis_js_api/library/3.17/3.17compact/dojo",packages: [{name: "js",location: location.pathname.replace(/\/[^/]*$/, '') + '/js'}]}</script><script type="text/javascript" src="arcgis_js_v317_api/arcgis_js_api/library/3.17/3.17compact/init.js"></script><script type="text/javascript">var map;require(["esri/map", "dojo/domReady!"], function (Map) {map = new Map("mapDiv", {basemap: "topo",center:[120,32],zoom:10});});</script>
三、require中的调用
require(["js/moudle1","js/moudle2","js/moudle3","js/moudle4"], function(moudle1,moudle2,moudle3,moudle4) {alert(moudle1.color)alert(moudle2.color)moudle3.change("test1","文本改变了moudle3")moudle4("aaaa")});
四、dojo/dom
该模块定义了Dojo Dom API,主要有以下几种用法:
1、dom.byId();(相当于document.getElementById())
①最直接的用法:
require(["dojo/dom"], function(dom){
var node = dom.byId("someNode");
});
②它是domNode,可以继续操作属性(也就是可以直接后面"."xxx.xxx...)
dom.byId("someNode").innerHTML = "Hello World";
③如果引用dom.byId();像这样:
var node = dom.byId("someNode");
var other = dom.byId(node);
console.log(node == other);//true
④require(["dojo/dom", "dojo/dom-style"], function(dom, domStyle){
domStyle.set(dom.byId("foo"), "opacity", 0.5);
//等同于(当然下面这种写法更好)
domStyle.set("foo", "opacity", 0.5);
});
举个例子:(dojo/on,dojo/_base/fx,dojo/domReady!我们不难看出它们是什么,后面继续学习)
require(["dojo/dom", "dojo/on", "dojo/_base/fx", "dojo/domReady!"],
function(dom, on, baseFx){
var node = dom.byId("findMe");
on(dom.byId("buttonOne"), "click", function(){
baseFx.fadeOut({ node: node, duration: 300 }).play();
});
on(dom.byId("buttonTwo"), "click", function(){
baseFx.fadeIn({ node: node, duration: 300 }).play();
})
});
<button id="buttonOne">隐藏</button> <button id="buttonTwo">显示</button>
<div id="findMe">Hi!</div>
2、isDescendant()
判断该节点是否是另外一个节点的子节点(后代节点)
require(["dojo/dom"], function(dom){
dom.isDescendant("child", "ancestor");
})
举个例子:
require(["dojo/dom", "dojo/domReady!"], function(dom){
var output = "";
if (dom.isDescendant("child", "ancestor")){
output += "'child' is a descendant of 'ancestor'</br>";
}else{
output += "'child' is not a descendant of 'ancestor'</br>";
}
if (dom.isDescendant("loner", "ancestor")){
output += "'loner' is a descendant of 'ancestor'</br>";
}else{
output += "'loner' is not a descendant of 'ancestor'</br>";
}
dom.byId("output").innerHTML = output;
});
<div id="ancestor">
<div id="child">I'm a child!</div>
</div>
<div id="loner">I'm not a child!</div>
<div id="output"></div>
3、setSelectable()
启用或禁用一个节点上的选择
举个例子:
require(["dojo/dom", "dojo/on", "dojo/domReady!"], function(dom, on){
on(dom.byId("button1"), "click", function(){
dom.setSelectable("model", true);
});
on(dom.byId("button2"), "click", function(){
dom.setSelectable("model", false);
});
});
<div id="model">Am I selectable?</div>
<button id="button1">setSelectable True</button>
<button id="button2">setSelectable False</button>
4、dojo/dom-attr该模块定义了Dojo DOM attributes API,属性有:
has(),get(),set(),remove(),getNodeProp() 对node属性的增删改查...
require(["dojo/dom-attr"], function(domAttr){
result = domAttr.has/get...("myNode", "someAttr");
})
5、dojo/dom-class
contains(),add(),remove(),replace(),toggle()对node className的增删改查...
6、dojo/dom-construct
toDom()实例化一个HTML片段返回相应的DOM
place()在已有的DOM树添加或者更改HTML片段
create()创建DOM简化DOM操作
empty()删除子元素
destroy()删除DOM,包括自身
7、dojo/dom-form 该模块定义了表单处理功能
fieldToObject()接收表单id返回它的值,跳过禁用表单控件和没选择的radio和checkbox,如果是select返回一个values的字符串数组
toObject()接收表单id返回{"name":"value","name":"value"...}对象,跳过禁用表单控件和没选择的radio和checkbox
toQuery()将输入表单的数据转换为URL
toJson()将输入表单的数据转换为JSON对象
8、dojo/dom-geometry 该模块定义了dojo DOM几何API,返回DOM节点的边框,大小,位置以及坐标等...
dojo/dom-geometry::position()
dojo/dom-geometry::getMarginBox()
dojo/dom-geometry::setMarginBox()
dojo/dom-geometry::getContentBox()
dojo/dom-geometry::setContentSize()
dojo/dom-geometry::getPadExtents()
dojo/dom-geometry::getBorderExtents()
dojo/dom-geometry::getPadBorderExtents()
dojo/dom-geometry::getMarginExtents()
dojo/dom-geometry::isBodyLtr()
dojo/dom-geometry::normalizeEvent()
dojo/dom-geometry::docScroll()
dojo/dom-geometry::fixIeBiDiScrollLeft()
dojo/dom-geometry::getMarginSize()
9、dojo/dom-prop 该模块是获取或设置DOM的各种类型属性,dojo/dom-style获取或设置DOM节点的Style
get(),set()
10、dojo/domReady! AMD加载插件,等到DOM加载完成后
dojo/query
1、该模块提供了DOM查询功能,输出一个函数,可以用来查询DOM节点的CSS选择器。
比如:require(["dojo/query!sizzle"], function(query){
query("div")...
(Sizzle是一个纯javascript CSS选择器引擎)
2、如果你想用CSS3伪类选择器,可以这样:
require(["dojo/query!css3"], function(query){
query('#t > h3:nth-child(odd)')...
3、query(selector,context)第一个参数是CSS选择器(String),第二个参数是可选的上下文来限制搜索范围(String|DomNode)
比如:require(["dojo/query", "dojo/dom"], function(query, dom){
var nl = query(".someClass", "someId");
// or
var node = dom.byId("someId");
nl = query(".someClass", node);
});
4、dojo/query()返回的是一个NodeList类数组对象,(判断是否是数组的最简单也是最有效的方法:
function isArray(arr) {
return Object.prototype.toString.call(arr) ==="[object Array]";
})
NodeList可以直接使用数组的方法,最常见的几种方法:
①at(),返回一个新的NodeList,数字参数(可以是多个)支持负数参数(原来的NodeList下标)指定新的NodeList下标0开始,比如:
require(["dojo/query"], function(query){
var nodelist = query("ul > li").at(0,-1);
console.log(nodelist);
});
<ul><li id="l1"></li>
<li id="l2"></li>
<li id="l3"></li>
<li id="l4"></li>
<li id="l5"></li></ul>
②concat()返回一个新的NodeList,和数组的拼接一样,如:
require(["dojo/query"], function(query){
var nodelist = query("h1").concat(query("h2"));
console.log(nodelist);
});
③end()该方法没有参数,用在超链接中,回到之前的NodeList,如:
require(["dojo/query", "dojo/NodeList-dom"], function(query){
query("a")
.filter(".disabled")
.style("color", "grey")
.end()
.style("fontSize", "50px");
});
④every()、some()该方法是数组的迭代方法;
其中every()如果NodeList中每个node都返回true,它才返回true;
some()如果NodeList中每个node都返回false,它才返回false,
every()、some()就像逻辑中的&、||比如:
require(["dojo/query"], function(query){
if(query(".someclass").every/some(function(node){
return node.innerHTML == "hello";
})){
// function is true for every node (every)
// function is true for at least one node (some)
}else{
// function is not true for every node
}
});
⑤forEach()遍历每个节点,如:
require(["dojo/query"], function(query){
query(".someclass").forEach(function(node){
// node will be each node in the list.
});
});
⑥indexOf()、lastIndexOf()查找指定参数首次(找到一个就不在继续往下找了)出现的位置,找到返回下标,找不到返回-1;
indexOf()从左向右开始找,lastIndexOf()从右向左找 如:
require(["dojo/query", "dojo/dom"], function(query, dom){
var node = dom.byId("someId");
var idx = query(".someClass").indexOf/lastIndexOf(node);
// if idx >= 0 then node has a class of someClass
// if idx = -1 then node doesn't have class of someClass
});
⑦instantiate()类的实例化,将可选配置对象传递给构造函数,如:
require(["dojo/query", "dijit/form/Button"], function(query, Button){
// Converts all button nodes to dijit/form/Buttons
query("button").instantiate(Button, {
showLabel: true
});
});
⑧map()将NodeList中的所有node传给回调函数,返回新的NodeList 如:
require(["dojo/query"], function(query){
var nodelist = query("h1").map(function(node){
return node.parentNode;
});
// nodelist contains all the parent nodes of every heading level 1 node
});
⑨on()给NodeList中所有/指定node绑定监听事件,我们到dojo/on中继续学习 如:
require("dojo/query", function(query){
query("button").on("click", function(e){
console.log("click!");
});
// Every button will log "click!" to the console when clicked
});
require("dojo/query", function(query){
query("#mylist").on("li:click", function(e){
console.log("click!");
});
// Listens for onclick events on list items in the list with an ID of "myList"
});
require("dojo/query", function(query){
query("#mylist").on("li button:mouseover, li:click", function(e){
console.log("hello!");
});
});
⑩其它像slice(),splice(),push(),pop(), shift(),unshift()等等就不在细说了,都是数组的方法。
dojo/NodeList-data 该模块通过简单的data API扩展了NodeList,可以将data数据绑定到单独的node节点,从而可以通过查询该节点来获取数据。
通常结合dojo/query一起用:
require(["dojo/query", "dojo/NodeList-data"], function(query){
query("#aNode").data("someKey", "someValue");
});
扩展了两个方法:data(),removeData()
①data()添加或获取NodeList中的任何数据;传两个参数(data("key","value"))时,函数会把这些数据data设置在NodeList的每个node中;
传一个参数(data("key"))时,它会作为一个getter返回一个数组arr(arr[0]指定key的值)。如:
require("dojo/query", "dojo/NodeList-data", function(query){
query("#foo").data("bar", "baz");
var values = query("#foo").data("bar");
if(values[0] == "baz"){
// do something
}
});
当data()作为setter时,它返回的是实例化NodeList的操作,所以可以继续操作 如:
require("dojo/query", "dojo/NodeList-data", function(query){
query(".someClass")
.data("bar", "baz")
.data("qat", "qut");
});
data()也可以接收一个对象,然后将数据混合到该节点:
require("dojo/query", "dojo/NodeList-data", function(query){
query("#foo").data({
a: "bar",
b: "baz",
c: [0, 1, 3]
});
var a = query("#foo").data("a")[0];
// a == "bar"
var b = query("#foo").data("b")[0];
// b == "baz"
var c = query("#foo").data("c")[0];
// c == [0, 1, 3]
});
当data()调用没有参数时,它返回一个包含所有的数据值的数组:
require(["dojo/query", "dojo/NodeList-data"], function(query){
query("#foo").data("a", "bar")
.data("b", "baz")
.data("c", [0, 1, 3]);
var values = query("#foo").data()[0];
// values == { a: "bar", b: "baz", "c": [0, 1, 3] }
});
②removeData()删除数据,指定参数key时,删除指定key的属性;没有参数则删除所有数据:
require(["dojo/query", "dojo/NodeList-data"], function(query){
query("#foo").removeData(); // add data removed
query("#foo").removeData("bar"); // only "bar" removed
});
当DOM改变时,有些节点不存在时可以手动删除不存在的节点的数据:
require(["dojo/_base/kernel", "dojo/NodeList-data"], function(kernel){
kernel._gcNodeData();
});
五、dojo.declare 定义类
dojo.declare 参数定义
dojo.declare(/*String*/ className,
/*Function | Function[]*/ superclass,
/*Object*/ props )
- className: 是要要申明的类的类名,也就是创建的构造函数的名称。
- superclass:所要继承的父类,此参数可为 null,表示没有父类,或者为一个父类,或为多个父类的数组,会在后续小节内详述。
- props:散列体,由名、值(key, value)对组成,这个散列体将被添加到定义的类的原型对象中,也即为定义的类被其所有实例共享的属性及方法。其中,key :constructor 为保留字,此函数用来初始化新对象。
如清单 6 所示,我们用 dojo.declare 定义了一个名为 ClassX 的类,父类为空,即无父类,类的每个实例都有属性 messageX,在调用 constructor 函数初始化新对象时赋值,并为类的原型设置了 sayMessageX 方法。
dojo.declare 定义类示例
dojo.declare( "ClassX", // 类的名字null, // 父类// 要加入新定义类的原型的所有属性及方法 { messageX: null, constructor: function(msgX){ this.messageX = msgX; }, sayMessageX: function(){ alert("hi, this is " + this. messageX); } } );
定义类 ClassX 后,便可以使用了,由示例代码可见,类 ClassX 的对象既是 ClassX 的实例也是 Object 的实例。
ClassX 使用示例
var objX = new ClassX("X");
objX. sayMessageX(); //output: "hi, this is X"
objX instanceof ClassX; //true
objX instanceof Object;//true
利用多继承定义 ClassZ 示例
dojo.declare( "ClassZ", // 类的名字[ClassX,ClassY] // 父类// 要加入新定义类的原型的所有属性及方法 { messageZ: null, constructor: function(msgX,msgY,msgZ){ this.messageZ = msgZ; this.setMessageY(msgY); }, sayMessageZ: function(){ alert("hi, this is " + this.messageZ); } } );
六、Dojo Widget 传入参数处理机制
Dojo所开发的控件具有很强的内聚性和面向对象性。dojo的dijit._widget是dojo提供的图形界面组件库
1、dijit本身的生命周期方法,
组件的生命周期指的是某一个组件从创建到销毁的存续阶段。理解在各个阶段被调用的函数有助于自定义组件或继承组件的功能扩展。
constructor():
构造函数,在使用new操作时被调用,发生在参数被混合进组件实例之前,主要用于状态、属性的初始化。
参数被混合进组件实例:
如果使用标签化实现或编程实现来实例化一个组件类的时候,传入参数,比如<button dojoType="dijit.form.Button" iconClass ="">或new dijit.form.Button({iconClass: ""}),该阶段没有关联特殊的函数,但我们可以使用传入的这些参数值。
postMixInProperties()自定义属性:
使用自定义属性,如果在你的widget里面需要自定义属性。该函数会在该组件对应DOM节点创建前被调用。可以通过参数传入一个包含各种属性的javascript对象,这些属性被混入到dijit组件中,可以通过this调用。当混入完成之后,在创建dijit组件界面之前,还可以加入自己的业务。
buildRendering()创建其外观:
该方法用来创建dijit组件的用户界面,即DOM节点,该方法完成时候,this.domNode指向的是刚创建的DOM节点。
postCreate()快速创建:
被自定义组件经常使用的一个函数。当DOM节点被创建完成之后,此方法被调用。需要注意的是,这个时候组件的DOM节点还没有被添加到当前页面文档树。一般用来添加添加组件相关的逻辑。
startup()如果要创建一个孩子widget:
在建立了一个父组件后,还需要添加若干子组件(这里的子组件不是表示继承关系,而是表示包含关系),并希望全部加载后一起展现时,就可以调用该函数。
一个关于该函数的最佳实践就是即使没有子组件,也对一个组件新建实例调用该函数,
destroy():
dijit组件的销毁过程比较复杂。组件实例的销毁,占用资源的释放。包括该组件的DOM节点,类似C语言里的析构函数。dijit._Widget提供了多个以destroy为前缀的方法,如destroyRecursive()用于某组件以及其内部包含的子组件(这里的子组件含义同startup处的说明)的销毁。
调用顺序为constructor、postCreate、startup
1.dojo.require("dijit.layout.ContentPane"); 2.dojo.declare("Test", [ dijit.layout.ContentPane ], { 3. tagattr1: "", 4. 5. constructor: function(){ 6. console.log("=============constructor============="); 7. console.log("this.title: ", this.title); 8. console.log("this.tagattr1: ", this.tagattr1); 9. console.log("arguments[0].title: ", arguments[0].title); 10. console.log("arguments[0].tagattr1: ", arguments[0].tagattr1); 11. }, 12. 13. postCreate: function(){ 14. console.log("=============postCreate============="); 15. console.log("this.title: ", this.title); 16. console.log("this.tagattr1: ", this.tagattr1); 17. }, 18. 19. startup: function(){ 20. console.log("=============startup============="); 21. console.log("this.title: ", this.title); 22. console.log("this.tagattr1: ", this.tagattr1); 23. } 24.});
2、核心类dijit._Widget
dijit._Widget是所以dijit组件的父类,dijit默认提供的组件和自己开发的组件都要继承此类。dijit._Widget提供了对组件生命周期的管理。dijit组件生命周期管理在实现的时候使用了template method设计方式。dijit._Widget的create()方法定义了默认模版。开发人员也可以覆盖create()方法,提供一套不同的生命周期实现。dijit定义的生命周期实现:
图中椭圆行的三个方法是dijit提供的扩展点,用户可以自己覆盖这些方法。startup方法需要显示被调用。
组件的connect()绑定事件处理方法。subscribe()监听事件通知
3、核心类:dijit._Templated
dijit._Template提供了一种从HTML模版中创建用户界面的方式。dijit._Templated是作为一个混入类来使用的。在dojo.declear()定义新组件的时候,dijit._Widget需要作为基类,而dijit._Templated要作为混入类,也就是说在父类声明中dijit._Widget需要作为第一个出现,否则会出错。
可以通过templateString 和templatePath两种方式指定使用的模版。
可以通过设定widgetInTemplate的值为true来声明该dijit组件包含其他组件。这些包含的组件在destroy方法中被销毁。
在模版中可以使用dojoAttachPoint和dojoAttachEvent两个特殊的DOM节点属性。dojoAttachPoint属性的值是当前DOM节点,dojoAttachEvent属性的值来完成事件处理绑定。
4、核心类:dijit._Container
dijit._Container提供了管理子组件的功能。它所提供的方法有:
addChild(widget,insertIndex);
removeChild(widget);
getChildren();包含子组件的数组。
hasChildren();是否包含子组件。
getIndexOfChild();
需要注意:dijit._COntianer只能包含dijit组件,也就是必须继承子dijit._Widget,不能包含普通的DOM组件。对于DOM节点可以用dijit.layout.pane封装之后,再添加到dijit._Container中。
七、draw类
实例:
1.<!DOCTYPE html> 2.<html> 3. <head> 4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 5. <meta http-equiv="X-UA-Compatible" content="IE=7, IE=9"> 6. <meta name="viewport" content="width=device-width,user-scalable=no"> 7. <!--The viewport meta tag is used to improve the presentation and behavior of the samples on iOS devices--> 8. <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"> 9. <title>地图工具栏</title> 10. 11. <link rel="stylesheet" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.3/js/dojo/dijit/themes/claro/claro.css"> 12. <link rel="stylesheet" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.3/js/esri/css/esri.css"> 13. <style> 14. html, body { 15. height: 100%; width: 100%; margin: 0; padding: 0; 16. } 17. </style> 18. 19. <script>var dojoConfig = { 20. parseOnLoad: true // 解析加载 21. };</script> 22. <script src="http://serverapi.arcgisonline.com/jsapi/arcgis/3.3/"></script> 23. <script> 24. // 导入包 25. dojo.require("esri.map"); 26. dojo.require("esri.toolbars.draw"); 27. dojo.require("dijit.layout.BorderContainer"); 28. dojo.require("dijit.layout.ContentPane"); 29. 30. var map, toolbar, symbol, geomTask; 31. 32. function init() { 33. map = new esri.Map("map", { 34. basemap: "streets", // 指定的地图底图。以下是有效的选项:"streets","satellite","hybrid","topo","gray","oceans","national-geographic","osm". 35. center: [-15.469, 36.428], // 经纬度 36. zoom: 3 // 缩放深度 37. }); 38. 39. dojo.connect(map, "onLoad", createToolbar); // 绑定加载事件 40. } 41. 42. function createToolbar(themap) { 43. toolbar = new esri.toolbars.Draw(map); // esri.toolbars.Draw(map, options) 44. dojo.connect(toolbar, "onDrawEnd", addToMap); // 绘制完成触发 45. } 46. 47. function addToMap(geometry) { 48. toolbar.deactivate(); // 关闭工具栏并激活地图导航. 49. map.showZoomSlider(); //在地图上显示的缩放滑块 50. // 判断几何图形的类型 51. switch (geometry.type) { 52. case "point": 53. var symbol = new esri.symbol.SimpleMarkerSymbol( 54. esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, // 样式,STYLE_CIRCLE(●),STYLE_CROSS(+),STYLE_DIAMOND(◆),STYLE_SQUARE(■),STYLE_X(X) 55. 10, // 像素 56. new esri.symbol.SimpleLineSymbol( 57. esri.symbol.SimpleLineSymbol.STYLE_SOLID, // 样式,STYLE_DASH(破折号),STYLE_DASHDOT(点划线),STYLE_DASHDOTDOT,STYLE_DOT(点),STYLE_NULL,STYLE_SOLID(实线) 58. new dojo.Color([255,0,0]), // 颜色 59. 1 // 像素 60. ), 61. new dojo.Color([0,255,0,0.25]) // 颜色和透明度 62. ); 63. break; 64. case "polyline": 65. var symbol = new esri.symbol.SimpleLineSymbol( 66. esri.symbol.SimpleLineSymbol.STYLE_SOLID, 67. new dojo.Color([255,0,0]), 68. 1 69. ); 70. break; 71. case "polygon": 72. var symbol = new esri.symbol.SimpleFillSymbol( 73. esri.symbol.SimpleFillSymbol.STYLE_SOLID, 74. new esri.symbol.SimpleLineSymbol( 75. esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, 76. new dojo.Color([255,0,0]), 77. 2 78. ), 79. new dojo.Color([255,255,0,0.25]) 80. ); 81. break; 82. case "extent": 83. var symbol = new esri.symbol.SimpleFillSymbol( 84. esri.symbol.SimpleFillSymbol.STYLE_SOLID, 85. new esri.symbol.SimpleLineSymbol( 86. esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, 87. new dojo.Color([255,0,0]), 88. 2 89. ), 90. new dojo.Color([255,255,0,0.25]) 91. ); 92. break; 93. case "multipoint": 94. var symbol = new esri.symbol.SimpleMarkerSymbol( 95. esri.symbol.SimpleMarkerSymbol.STYLE_DIAMOND, 96. 20, 97. new esri.symbol.SimpleLineSymbol( 98. esri.symbol.SimpleLineSymbol.STYLE_SOLID, 99. new dojo.Color([0,0,0]), 100. 1 101. ), 102. new dojo.Color([255,255,0,0.5]) 103. ); 104. break; 105. } 106. var graphic = new esri.Graphic(geometry, symbol); 107. map.graphics.add(graphic); // 将绘图加入到图层中 108. } 109. dojo.ready(init); // 初始化加载 110. </script> 111. </head> 112. <body class="claro"> 113.<div id="mainWindow" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;"> 114. <div id="header" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'" style="height:75px;text-align:left;font-weight:bold;font-size:14px;color:#400D12;overflow:hidden;"> 115. <span>绘制:<br /></span> 116. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.POINT);map.hideZoomSlider();}">Point(点)</button> 117. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.MULTI_POINT);map.hideZoomSlider();}">Multipoint(多点)</button> 118. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.LINE);map.hideZoomSlider();}">Line(线)</button> 119. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.POLYLINE);map.hideZoomSlider();}">Polyline(折线)</button> 120. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.POLYGON);map.hideZoomSlider();}">Polygon(多边形)</button> 121. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.FREEHAND_POLYLINE);map.hideZoomSlider();}">Freehand Polyline(手绘折线)</button> 122. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.FREEHAND_POLYGON);map.hideZoomSlider();}">Freehand Polygon(手绘多边形)</button> 123. <!-- 箭头,三角形,圆形和椭圆类型所有绘制的多边形符号 --> 124. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.ARROW);map.hideZoomSlider();}">Arrow(箭头)</button> 125. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.TRIANGLE);map.hideZoomSlider();}">Triangle(三角形)</button> 126. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.CIRCLE);map.hideZoomSlider();}">Circle(圆形)</button> 127. <button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:function(){toolbar.activate(esri.toolbars.Draw.ELLIPSE);map.hideZoomSlider();}">Ellipse(椭圆)</button> 128. </div> 129. <div id="map" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center'"> 130. </div> 131.</div> 132. </body> 133.</html>
options:
常量 | 描述 |
ARROW | 绘制箭头. |
UP_ARROW | 绘制一个上箭头. |
DOWN_ARROW | 绘制一个下箭头 |
LEFT_ARROW | 绘制一个左箭头. |
RIGHT_ARROW | 绘制一个右箭头 |
POINT | 绘制点. |
MULTI_POINTPOINT | 绘制多点. |
ELLIPSE | 绘制一个椭圆形. |
POLYGON | 绘制多边形. |
POLYLINE | 绘制折线. |
FREEHAND_POLYGON | 手绘多边形. |
FREEHAND_POLYLINE | 手绘折线. |
LINE | 绘制线 |
RECTANGLE | 绘制一个矩形 |
CIRCLE | 绘制圆. |
TRIANGLE | 绘制一个三角形. |
EXTENT | Draws an extent box. |
属性:
属性 | 类型 | 描述 |
fillSymbol | SimpleFillSymbol | 当绘制 Polygon 或 Extent 时使用的符号. |
lineSymbol | SimpleLineSymbol | 当绘制 Polyline 时使用的符号. |
markerSymbol | SimpleMarkerSymbol | 当绘制 Point 绘制Multipoint 时使用的符号. |
respectDrawingVertexOrder | Boolean | 设置为false, 几何图形被修改成拓扑正确项. 设置为true,输入几何体不被修改. |
方法:
activate(geometryType, options?) | None | 激活工具栏的绘图几何形状。激活工具栏禁用地图导航。 |
deactivate() | None | 关闭工具栏并激活地图导航. |
finishDrawing() | none | 最后,绘制的几何形状并触发onDrawEnd事件.工作时使用此方法来完成绘制折线,多边形或点对多点,支持触摸的设备iPhone. |
setFillSymbol(fillSymbol) | None | 设置 fill symbol. |
setLineSymbol(lineSymbol) | None | 设置线符号 |
setMarkerSymbol(markerSymbol) | None | 设置标记符号 |
setRespectDrawingVertexOrder(set) | None | Sets whether the polygon geometry should be modified to be topologically correct. |
八、dojo 加载自定义module的路径问题
<script type="text/javascript"> var dojoConfig={ baseUrl:"", tlmSiblingOfDojo: false, packages:[ {"name":"dojo","location":'dojo-release-1.10.4/dojo'}, {"name":"mytest","location":"mytest",main:"myModule"}, ] }; </script> <script data-dojo-config="async: true" src="dojo-release-1.10.4/dojo/dojo.js"></script> <script type="text/javascript"> require( ['mytest/myModule'],function(myModule){ //do something with myModule }) </script>
说明:
1.dojoConfig 必须set在加载dojo.js之前,否则在控制台调试时会发现报错。
2.baseUrl是什么?
默认值是dojo.js所在文件夹的路径,此例中即dojo-release-1.10.4/
所有的package路径都是相对于baseUrl,例如:如果我这样设置baseUrl:"/myfolder/",那么当我加载模块“mytest/myModule”,loader将会从下面路径去加载:
/myfolder/mytest/myModule.js
3.tlmSiblingOfDojo是什么?
默认值是true,此时loader将从dojo.js所在文件夹的同级文件夹中加载模块
4.packages
一个array,包含多个module及每个module对应的features。
※ name:the name of the package. 即包含了自定义module js文件的文件夹名,如此例中的“my”。
※ location:the location of the package. 可以是基于baseUrl的相对路径也可以是绝对路径。
采取相对路径时,当我require“mytest/myModule”, loader将从形如下面的路径加载module:
baseUrl+mytest的location+”/myModule.js
※ main:默认值是main.js。用于require package本身时告诉loader该去加载什么文件。例如,当我require “mytest”而不是“mytest/myModule”时,loader依然知道去load myModule.js。
另一种情况,当直接require一个没有在packages里define过的package时,如“anotherTest”时,loader将会尝试去加载下面的文件:
baseUrl+anotherTest.js
九、图层控制
1.图层控制显示
1.dojo.connect(dynamicMapServiceLayer, "onLoad", loadLayerList); 2. function loadLayerList(layers) { 3. var html = "" 4. var infos = layers.layerInfos; 5. for (var i = 0, length = infos.length; i < length; i++) { 6. var info = infos[i]; 7. //图层默认显示的话就把图层id添加到visible 8. if (info.defaultVisibility) { 9. visible.push(info.id); 10. } 11. //输出图层列表的html 12. html = html + "<div><input id='" + info.id + "' name='layerList' class='listCss' type='checkbox' value='checkbox' οnclick='setLayerVisibility()' " + (info.defaultVisibility ? "checked" : "") + " />" + info.name + "</div>"; 13. } 14. //设置可视图层 15. dynamicMapServiceLayer.setVisibleLayers(visible); 16. //在右边显示图层名列表 17. dojo.byId("toc").innerHTML = html; 18. } 19. setLayerVisibility = function () { 20. //用dojo.query获取css为listCss的元素数组 21. var inputs = dojo.query(".listCss"); 22. visible = []; 23. //对checkbox数组进行变量把选中的id添加到visible 24. for (var i = 0; i < inputs.length; i++) { 25. if (inputs[i].checked) { 26. visible.push(inputs[i].id); 27. } 28. } 29. //设置可视图层 30. dynamicMapServiceLayer.setVisibleLayers(visible); }
2.拉框查询
1.map.on("load", initSelectToolbar); 2. 3. var fieldsSelectionSymbol = 4. new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, 5. new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, 6. new Color([0, 255, 0]), 1), 7. new Color([255, 0, 0, 5])); 8. 9. featureLayer = new FeatureLayer("http://localhost:6080/arcgis/rest/services/MyMapService/MapServer/5"); 10. map.addLayer(featureLayer); 11. featureLayer.setSelectionSymbol(fieldsSelectionSymbol); 12. 13. on(dom.byId("selectFieldsButton"), "click", function () { 14. selectionToolbar.activate(Draw.EXTENT); 15. }); 16. 17. on(dom.byId("clearSelectionButton"), "click", function () { 18. featureLayer.clearSelection(); 19. }); 20. 21. function initSelectToolbar(event) { 22. selectionToolbar = new Draw(event.map); 23. var selectQuery = new Query(); 24. 25. on(selectionToolbar, "DrawEnd", function (geometry) { 26. selectionToolbar.deactivate(); 27. selectQuery.geometry = geometry; 28. featureLayer.selectFeatures(selectQuery, 29. FeatureLayer.SELECTION_NEW); 30. }); 31. } 32. 33. 34. }); 35. </script> </head>
3、地图的基本加载
1.<!DOCTYPE html> 2.<html> 3.<head> 4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 5. <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" /> 6. <title>final Map</title> 7. <link rel="stylesheet" href="http://localhost/arcgis_js_v314_api/arcgis_js_api/library/3.14/3.14/esri/css/esri.css"> 8. 9. <style> 10. html, body, #map { 11. height: 100%; 12. margin: 0; 13. padding: 0; 14. } 15. 16. body { 17. background-color: #FFF; 18. overflow: hidden; 19. font-family: "Trebuchet MS"; 20. } 21. 22. #BasemapToggle { 23. position: absolute; 24. right: 20px; 25. top: 20px; 26. z-index: 50; 27. } 28. 29. #HomeButton { 30. left: 25px; 31. position: absolute; 32. top: 93px; 33. z-index: 50; 34. } 35. 36. #LocateButton { 37. left: 25px; 38. position: absolute; 39. top: 130px; 40. z-index: 50; 41. } 42. 43. #search { 44. display: block; 45. position: absolute; 46. z-index: 2; 47. top: 25px; 48. left: 75px; 49. } 50. </style> 51. <script src="http://localhost/arcgis_js_v314_api/arcgis_js_api/library/3.14/3.14/init.js"></script> 52. <script> 53. var map, mapCenter, selectionToolbar, featureLayer; 54. var visible = [], setLayerVisibility;; 55. require([ 56. "esri/basemaps", 57. "esri/map", 58. "esri/layers/ArcGISTiledMapServiceLayer", 59. "esri/layers/FeatureLayer", 60. "esri/layers/GraphicsLayer", 61. "esri/geometry/Point", 62. 63. "esri/symbols/SimpleFillSymbol", 64. "esri/symbols/SimpleLineSymbol", 65. "esri/symbols/SimpleMarkerSymbol", 66. "esri/tasks/query", 67. "esri/toolbars/draw", 68. 69. "esri/graphic", 70. "esri/dijit/Scalebar", 71. "esri/dijit/HomeButton", 72. "esri/dijit/LocateButton", 73. "esri/dijit/BasemapToggle", 74. "esri/dijit/OverviewMap", 75. "esri/dijit/Search", 76. "esri/geometry/webMercatorUtils", 77. 78. "dojo/dom", 79. "dojo/on", 80. "dojo/_base/Color", 81. "dojox/charting/Chart2D", 82. "dojo/domReady!"], 83. function ( 84. esriBasemaps, 85. Map, 86. Tiled, 87. FeatureLayer, 88. GraphicsLayer, 89. Point, 90. 91. SimpleFillSymbol, SimpleLineSymbol, SimpleMarkerSymbol, 92. Query, 93. Draw, 94. 95. Graphic, 96. Scalebar, 97. HomeButton, 98. LocateButton, 99. BasemapToggle, 100. OverviewMap, 101. Search, 102. webMercatorUtils, 103. 104. dom, 105. on, 106. 107. Color, 108. Chart2D, 109. domConstruct) { 110. 111. esriBasemaps.delorme = { 112. baseMapLayers: [ 113. //中国矢量地图服务 114. { url: "http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer" } 115. ], 116. //缩略图 117. thumbnailUrl: "shiliang.jpg", 118. title: "矢量图" 119. }; 120. 121. //初始化地图 122. map = new esri.Map("map", { basemap: "delorme", logo: false, }); 123. 124. //map = new Map("map", {logo:false,slider: true}); 125. //var tiled = new Tiled("http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer"); 126. //map.addLayer(tiled,0); 127. var dynamicMapServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://localhost:6080/arcgis/rest/services/MyMapService/MapServer"); 128. map.addLayer(dynamicMapServiceLayer, 1); 129. var chartLayer = new GraphicsLayer({ "id": "chartLayer" }); 130. map.addLayer(chartLayer, 2); 131. mapCenter = new Point(103.847, 36.0473, map.spatialReference); 132. map.centerAndZoom(mapCenter, 4); 133. /*************************************************************************************/ 134. //卫星底图 135. var toggle = new BasemapToggle({ 136. map: map, 137. basemap: "satellite" 138. }, "BasemapToggle"); 139. toggle.startup(); 140. //返回主视图 141. var home = new HomeButton({ 142. map: map 143. }, "HomeButton"); 144. home.startup(); 145. //定位 146. var geoLocate = new LocateButton({ 147. map: map 148. }, "LocateButton"); 149. geoLocate.startup(); 150. //鹰眼 151. var overviewMapDijit = new OverviewMap({ 152. map: map, 153. expandFactor: 2, 154. attachTo: "bottom-left", 155. visible: true 156. }); 157. overviewMapDijit.startup(); 158. //比例尺 159. var scalebar = new esri.dijit.Scalebar({ 160. map: map,//地图对象 161. attachTo: "bottom-right",//控件的位置,右下角 162. scalebarStyle: "ruler",//line 比例尺样式类型 163. scalebarUnit: "metric"//显示地图的单位,这里是km 164. }); 165.//搜索 166. var search = new Search({ 167. map: map 168. }, "search"); 169. search.startup(); 170. //显示地图坐标 171. map.on("load", function () { 172. //after map loads, connect to listen to mouse move & drag events 173. map.on("mouse-move", showCoordinates); 174. map.on("mouse-drag", showCoordinates); 175. }); 176. function showCoordinates(evt) { 177. //the map is in web mercator but display coordinates in geographic (lat, long) 178. var mp = webMercatorUtils.webMercatorToGeographic(evt.mapPoint); 179. //display mouse coordinates 180. dom.byId("info").innerHTML = mp.x.toFixed(3) + ", " + mp.y.toFixed(3); 181. } 182.<body> 183. <div id="map"> 184. 185. <!-- 返回初始化地图按钮--> 186. <div id="HomeButton"></div> 187. <!-- Html5定位按钮--> 188. <div id="LocateButton"></div> 189. <!-- 切换底图--> 190. <div id="BasemapToggle"></div> 191. <!-- 搜索栏--> 192. <div id="search"></div> 193. <!-- 坐标--> 194. <span id="info" style="position:absolute; left:750px; bottom:5px; color:#000; z-index:50;"></span> 195. 196. <button id="selectFieldsButton">选框查询</button> 197. <button id="clearSelectionButton" data-dojo-type="dijit/form/Button">清除选择</button><br> 198. <div id="toc" style="position: absolute; left: 10px; bottom: 20px; border: 1px solid #9c9c9c; background: #fff; width: 100px; height: auto; z-index: 99;padding: 10px;"></div> 199. </div> 200.</body> </html>
4、地图切换
this.map.getLayer("yhmap").setVisibility(!this.map._layers.yhmap.visible); //方式一,根据名称使用GetLayer方法
this.map._layers.yhmapanno.setVisibility(!this.map._layers.yhmapanno.visible); //方式二,直接根据图层Id名称读取
this.map._layers.yhimage.setVisibility(!this.map._layers.yhimage.visible);
this.map._layers.yhimageanno.setVisibility(!this.map._layers.yhimageanno.visible);
//注意,使用setVisibility()方法,如果 直接使用visible属性无效果
5、Geocoder snippets
dojo.require("esri.dijit.Geocoder"); //geocoder widget (the searchTextBox) var geocoderParas = [{ //self-defined geocoderurl: "http://localhost:6080/arcgis/rest/services/subwayWGS84/stationLocator/GeocodeServer",name: "stationLocator"// name of Locator in geocodeService }];geocoder = new esri.dijit.Geocoder({// construct geocoder widget map: map,autoComplete: true,arcgisGeocoder: false, //don't use argis global geocoder geocoders: geocoderParas,outFields: ["*"]}, "search");geocoder.startup();dojo.connect(geocoder, "onSelect", function (result) {//when one result is selected//result.feature is type graphicmap.graphics.clear(); //clear previous graphicsmap.infoWindow.hide();
十、render(arcgis for js 中的渲染)
渲染器分类:
1、分级渲染(ClassBreaksRenderer)
根据某个字段值按范围划分颜色
var symbol = new SimpleFillSymbol();symbol.setColor(new Color([150, 150, 150, 0.5]));// Add five breaks to the renderer.// If you have ESRI's ArcMap available, this can be a good way to determine break values.// You can also copy the RGB values from the color schemes ArcMap applies, or use colors// from a site like www.colorbrewer.org// // alternatively, ArcGIS Server's generate renderer task could be usedvar renderer = new ClassBreaksRenderer(symbol, "POP07_SQMI");renderer.addBreak(0, 25, new SimpleFillSymbol().setColor(new Color([56, 168, 0, 0.5])));renderer.addBreak(25, 75, new SimpleFillSymbol().setColor(new Color([139, 209, 0, 0.5])));renderer.addBreak(75, 175, new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));renderer.addBreak(175, 400, new SimpleFillSymbol().setColor(new Color([255, 128, 0, 0.5])));renderer.addBreak(400, Infinity, new SimpleFillSymbol().setColor(new Color([255, 0, 0, 0.5])));var infoTemplate = new InfoTemplate("${NAME}", "${*}");var featureLayer = new FeatureLayer("https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/3", {mode: FeatureLayer.MODE_SNAPSHOT,outFields: ["*"],infoTemplate: infoTemplate});featureLayer.setDefinitionExpression("STATE_NAME = 'Kansas'");featureLayer.setRenderer(renderer);map.addLayer(featureLayer);
2、融合渲染(BlendRenderer)
根据图层不同字段的值,所占的比重,实现不同颜色的融合渲染,官方给的例子是,根据地区房屋的使用情况,出租,空置, 自住,所占的比例实现Red,Green,Blue的融合渲染效果
19栋房子里,有17栋都是自住的,因此,渲染结果是深蓝色
下面的选中区域里,24个自住,20个出租,两个值基本相当,所以渲染的效果是Blue和Red融合的紫色
//Set the blendRenderer's parametersvar blendRendererParams = {//blendMode:"overlay" //By default, it uses "source-over", uncomment to display different mode//See: http://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperationsymbol: new SimpleFillSymbol().setOutline(new SimpleLineSymbol().setWidth(0)),fields: [{field: "OWNER_CY",color: new Color([0, 0, 255])}, {field: "RENTER_CY",color: new Color([255, 0, 0])}, {field: "VACANT_CY",color: new Color([0, 255, 0])}],opacityStops: [{value: .1,opacity: 0},{value: 1,opacity: .7}],normalizationField: "TOTHU_CY"};
3、聚类分析(clustering)
var serviceUrl = "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/nyc_parks_gardens_hist_sites/FeatureServer/0";var layer = new FeatureLayer(serviceUrl, {outFields: [ "facname", "proptype", "factype", "address" ],featureReduction: {type: "cluster"},infoTemplate: new PopupTemplate({title: "{facname}",description: "{proptype} {factype} on {address}."})});map.addLayer(layer);
4、简单渲染(SimpleRenderer)
var map = new Map("map", {extent: new Extent({"xmin":-2460944,"ymin":-1389910,"xmax":2297115,"ymax":1643787,"spatialReference":{"wkid":102003}})});var layer = new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/USA_County_Crops_2007/FeatureServer/0", {outFields: ["*"],infoTemplate: new InfoTemplate("${COUNTY}, ${STATE}", "<div style='font: 18px Segoe UI'>The percentage of the area of the county that represents farmland is <b>${M086_07:NumberFormat(places:0)}%</b>.</div>")});var legend = new Legend({map: map,layerInfos: [{ title: "Percentage of county area used for farming", layer: layer }]}, "legend");layer.on("load", function(){var renderer = new SimpleRenderer(new SimpleFillSymbol().setOutline(new SimpleLineSymbol().setWidth(0.1).setColor(new Color([128,128,128]))));renderer.setColorInfo({field: "M086_07",minDataValue: 0,maxDataValue: 100,colors: [new Color([255, 255, 255]),new Color([127, 127, 0])]});layer.setRenderer(renderer);map.addLayer(layer);legend.startup();
十一、arcgis+postgresql将osm数据发布成要素服务
由于arcgis 发布要素服务需要数据库,所以选择开源的支持空间数据较好的postgresql数据库。
一:postgresql的下载与安装:
1.1、下载官方地址:https://www.postgresql.org/download/(一定要下载含有postgis的版本)
1.2:安装
参考此教程:https://jingyan.baidu.com/article/e75057f2c6f6eaebc91a89ed.html
1.3:建立数据库
1.3.1、打开navicat
1.3.2、连接postgresql数据库
1.3.3、建立数据库
点击确定就建立成功
二、数据导入数据库
2.1、打开arcmap,连接postgresql数据库
2.2、将空间数据导入postgresql中
2.2.1、打开要发布的shp数据
2.2.2、将arccatalog和postgresql数据库连接
2.2.3、连接信息
点击ok,出现如下情况,表示连接成功
2.2.4、要素添加到postgresql数据库中
2.2.5、点击feature class(single)
2.2.6、点击确定,等待数据导入,如果导入成功,则出现下图的所示
2.2.7、依次将其他数据按照这种方式都加入到postgresql数据库中
三:要素服务的发布
3.1、关闭直接打开的shp数据,留下数库中的数据
3.2、开始发布要素服务。file-》share as ->service
点击下一步
点击一下一布
点击下一步
选择发布服务类型
分析是否存在错误
有错误,下边解决错误,
第一个错误:SEVERITY STATUSCODEDESCRIPTIONNAMETYPEDATA FRAME
High Unresolved00090Feature service requires a registered databaseLayersData FrameLayers
这个错误是没有和数据库关联起来,需要数据库
双击第一个错误,出现如图
点击加号添加数据库
点击ok 点击确定
解决第二个错误
SEVERITY STATUSCODEDESCRIPTIONNAMETYPEDATA FRAME
High Unresolved00002Data frame does not have a spatial referenceLayersData FrameLayers
没有坐标,需要点击坐标
双击错误,
错误全部消失,点击发布,
发布成功
3.3、浏览器查看发布的服务
浏览器输入https://localhost:6443/arcgis/manager/service
输入账号和密码
十二、arcgis for js 轨迹回放
原理:
创建两个graphic图层lineLayer、carLayer,在两点之间进行插值,把小车图片创建成graphic,然后显示隐藏。简单来说就是:根据设置的时间间隔,在两个点之间创建n个点,然后代表小车的graphic在这些点的位置上依次添加
小车角度通过setAngle()进行控制,拐点处的停顿通过setInterval()控制
代码:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>轨迹回放</title><link rel="stylesheet" href="http://localhost/library/3.20/jsapi/js/dojo/dijit/themes/tundra/tundra.css" /><link rel="stylesheet" type="text/css" href="http://localhost/library/3.20/jsapi/js/esri/css/esri.css" /><style>html, body, #mapDiv{height: 550px;width: 100%;margin: 0;padding: 0;}</style><script type="text/javascript" src="http://localhost/library/3.20/jsapi/init.js"></script><script type="text/javascript">dojo.require("esri.map");dojo.require("esri.SpatialReference");dojo.require("esri.tasks.GeometryService");dojo.require("esri.dijit.Scalebar");dojo.require("dojo.parser");dojo.require("esri.Color");var map;var points = [];var lineSymbol;var pointSymbol;var carSymbol;var carGraphic;var timer;function init() {map = new esri.Map("mapDiv");var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://localhost:6080/arcgis/rest/services/BaseMap/MapServer");map.addLayer(layer);lineSymbol = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color("red"), 3);pointSymbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1), new dojo.Color([255, 0, 0, 1]));carSymbol = new esri.symbol.PictureMarkerSymbol("car.png", 24, 24)var lineLayer = new esri.layers.GraphicsLayer({ id: "lineLayer" });var carLayer = new esri.layers.GraphicsLayer({ id: "carLayer" });map.addLayer(lineLayer);map.addLayer(carLayer);dojo.connect(map, "onClick", Click);}/*** 点击事件,添加点*/function Click(e) {points.push(e.mapPoint);map.graphics.add(new esri.Graphic(e.mapPoint, pointSymbol));}/*** 根据回放速度在两点之间进行插值*/function interpolation(pointA, pointB, speed) {var tmp = [];if (speed == undefined) {speed = 1;}speed = speed - 0.5; //不能大于播放速度var count = Math.abs(speed) * 25;var disX = (pointB.x - pointA.x) / count;var disY = (pointB.y - pointA.y) / count;var i = 0;while (i <= count) {var x = pointA.x + i * disX;var y = pointA.y + i * disY;tmp.push(new esri.geometry.Point(x, y));i++;}tmp.push(pointB);//防止插值出来的最后一个点到不了B点return tmp;}var j = 0;/*** 播放*/function play(tmpPoints) {var ref = setTimeout(function () {if (j < tmpPoints.length - 1) {var line = new esri.geometry.Polyline({ "paths": [[[tmpPoints[j].x, tmpPoints[j].y], [tmpPoints[j + 1].x, tmpPoints[j + 1].y]]] });var lineGriphic = new esri.Graphic(line, lineSymbol);map.getLayer("lineLayer").add(lineGriphic);map.getLayer("carLayer").clear();carGriphic = new esri.Graphic(tmpPoints[j + 1], carSymbol);map.getLayer("carLayer").add(carGriphic);j++;play(tmpPoints);}else { j = 0; }}, 40); //小车40毫秒换个位置闪现一次,25*40*speed就是两点之间的时间间隔 }//计算两个点的角度值function Angle(startx, starty, endx, endy) {console.log("+++++++++");var tan = 0if (endx == startx) {tan = Math.atan(0) * 180 / Math.PI} else {tan = Math.atan(Math.abs((endy - starty) / (endx - startx))) * 180 / Math.PIconsole.log(tan);}if (endx >= startx && endy >= starty)//第一象限 {return -tan;} else if (endx > startx && endy < starty)//第四象限 {return tan;} else if (endx < startx && endy > starty)//第二象限 {return tan - 180;} else {return 180 - tan; //第三象限 }}//开始执行function Start() {if (timer != null) {clearInterval(timer);map.getLayer("lineLayer").clear();}var replayIndex=0;timer = setInterval(function () {if (replayIndex == points.length - 1) {clearInterval(timer);}else {if (replayIndex == 0) {map.getLayer("lineLayer").clear();}var p1 = points[replayIndex];var p2 = points[++replayIndex];var tempPoints = interpolation(p1, p2, document.getElementById("txtSpeed").value);var angle = Math.ceil(Angle(p1.x, p1.y, p2.x, p2.y))console.log(angle);carSymbol.setAngle(angle) //设置小车角度 play(tempPoints);}}, document.getElementById("txtSpeed").value * 1000);}</script> </head> <body class="tundra" οnlοad="init()"><div id="mapDiv"></div><div>先添加点</div>回放速度<input id="txtSpeed" type="text" value="4" style="width:30px" /><input type="button" value="回放" οnclick="Start()" /> </body> </html>