I am working trying to write a custom widget for Experience Builder using with the Javascript 4.x API. The user should be able to draw a rectangle, then the map (working in 2d here, 3d comes later) should update to the extent of the rectangle drawn.
I can get the rectangle from the user and draw it on the map as a visual display of the area that will be the new extent, I just can't get the view to actually move to that extent. I thought the goTo method of the MapView would be my answer, but I can't quite seem to get it right. Any advice?
/** @jsx jsx */
import {React, AllWidgetProps, jsx } from 'jimu-core';
import {JimuMapView, JimuMapViewComponent } from 'jimu-arcgis';
import { Point, Polygon } from 'esri/geometry';
import * as Graphic from "esri/Graphic";
import * as GraphicsLayer from "esri/layers/GraphicsLayer";
import {getStyle} from './lib/style';
import { jimuMapViewAdded } from 'jimu-core/lib/app-actions';
export default class Widget extends React.PureComponent<AllWidgetProps<any>, any> {
/** code for creating graphics layer, activating button for user
* to be able to draw the rectangle, etc.
*/
setNewExtent(evt) {
//get the point for the last corner on the rectangle
let crossPoint: Point = this.state.jimuMapView.view.toMap({
x: evt.x,
y: evt.y
});
//draw the rectangle
let extentRectangle = new Polygon({
rings: [
[ this.state.startingPoint.x, this.state.startingPoint.y ], // starting point
[ this.state.startingPoint.x, crossPoint.y ], // corner 1
[ crossPoint.x, crossPoint.y ], // diagonal to starting point (current cursor location)
[ crossPoint.x, this.state.startingPoint.y ], //corner 2
[ this.state.startingPoint.x, this.state.startingPoint.y ] // starting point (close rectangle)
],
spatialReference: { wkid: this.state.jimuMapView.view.map.spatialReference }
});
//turn the geometry into a graphic
let extentGraphic = new Graphic({
geometry: extentRectangle,
symbol: this.state.extentSymbol // simple fill symbol
});
//add the graphic to the map
this.state.graphicsLayer.add(extentGraphic);
//set the mapview to the extent of the user's rectangle
this.state.jimuMapView.view.goTo(extentRectangle);
//it works the same with goTo(extentGraphic)
/**
* Later code for deactivating button, removing
* stylings for edit mode, etc.
*/
}
}
There are no errors in the console. Any advice on what I'm missing?
Solved! Go to Solution.
I'm not sure what wasn't working with the geometry I was generating before, but the Sketch widget got me to the answer I was looking for.
If anyone else is looking for a solution, I made a codepen with the core functionality described above. You can view it here. (This is basically a rubber-band zoom widget for any user who can't zoom to a map extent by holding ctrl while clicking and drawing a rectangle due to accessibility concerns).
I'm not using Jimu, but since jimuMapView.view equates to an ArcGIS Javascript View, I would just use 'extent', as in this.state.jimuMapView.view.extent = extentRectangle.
extentRectangle is a polygon.
I can do
this.state.jimMapView.view.extent = extentRectangle.extent, but I get an error in the console saying:
[esri.views.MapView] #extent invalid extent size
I can output the extentRectangle's extent just before that line runs (using a debugger to be sure), and it has a valid center, xmin, xmax, ymin, ymax, and spatialReference.
Doesn't make sense why it won't work. The API reference for MapView says the 'extent' is just an Extent object with xmax, xmin, ymax, ymin, center, and spatialReference which it has. Maybe there needs to be a conversion to a jimuMapView.extent, or maybe import the ArcGIS API Extent object and set a new one equal to extentRectangle.extent, then use that. Seems unnecessary but it's all I can think of.
But what types of values are you getting and how do they compare to the current MapView extent and SR? Setting a MapView extent to your specific extent is something you should be able to test via a simple codepen that doesn't use ExB or widgets. Also, you should check out the SketchViewModel as it will provides a way for the user to interactively create an extent that you could then zoom to.
I'm not sure what wasn't working with the geometry I was generating before, but the Sketch widget got me to the answer I was looking for.
If anyone else is looking for a solution, I made a codepen with the core functionality described above. You can view it here. (This is basically a rubber-band zoom widget for any user who can't zoom to a map extent by holding ctrl while clicking and drawing a rectangle due to accessibility concerns).