<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>ArcGIS 4x - Add Image to Map</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.19/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.19/"></script>
</head>
<body>
<div id="viewDiv"></div>
<div id="instructions" style="font-family:Arial;">This pen is a sandbox for testing methods of adding images to the map view in 4x, without the use of a map service.
<ul>
<li>
Option 1: <a style="font-weight:bold;">WebTileLayer</a>
</li>
<li>
Option 2: <a style="font-weight:bold;">PictureFillSymbol</a>
</li>
<li>
Option 3: <a style="font-weight:bold;">PictureMarkerSymbol</a>
</li>
<li>
Option 4: <a style="font-weight:bold;">Sublayer</a>
</li>
</ul>
</div>
</body>
</html>
require(["esri/layers/WebTileLayer", "esri/layers/MapImageLayer", "esri/Map", "esri/layers/WMSLayer", "esri/layers/GraphicsLayer", "esri/symbols/PictureFillSymbol", "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol", "esri/Color", "esri/views/MapView", "esri/Graphic", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/geometry/Point", "esri/layers/TileLayer", "esri/layers/WebTileLayer", "esri/core/watchUtils", "esri/request",
"esri/widgets/CoordinateConversion"], function(
WebTileLayer,
MapImageLayer,
Map,
WMSLayer,
GraphicsLayer,
PictureFillSymbol,
SimpleLineSymbol,
SimpleFillSymbol,
Color,
MapView,
Graphic,
Extent,
Polygon,
Point,
TileLayer,
WebTileLayer,
watchUtils,
esriRequest,
CoordinateConversion
) {
const imageUrl = "https://prd-wret.s3.us-west-2.amazonaws.com/assets/palladium/production/s3fs-public/styles/atom_page_medium/public/thumbnails/image/md_state_house.jpg";
//OPTION 1
const layerTile = new WebTileLayer({
urlTemplate: imageUrl
});
//OPTION 2
const rings = [[-76.492400, 38.9800], [-76.4896, 38.9800], [-76.4896, 38.9774], [-76.492400, 38.9774],[-76.492400, 38.9810]];
const polygon = new Polygon({
rings: rings,
spatialReference: { wkid: 4326 }
});
const symbolFill = {
type: "picture-fill",
url: imageUrl,
width: 1200,
height: 1500
};
const graphicPolygon = new Graphic({
geometry: polygon,
symbol: symbolFill
});
const layerPolygon = new GraphicsLayer({
graphics: [graphicPolygon]
});
//OPTION 3
const point = new Point ({
x: -76.490695,
y: 38.9788
});
const markerExtent = {
xmin: -76.492706,
xmax: -76.488920,
ymin: 38.978750,
ymax: 38.980800
}
const symbolMarker = {
type: "picture-marker",
url: imageUrl,
width: 200,
height: 200
};
const graphicPoint = new Graphic({
geometry: point,
symbol: symbolMarker
});
const layerPoint = new GraphicsLayer({
graphics: [graphicPoint]
});
//OPTION 4
const CustomTileLayer = WebTileLayer.createSubclass({
properties: {
urlTemplate: null,
},
getTileUrl: function(level, row, col) {
return imageUrl;
// return urlTemplate
// .replace("{z}", level)
// .replace("{x}", col)
// .replace("{y}", row);
},
// Override this method to process the data returned from the server.
fetchTile: function(level, row, col, options) {
// call getTileUrl() method to construct the URL to tiles
// for a given level, row and col provided by the LayerView
const url = this.getTileUrl(level, row, col);
// request for tiles based on the generated url
// the signal option ensures that obsolete requests are aborted
return esriRequest(url, {
responseType: "image",
signal: options && options.signal
}).then(
function(response) {
const image = response.data;
const width = this.tileInfo.size[0];
const height = this.tileInfo.size[0];
// create a canvas with 2D rendering context
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
if (this.tint) {
context.fillStyle = this.tint.toCss();
context.fillRect(0, 0, width, height);
context.globalCompositeOperation = "difference";
}
context.drawImage(image, 0, 0, width, height);
return canvas;
}.bind(this)
);
}
});
const layerSub = new CustomTileLayer({
urlTemplate: imageUrl });
//--------------------------------
const option1 = layerTile;
const option2 = layerPolygon;
const option3 = layerPoint;
const option4 = layerSub;
//Change targetLayer to try different options
const targetLayer = option3;
//---------------------------------
const map = new Map({
basemap: "dark-gray",
layers: [targetLayer]
});
const center = [-76.4907, 38.9789];
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 16,
center: center
});
if (targetLayer === option1) {
watchUtils.on(targetLayer, "destroy", "call", () => {console.warn('targetLayer refresh!');});
targetLayer.destroyer = function fakeDestroyer() {
// return targetLayer.url;
}
targetLayer.destroy = function fakeDestroy() {
//test destroy override
}
console.warn(targetLayer.destroyer);
console.warn(targetLayer.destroy);
}
if (targetLayer === option3) {
view.watch("animation", (response) => {
if(response && response.state === "running"){
targetLayer.visible = false;
}
});
view.watch("stationary", (newValue, oldValue) => {
if (newValue == true) {
adjustMarker();
}
});
}
function adjustMarker() {
const topRightScreenPt = view.toScreen({
x: markerExtent.xmax,
y: markerExtent.ymax,
spatialReference:{
wkid: 4326
}
});
const bottomLeftScreenPt = view.toScreen({
x: markerExtent.xmin,
y: markerExtent.ymin,
spatialReference:{
wkid: 4326
}
});
const newWidth = Math.abs(topRightScreenPt.x - bottomLeftScreenPt.x);
const newHeight = Math.abs(bottomLeftScreenPt.y - topRightScreenPt.y);
targetLayer.graphics.items[0].symbol = {
type: "picture-marker",
url: imageUrl,
width: newWidth > 0 ? newWidth + "pt" : 1,
height: newHeight > 0 ? newHeight + "pt" : 1
};
targetLayer.visible = true;
}
var ccWidget = new CoordinateConversion({
view: view
});
view.ui.add(ccWidget, "bottom-left");
});