in packages/core/base/src/Polaris.ts [43:198]
constructor(props: PolarisProps) {
// @note do not pass props into AbstractLayer constructor
super()
const _props = {
...defaultProps,
...props,
}
this.setProps(_props)
this.#width = _props.width
this.#height = _props.height
this.#ratio = _props.ratio
this.watchProps(['width', 'height', 'ratio'], (e) => {
this.resize(
this.getProp('width') ?? this.#width,
this.getProp('height') ?? this.#height,
this.getProp('ratio') ?? this.#ratio
)
})
/**
* init timeline
*/
const timeline =
_props.timeline ||
new Timeline({
duration: Infinity,
// pauseWhenInvisible: false, // 检测标签页是否隐藏,已知在一些环境中不可用,建议关闭
openStats: false,
autoRelease: true, // 自动回收过期的track
maxStep: 1000, // 最大帧长
maxFPS: 30, // 最大帧率
// ignoreErrors: true, // 出错后是否停止
})
/**
* 等到全部初始化完成后再开始计时运行
*/
if (_props.autoplay) {
if (_props.timeline) {
console.warn('Polaris:: autoplay will be ignored for custom timeline.')
} else {
setTimeout(() => {
if (this.timeline.playing)
throw new Error('Polaris:: Timeline is already playing. Autoplay may restart timeline.')
this.timeline.play()
})
}
}
/**
* init projection
*/
const projection =
_props.projection ||
new MercatorProjection({
center: [0, 0],
})
this.timeline = timeline
this.projection = projection
/**
* init html / canvas
*/
/**
* init CameraProxy
* proxy Renderer.camera
*/
const { fov, center, zoom, pitch, rotation } = _props
const cameraProxy = new AnimatedCameraProxy({
cameraFOV: fov as number,
timeline: timeline as any, // AnimatedCameraProxy use old version of timeline but only unchanged api
canvasWidth: this.canvasWidth,
canvasHeight: this.canvasHeight,
ratio: this.#ratio,
onUpdate: () => {},
})
// cameraProxy config props listener
this.watchProps(
['zoomLimit', 'pitchLimit'],
(e) => {
if (!e.initial) console.warn('Changing camera limit after init is deprecated.')
cameraProxy['limit'].zoom = this.getProp('zoomLimit')
cameraProxy['limit'].pitch = this.getProp('pitchLimit')
},
true
)
// 更新相机初始状态
const geo = this.projection.project(...(center as [number, number, number]))
const states: GeographicStates = {
center: geo,
pitch: pitch || 0 - 0,
rotation: rotation || 0 - 0,
zoom: zoom || 0 - 0,
}
// 使用无缓动的setStates方法,因为此时timeline可能还未start
cameraProxy.setGeographicStates(states)
// this.cameraman = new Cameraman({ camera: cameraProxy })
this.cameraProxy = cameraProxy
// handle projection alignment and ViewChangeEvent, on every frame
this.addEventListener('beforeRender', (e) => {
this.traverse((layer) => {
// projection alignment
// skip root
if (layer.parent) {
const parentProjection = resolveProjection(layer.parent)!
const projection = resolveProjection(layer)!
const visualCenter = this.getGeoCenter()
const alignmentMatrix = Coordinator.getRelativeMatrix(parentProjection, projection, [
visualCenter[0],
visualCenter[1],
])
layer.updateAlignmentMatrix(alignmentMatrix)
}
// ViewChange detection
checkViewChange(this, layer)
})
})
// 基本绘制循环
this.timeline.addTrack({
id: 'polaris_render_loop',
duration: Infinity,
loop: false,
onUpdate: () => {
if (_props.asyncRendering) {
setTimeout(() => {
this.tick()
})
} else {
this.tick()
}
},
})
// static props(change these props will not be reacted or even cause problems)
this.watchProps(STATIC_PROPS, (e) => {
const msg = `Do not modify static props: [${e.changedKeys.join(',')}]`
this.dispatchEvent({ type: 'error', error: new Error(msg) })
console.error(msg)
})
}