07 ArcGIS JS API 4.14 realize map Load picture

Description of Requirement

The picture is superimposed is now a widespread demand for many items on the ArcGIS maps, access to online information found by the demand that currently there are only four ways to achieve because ArcGIS JS API official website does not provide the corresponding image layers to class let's instantiate picture layer, but the JS API official website explained the latter will increase this type of API, just do not know what time it is. Since at present no such API layer, then we will look for other ways to own it, just mentioned realize the picture is superimposed onto a map There are four, are as follows:

  • ArcGIS know almost be achieved through the use was mentioned Graphic, in fact, the picture as a Symbol;
  • Be achieved by similar ArcGIS JS API 3.X MapImage the module;
  • Be achieved by extending MapImageLayer;
  • JS API is implemented by the class online BaseDynamicLayer officer

Next we will look at various ways in the end can not be done, or what the effect can be made. Before began to introduce specific steps, we'll give you disclose is that this article is the fourth method to achieve, namely to achieve by BaseDynamicLayer this class, the final results are as follows:

Analysis of the various programs and specific steps to achieve

First, the realization of the form Graphic

This approach is a first implementation I found online, but also the most simple one, its principle is actually a picture as a Symbol symbol, as a symbol of class ArcGIS JS API has supported picture symbols, so the picture as one symbol, and then added to the configuration instantiates Graphic layer, the final add the Graphic layer is instantiated on the map, the specific code as follows:

      require(["esri/Map", 
            "esri/views/MapView",
            "esri/Graphic"
        ], function(Map, MapView, Graphic) {
        var map = new Map({
          basemap: "satellite"
        });
        var view = new MapView({
          container: "viewDiv", 
          map: map, 
          zoom: 4, 
          center: [15, 65] 
        });

        var polyline = {
            type: "polyline", 
            paths: [
                [91.0761406150, 29.5803130630]
            ]
        };

        var polylineAtt = {
            Name: "Keystone Pipeline",
            Owner: "TransCanada"
        };

        var pictureSymbol = {
            type: "picture-marker",  
            url: "./test.jpg",
            width: "240px",
            height: "240px",
        };
        var polylineGraphic = new Graphic({
            geometry: polyline,
            symbol: pictureSymbol,
            attributes: polylineAtt
        });

        view.graphics.add(polylineGraphic);

      });

The final effect achieved by the above code is as follows:

As can be seen from the above results, this is not the result we want, though we add to the picture on the map by this method, but as the map zoom, image and does not scale, it still maintains its original size. While it is possible to dynamically adjust the size of the picture by listening to zoom view events view layer, but this approach feel a little stupid, and late effects may not be how. So this method is eliminated, being to consider.

Second, is achieved by a similar ArcGIS JS API 3.X module in MapImage

In ArcGIS JS API 3.X and ArcGIS JS API 4.X MapImage in both modules, the version 3.X can be instantiated by a class of this block image information, and then the image information of the class by addImage method MapImageLayer Add to MapImageLayer layer, and finally add MapImageLayer layers to the map, this completes the picture and map overlay, the code is as follows:

      require(["esri/Map", 
            "esri/views/MapView",
            "esri/layers/MapImageLayer",
            "esri/layers/support/MapImage"
        ], function(Map, MapView, MapImageLayer, MapImage) {
        var map = new Map({
          basemap: "satellite"
        });
        var view = new MapView({
          container: "viewDiv", 
          map: map, 
          zoom: 4, 
          center: [15, 65] 
        });

        //实例化图层
        var mapimageLayer = new MapImageLayer({
            id: 'imageLayer_xuqw'
        });
        map.add(mapimageLayer);

        var image = new MapImage({  
            'extent': 
                { 
                    'xmin': -8864908, 
                    'ymin': 3885443, 
                    'xmax': -8762763, 
                    'ymax': 3976997, 
                    'spatialReference': 
                        { 
                            'wkid': 3857 
                        }
                },  
            'href': './test.jpg'  
        });

        mapimageLayer.addImage(image); 
      });

