mapbox-gl-js icon indicating copy to clipboard operation
mapbox-gl-js copied to clipboard

marker addTo ->ERROR TypeError: this._offset.mult is not a function

Open simplelayers opened this issue 1 year ago • 4 comments

For a line of code that worked in version 2.* which is attempting to add a Marker to the map using addTo "this.queryMarker.addTo(this.map.ui);" where this.queryMarker is a Marker and this.map.ui is a mapbox-gl Map instance

I am getting an error: ERROR TypeError: this._offset.mult is not a function at aI._updateDOM (mapbox-gl.js:33:808684) at mapbox-gl.js:33:810271 at Map._requestDomTask (mapbox-gl.js:33:843059) at aI._update (mapbox-gl.js:33:810216) at aI.addTo (mapbox-gl.js:33:805410)

mapbox-gl-js version: 3.* 2.14.0 Seems to happen after version 2.7.0 where the addTo command worked. browser: Chrome

Steps to Trigger Behavior

I have not confirmed the error in a simpler setup, but the line of code shared above has worked for a couple years and suddenly isn't.

Link to Demonstration

not presently possible I appreciate the virtue of having a discrete test setup. However, the offending code exists once and should be easy for an IDE to find, just look for this._offset._mult "_updateDOM(){const e=this._pos;if(!e||!this._map)return;const t=this._offset.mult(this._scale); ..."

What reasons would this._offset be null/undefined? or not have the expected mult function?

Expected Behavior

I expect a marker to be added to the map without error

Actual Behavior

I get an error about this._mult not being a function.

simplelayers avatar Apr 12 '24 13:04 simplelayers

What reasons would this._offset be null/undefined? or not have the expected mult function?

It's impossible to tell without knowing more about your codebase or having a reproducible example. Does the marker call setOffset at any point, possibly passing a nullish value?

mourner avatar Apr 12 '24 14:04 mourner

What changed between 2.7 and 2.14?Did something change in how markers are added?I may be  adding the marker then positioning it. Im not in front of the code right now. I can look more into it this afternoon. But the same line of code works in 2.7 and  fails in versions after that. Should the update function be checking that position is set before scaling via mult?Sent from my iPhoneOn Apr 12, 2024, at 7:02 AM, Volodymyr Agafonkin @.***> wrote:

What reasons would this._offset be null/undefined? or not have the expected mult function?

It's impossible to tell without knowing more about your codebase or having a reproducible example. Does the marker call setOffset at any point, possibly passing a nullish value?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: @.***>

simplelayers avatar Apr 12 '24 14:04 simplelayers

I found the issue:

version 2.7 marker.js:

_updateDOM() {
        const pos = this._pos || new Point(0, 0);
        const pitch = this._calculatePitch();
        const rotation  = this._calculateRotation();
        this._element.style.transform = `${anchorTranslate[this._anchor]} translate(${pos.x}px, ${pos.y}px) rotateX(${pitch}deg) rotateZ(${rotation}deg)`;
    }

Note: const pos = this._pos || new Point(0, 0);

It is establishing a new point if one is not set

However, that is not happening in the newer versions hence the problem version 3.3.0

  _updateDOM() {
        const pos = this._pos;
        const map = this._map;
        if (!pos || !map) { return; }

        const offset = this._offset.mult(this._scale);

        this._element.style.transform = `
            translate(${pos.x}px,${pos.y}px)
            ${anchorTranslate[this._anchor]}
            ${this._calculateXYTransform()} ${this._calculateZTransform()}
            translate(${offset.x}px,${offset.y}px)
        `;
    }

My problem is that I need the advancements in 3.* but this is impeding me from being able to upgrade.

simplelayers avatar Apr 13 '24 00:04 simplelayers

I have done a deeper exploration of the issue. The code adding my marker was:

this.queryMarker = new Marker(
        {
          anchor: 'center',
          element: puc.element,
          draggable: false,
          offset: { x: 0, y: 0 }
        }
      );

For some reason, even though the older versions defined PointLIke as either Point or [number,number] the above worked. changing offset to new Point(0,0) with the newer versions seems to resolve the error.

In reviewing older and newer versions I don't know that ever should have worked with a non Point object or array. It appears that the offset option for Parameter is not being checked for being a Point in an {x:number,y:number,z?:number} sense of a Point.

This resulted in _updateDOM seeing this._pos as being an object like {x:0,y:0} and not a Point geometry object with mult as a function.

At this juncture I can only guess that Point.convert recieving {x:0,y:0} used to returned some falsy value. this._pos didn't get set to a lnglat object or Point object because offset was falsy. Then _updateDOM used new Point(0,0) because this._pos was falsy and it just so happened that the offset I set at {x:0,y:0} happened to align with the default this._pos new Point(0,0) which worked to initialize the Marker; providing a false positive. When I subsequently set the marker position it moved the marker to where I wanted it so I didn't know there was a problem.

Should there be another aspect of PointLIke that supports a simpler type like

export type PointCoord =  {x:number,y:number,?z:number}

Then Point.convert would need to know to check for Point as a type, an array, or Point Coord and if PointCoord return either a Point or 3DPoint object?

simplelayers avatar Apr 18 '24 01:04 simplelayers