为什么 SceneView 渲染不正确
Why is the SceneView not rendering correct
我正在加快 ArcGIS JS Api 版本 4.x 的速度,并认为这是一个很好的 Typescript 和 Widget 架构练习,可以实现一个显示 SceneView
的小部件在当前 MapView
.
之上
/// <amd-dependency path="esri/core/tsSupport/declareExtendsHelper" name="__extends" />
/// <amd-dependency path="esri/core/tsSupport/decorateHelper" name="__decorate" />
import EsriMap from 'esri/Map';
import SceneView = require("esri/views/SceneView");
import { aliasOf, declared, property, subclass } from "esri/core/accessorSupport/decorators";
// building Widgets
import Widget = require("esri/widgets/Widget");
import { accessibleHandler, renderable, cssTransition, tsx } from "esri/widgets/support/widget";
// CSS class lookup object
const CSS = {
base: "app-sceneView",
iconClass: "esri-icon-layer-list"
};
@subclass("Widgets.SceneViewWidget")
export default class SceneViewWidget extends declared(Widget) {
constructor(params?: any) {
super();
}
//icon class for the expand widget(!)
@property()
iconClass = CSS.iconClass;
map: EsriMap = null;
_bindView() {
const view = new SceneView({
map: this.map,
container: "sceneView-container"
});
}
render() {
return <div id="sceneView-container" class={CSS.base} afterCreate={this._bindView}></div>
}
}
小部件的容器在所需位置呈现良好,缩放按钮等控件也在那里,但地图未呈现,当这样调用时:
const map = new EsriMap({
basemap: "streets",
ground: "hybrid"
});
const mapView = new MapView({
map: map,
container: "mapView",
center: [-118.244, 34.052],
zoom: 12,
ui: {
components: ["zoom", "compass"]
}
});
const sceneView = new SceneViewWidget({
map: map
});
mapView.ui.add(sceneView, "top-right");
如你所见。 div 的边界在那里,控件被呈现,属性也在那里。仅缺少 SceneView 本身。这是为什么?
SceneView
未在上述 TypeScript 代码中呈现的原因是 _bindView()
中的 this.map
为空,因为 this
是函数而非对象范围。
_bindView() {
new SceneView({
map: this.map,
container: "sceneView-container"
});
}
这可以通过在 render()
中传递正确范围的 _bindView()
函数来解决:
render() {
return <div afterCreate={this._bindView.bind(this)} id="sceneView-container" class={CSS.base}></div>;
}
或
render() {
return <div afterCreate={() => this._bindView()} id="sceneView-container" class={CSS.base}></div>;
}
请参阅以下 CodePen 的工作演示(普通 JavaScript):
https://codepen.io/arnofiva/pen/1a801eca6a01ca9bf7625f89f906b6e7
此外,我还建议更改上面代码中的以下内容:
- 将 SceneView 容器
sceneView-container
包装在一个额外的 <div>
中以避免 Widget 和 SceneView 共享相同的元素:
<div><div id="sceneView-container" class={CSS.base} afterCreate={this._bindView.bind(this)}></div></div>
- 为
Map.ground
传递一个有效值,例如
const map = new EsriMap({
basemap: "streets",
ground: "world-elevation"
});
我正在加快 ArcGIS JS Api 版本 4.x 的速度,并认为这是一个很好的 Typescript 和 Widget 架构练习,可以实现一个显示 SceneView
的小部件在当前 MapView
.
/// <amd-dependency path="esri/core/tsSupport/declareExtendsHelper" name="__extends" />
/// <amd-dependency path="esri/core/tsSupport/decorateHelper" name="__decorate" />
import EsriMap from 'esri/Map';
import SceneView = require("esri/views/SceneView");
import { aliasOf, declared, property, subclass } from "esri/core/accessorSupport/decorators";
// building Widgets
import Widget = require("esri/widgets/Widget");
import { accessibleHandler, renderable, cssTransition, tsx } from "esri/widgets/support/widget";
// CSS class lookup object
const CSS = {
base: "app-sceneView",
iconClass: "esri-icon-layer-list"
};
@subclass("Widgets.SceneViewWidget")
export default class SceneViewWidget extends declared(Widget) {
constructor(params?: any) {
super();
}
//icon class for the expand widget(!)
@property()
iconClass = CSS.iconClass;
map: EsriMap = null;
_bindView() {
const view = new SceneView({
map: this.map,
container: "sceneView-container"
});
}
render() {
return <div id="sceneView-container" class={CSS.base} afterCreate={this._bindView}></div>
}
}
小部件的容器在所需位置呈现良好,缩放按钮等控件也在那里,但地图未呈现,当这样调用时:
const map = new EsriMap({
basemap: "streets",
ground: "hybrid"
});
const mapView = new MapView({
map: map,
container: "mapView",
center: [-118.244, 34.052],
zoom: 12,
ui: {
components: ["zoom", "compass"]
}
});
const sceneView = new SceneViewWidget({
map: map
});
mapView.ui.add(sceneView, "top-right");
如你所见。 div 的边界在那里,控件被呈现,属性也在那里。仅缺少 SceneView 本身。这是为什么?
SceneView
未在上述 TypeScript 代码中呈现的原因是 _bindView()
中的 this.map
为空,因为 this
是函数而非对象范围。
_bindView() {
new SceneView({
map: this.map,
container: "sceneView-container"
});
}
这可以通过在 render()
中传递正确范围的 _bindView()
函数来解决:
render() {
return <div afterCreate={this._bindView.bind(this)} id="sceneView-container" class={CSS.base}></div>;
}
或
render() {
return <div afterCreate={() => this._bindView()} id="sceneView-container" class={CSS.base}></div>;
}
请参阅以下 CodePen 的工作演示(普通 JavaScript): https://codepen.io/arnofiva/pen/1a801eca6a01ca9bf7625f89f906b6e7
此外,我还建议更改上面代码中的以下内容:
- 将 SceneView 容器
sceneView-container
包装在一个额外的<div>
中以避免 Widget 和 SceneView 共享相同的元素:
<div><div id="sceneView-container" class={CSS.base} afterCreate={this._bindView.bind(this)}></div></div>
- 为
Map.ground
传递一个有效值,例如
const map = new EsriMap({
basemap: "streets",
ground: "world-elevation"
});