The code above seems to be so perfect, we only need to pass the picture in MapImage class instantiation time information and url address range can be, but happens to be a coincidence, ArcGIS JS API 4.X version of MapImageLayer not addImage ( ) this method, so we can only give up this approach. But did not give the students may have to ask, since there is no addImage () This method, why the official website will also write it MapImage this category, since not take, then simply do not announce not on line yet, the problem is actually in GeoNet there is also the official responded, saying it was written because mistakes ......

Third, be achieved by extending MapImageLayer

In fact, this idea just fine, mainly to see the big brother Xu Lei article received the inspiration, the article at the following address:

https://www.jianshu.com/p/cc744f1ad6bb?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weixin-timeline&from=timeline

Interested students can go to learn under this article, the article is finally put out github address and source code, written in great detail, I was last extended in accordance with the layer type of test is successful, the effect is as follows:

The screenshots above, the picture is superimposed on the map will follow the map's zoom and resizing the corresponding drawing, the effect is pretty good, but given the current project only needs to do such a small expansion layer operation, range of motion is a bit too big and put in some effort and energy costs, the feeling is not worth, in fact, it is their own lazy, ha ha ha, so I still want to look for other ways, this is not to find a fourth method.

Fourth, be achieved by BaseDynamicLayer class JS API official website

In the unremitting efforts to find, finally found a home of GIS articles and BaseDynamicLayer this class, which allows us to customize the extension layer, so we can pass this class simple extension at the picture superimposed layers to achieve Map superimposed on the image. In fact, after the scope of the principle is used by canvas rendering technology, access to images convert its range of coordinate information screen coordinates, and then instantiate canvas handle to draw pictures.

Superimposing the image of the expanded custom class code as follows:

			//自定义叠加图片图层
			var CustomImageOverlayLayer = BaseDynamicLayer.createSubclass({
				properties: {
					picUrl: null,
					extent: null,
					image: null,
					canvas: null,
				},
 
				// Override the getImageUrl() method to generate URL
				// to an image for a given extent, width, and height.
				getImageUrl: function (extent, width, height) {
					//新Image对象,可以理解为DOM 
					if (!this.image) {
						this.image = new Image();
					}
					this.image.src = this.picUrl;
 
					// 创建canvas DOM元素,并设置其宽高和图片一样   
					if (!this.canvas) {
						this.canvas = canvas = document.createElement("canvas");
					}
					this.canvas.width = 2000;
					this.canvas.height = 2000;
 
					//左上角地理坐标转换屏幕坐标,为了获取canvas绘制图片的起点
					var mapPoint = {
						x: this.extent.xmin,
						y: this.extent.ymax,
						spatialReference: {
							wkid: 4326
						}
					};
					var screenPoint = view.toScreen(mapPoint);
					//根据extent范围计算canvas绘制图片的宽度以及高度
					//左下角
					var leftbottom = {
						x: this.extent.xmin,
						y: this.extent.ymin,
						spatialReference: {
							wkid: 4326
						}
					};
					var screen_leftbottom = view.toScreen(leftbottom);
					//右上角
					var righttop = {
						x: this.extent.xmax,
						y: this.extent.ymax,
						spatialReference: {
							wkid: 4326
						}
					};
					var screen_righttop = view.toScreen(righttop);

					this.canvas.getContext("2d").drawImage(this.image, screenPoint.x, screenPoint.y, Math.abs(screen_righttop.x - screen_leftbottom.x), Math.abs(screen_righttop.y - screen_leftbottom.y));
					return this.canvas.toDataURL("image/png");
 
				}
			});

Instantiate the class code as follows:

				var ImageOverlayLayer = new CustomImageOverlayLayer({
					picUrl: "1.jpg",
					extent: { 
                        xmin: 91.0761406150, 
                        ymin: 29.5803130630, 
                        xmax: 92.0761406150, 
                        ymax: 30.5803130630 
                    }
				});
				map.add(ImageOverlayLayer);

