Skip to content

Commit

Permalink
Bypass the DOM rendering queue if map is idle (#10567)
Browse files Browse the repository at this point in the history
* Bypass the DOM rendering queue if map is idle

* Add a map._requestDomTask method to handle the behavior surrounding DOM elements

* Directly use map instead of domQueue in scale_control
  • Loading branch information
zarov authored Apr 19, 2021
1 parent 5624309 commit 364ca37
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/ui/control/navigation_control.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class NavigationControl {
`scale(${1 / Math.pow(Math.cos(this._map.transform.pitch * (Math.PI / 180)), 0.5)}) rotateX(${this._map.transform.pitch}deg) rotateZ(${this._map.transform.angle * (180 / Math.PI)}deg)` :
`rotate(${this._map.transform.angle * (180 / Math.PI)}deg)`;

this._map._domRenderTaskQueue.add(() => {
this._map._requestDomTask(() => {
if (this._compassIcon) {
this._compassIcon.style.transform = rotate;
}
Expand Down
15 changes: 7 additions & 8 deletions src/ui/control/scale_control.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,32 +96,31 @@ function updateScale(map, container, options) {
const left = map.unproject([0, y]);
const right = map.unproject([maxWidth, y]);
const maxMeters = left.distanceTo(right);
const domQueue = map._domRenderTaskQueue;
// The real distance corresponding to 100px scale length is rounded off to
// near pretty number and the scale length for the same is found out.
// Default unit of the scale is based on User's locale.
if (options && options.unit === 'imperial') {
const maxFeet = 3.2808 * maxMeters;
if (maxFeet > 5280) {
const maxMiles = maxFeet / 5280;
setScale(container, maxWidth, maxMiles, map._getUIString('ScaleControl.Miles'), domQueue);
setScale(container, maxWidth, maxMiles, map._getUIString('ScaleControl.Miles'), map);
} else {
setScale(container, maxWidth, maxFeet, map._getUIString('ScaleControl.Feet'), domQueue);
setScale(container, maxWidth, maxFeet, map._getUIString('ScaleControl.Feet'), map);
}
} else if (options && options.unit === 'nautical') {
const maxNauticals = maxMeters / 1852;
setScale(container, maxWidth, maxNauticals, map._getUIString('ScaleControl.NauticalMiles'), domQueue);
setScale(container, maxWidth, maxNauticals, map._getUIString('ScaleControl.NauticalMiles'), map);
} else if (maxMeters >= 1000) {
setScale(container, maxWidth, maxMeters / 1000, map._getUIString('ScaleControl.Kilometers'), domQueue);
setScale(container, maxWidth, maxMeters / 1000, map._getUIString('ScaleControl.Kilometers'), map);
} else {
setScale(container, maxWidth, maxMeters, map._getUIString('ScaleControl.Meters'), domQueue);
setScale(container, maxWidth, maxMeters, map._getUIString('ScaleControl.Meters'), map);
}
}

function setScale(container, maxWidth, maxDistance, unit, domQueue) {
function setScale(container, maxWidth, maxDistance, unit, map) {
const distance = getRoundNum(maxDistance);
const ratio = distance / maxDistance;
domQueue.add(() => {
map._requestDomTask(() => {
container.style.width = `${maxWidth * ratio}px`;
container.innerHTML = `${distance} ${unit}`;
});
Expand Down
2 changes: 1 addition & 1 deletion src/ui/handler/box_zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class BoxZoomHandler {
minY = Math.min(p0.y, pos.y),
maxY = Math.max(p0.y, pos.y);

this._map._domRenderTaskQueue.add(() => {
this._map._requestDomTask(() => {
if (this._box) {
DOM.setTransform(this._box, `translate(${minX}px,${minY}px)`);

Expand Down
15 changes: 15 additions & 0 deletions src/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -2518,6 +2518,21 @@ class Map extends Camera {
this._renderTaskQueue.remove(id);
}

/**
* Request that the given callback be executed during the next render frame if the map is not
* idle. Otherwise it is executed immediately, to avoid triggering a new render.
* @private
*/
_requestDomTask(callback: () => void) {
// This condition means that the map is idle: the callback needs to be called right now as
// there won't be a triggered render to run the queue.
if (!this.isMoving() && this.loaded()) {
callback();
} else {
this._domRenderTaskQueue.add(callback);
}
}

/**
* Call when a (re-)render of the map is required:
* - The style has changed (`setPaintProperty()`, etc.)
Expand Down
2 changes: 1 addition & 1 deletion src/ui/marker.js
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ export default class Marker extends Evented {
this._pos = this._pos.round();
}
this._map._domRenderTaskQueue.add(() => {
this._map._requestDomTask(() => {
if (this._element && this._pos && this._anchor) {
DOM.setTransform(this._element, `${anchorTranslate[this._anchor]} translate(${this._pos.x}px, ${this._pos.y}px) ${pitch} ${rotation}`);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ui/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ export default class Popup extends Evented {
}

const offsetedPos = pos.add(offset[anchor]).round();
this._map._domRenderTaskQueue.add(() => {
this._map._requestDomTask(() => {
if (this._container && anchor) {
DOM.setTransform(this._container, `${anchorTranslate[anchor]} translate(${offsetedPos.x}px,${offsetedPos.y}px)`);
applyAnchorClass(this._container, anchor, 'popup');
Expand Down

0 comments on commit 364ca37

Please sign in to comment.