The resulting image overlay effects are as follows:

The effect obtained by this method is what we need, simple operation, and eventually superimposed images on a map with the map will zoom to resize, so this finally be achieved in this way.

 

Attachment:

The fourth method of all the source code:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
	<title>地图叠加图片</title>
	<link rel="stylesheet" href="http://localhost/4.14/esri/themes/light/main.css" />
	<style>
		html,
		body,
		#viewDiv {
			padding: 0;
			margin: 0;
			height: 100%;
			width: 100%;
		}
	</style>
	<script src="http://localhost/4.14/init.js"></script>
</head>
 
<body>
	<div id="viewDiv"></div>
	<script>
		require([
			"esri/Map",
			"esri/views/MapView",
			"esri/layers/BaseDynamicLayer"
		], function (Map, MapView, BaseDynamicLayer) {
 
			//自定义叠加图片图层
			var CustomImageOverlayLayer = BaseDynamicLayer.createSubclass({
				properties: {
					picUrl: null,
					extent: null,
					image: null,
					canvas: null,
				},
 
				// Override the getImageUrl() method to generate URL
				// to an image for a given extent, width, and height.
				getImageUrl: function (extent, width, height) {
					//新Image对象,可以理解为DOM 
					if (!this.image) {
						this.image = new Image();
					}
					this.image.src = this.picUrl;
 
					// 创建canvas DOM元素,并设置其宽高和图片一样   
					if (!this.canvas) {
						this.canvas = canvas = document.createElement("canvas");
					}
					this.canvas.width = 2000;
					this.canvas.height = 2000;
 
					//左上角地理坐标转换屏幕坐标,为了获取canvas绘制图片的起点
					var mapPoint = {
						x: this.extent.xmin,
						y: this.extent.ymax,
						spatialReference: {
							wkid: 4326
						}
					};
					var screenPoint = view.toScreen(mapPoint);
					//根据extent范围计算canvas绘制图片的宽度以及高度
					//左下角
					var leftbottom = {
						x: this.extent.xmin,
						y: this.extent.ymin,
						spatialReference: {
							wkid: 4326
						}
					};
					var screen_leftbottom = view.toScreen(leftbottom);
					//右上角
					var righttop = {
						x: this.extent.xmax,
						y: this.extent.ymax,
						spatialReference: {
							wkid: 4326
						}
					};
					var screen_righttop = view.toScreen(righttop);

					this.canvas.getContext("2d").drawImage(this.image, screenPoint.x, screenPoint.y, Math.abs(screen_righttop.x - screen_leftbottom.x), Math.abs(screen_righttop.y - screen_leftbottom.y));
					return this.canvas.toDataURL("image/png");
 
				}
			});
 
			var map = new Map({
				basemap: 'osm',
			});
 
			var view = new MapView({
				container: "viewDiv",
				map: map,
				center: [107.246152,34.414465],
				zoom: 7
			});
 
			view.when(function () {
				var ImageOverlayLayer = new CustomImageOverlayLayer({
					picUrl: "1.jpg",
					extent: { 
                        xmin: 91.0761406150, 
                        ymin: 29.5803130630, 
                        xmax: 92.0761406150, 
                        ymax: 30.5803130630 
                    }
				});
				map.add(ImageOverlayLayer);

				//地图移动刷新,防止地图初始化时候,图片叠加图层加载刷新不过来
				setTimeout(function () {
					var center = view.center.clone();
					center.x -= 0.001;//底图是经纬度
					view.center = center;
					view.goTo(view.center,
						{
							speedFactor: 0.1,
							easing: "linear" //linear, in-cubic, out-cubic, in-out-cubic, in-expo, out-expo, in-out-expo
						});
				}, 500);
			}, function (error) {
				console.log("图片叠加失败: ", error);
			});
 
 
		});
	</script>
</body>
 
</html>

 

 

 

 

 

 

Published 143 original articles · won praise 225 · Views 300,000 +

Guess you like

Origin blog.csdn.net/qq_35117024/article/details/105247503