visgl / deck.gl

WebGL2 powered visualization framework
https://deck.gl
MIT License
12.29k stars 2.09k forks source link

Bad uniform iconsTextureDim (2) [undefined, undefined] with IconLayer #3449

Closed CorentinAmbroise closed 4 years ago

CorentinAmbroise commented 5 years ago

Description

I am developping an app which contains a map on which are displayed data. I am currently implementing a layer which is composed of a heatmap which is a simple extension of an HexagonLayer, and it is supposed to turn into an IconLayer extension when the zoom is big enough to see all the data points. So this is the same map's layer which turns from an HexagonLayer into a IconLayer, that I instantiate with a correct iconAtlas and iconMapping (it used to work, none of these has changed and it still matches the documentation requirements). The IconLayer still has some properties of the heatmap, like the radius and the onHover function. This bug occurs right when I zoom enough to change the Heatmap to the IconLayer. Both of them have data correctly formatted for their use by the layer. So the _externalTexture of the IconManager is null and the _texture is not, but it seems like its height and width are undefined, eventhough when I log them right before I get the error they are not.

If I only display the points of data from the begining, not the heatmap, so that the layer remains an IconLayer, it works fine.

Environment :

Logs

Error :

index.js:1375 fleet-icon-program  Bad uniform iconsTextureDim (2) [undefined, undefined]
console.<computed> @ index.js:1375
checkUniformValues @ uniforms.js:179
setUniforms @ program.js:205
setUniforms @ base-model.js:98
draw @ icon-layer.js:238
(anonymous) @ layer.js:928
withParameters @ with-parameters.js:17
drawLayer @ layer.js:927
drawLayerInViewport @ layers-pass.js:164
(anonymous) @ layers-pass.js:136
drawLayersInViewport @ layers-pass.js:122
(anonymous) @ layers-pass.js:64
drawLayers @ layers-pass.js:58
(anonymous) @ layers-pass.js:27
withParameters @ with-parameters.js:17
render @ layers-pass.js:24
renderLayers @ deck-renderer.js:87
_drawLayers @ deck.js:663
_redrawDeck @ deckgl.js:86
componentDidUpdate @ deckgl.js:60
commitLifeCycles @ react-dom.development.js:21157
commitLayoutEffects @ react-dom.development.js:24138
callCallback @ react-dom.development.js:363
invokeGuardedCallbackDev @ react-dom.development.js:412
invokeGuardedCallback @ react-dom.development.js:466
commitRootImpl @ react-dom.development.js:23903
unstable_runWithPriority @ scheduler.development.js:674
runWithPriority$2 @ react-dom.development.js:11834
commitRoot @ react-dom.development.js:23723
runRootCallback @ react-dom.development.js:22809
(anonymous) @ react-dom.development.js:11886
unstable_runWithPriority @ scheduler.development.js:674
runWithPriority$2 @ react-dom.development.js:11834
flushSyncCallbackQueueImpl @ react-dom.development.js:11881
flushSyncCallbackQueue @ react-dom.development.js:11869
scheduleUpdateOnFiber @ react-dom.development.js:22667
enqueueForceUpdate @ react-dom.development.js:13755
push../node_modules/react/cjs/react.development.js.Component.forceUpdate @ react.development.js:343
_customRender @ deckgl.js:98
redraw @ deck.js:279
_onRenderFrame @ deck.js:709
onRender @ animation-loop.js:278
_renderFrame @ animation-loop.js:352
redraw @ animation-loop.js:170
renderFrame @ animation-loop.js:310
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
Show 15 more frames
uniforms.js:180 Uncaught Error: fleet-icon-program  Bad uniform iconsTextureDim
    at checkUniformValues (uniforms.js:180)
    at Program.setUniforms (program.js:205)
    at Model.setUniforms (base-model.js:98)
    at Icon.draw (icon-layer.js:238)
    at layer.js:928
    at withParameters (with-parameters.js:17)
    at Icon.drawLayer (layer.js:927)
    at DrawLayersPass.drawLayerInViewport (layers-pass.js:164)
    at layers-pass.js:136
    at Array.forEach (<anonymous>)
    at DrawLayersPass.drawLayersInViewport (layers-pass.js:122)
    at layers-pass.js:64
    at Array.forEach (<anonymous>)
    at DrawLayersPass.drawLayers (layers-pass.js:58)
    at layers-pass.js:27
    at withParameters (with-parameters.js:17)
    at DrawLayersPass.render (layers-pass.js:24)
    at DeckRenderer.renderLayers (deck-renderer.js:87)
    at Deck._drawLayers (deck.js:663)
    at DeckGL._redrawDeck (deckgl.js:86)
    at DeckGL.componentDidUpdate (deckgl.js:60)
    at commitLifeCycles (react-dom.development.js:21157)
    at commitLayoutEffects (react-dom.development.js:24138)
    at HTMLUnknownElement.callCallback (react-dom.development.js:363)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:412)
    at invokeGuardedCallback (react-dom.development.js:466)
    at commitRootImpl (react-dom.development.js:23903)
    at unstable_runWithPriority (scheduler.development.js:674)
    at runWithPriority$2 (react-dom.development.js:11834)
    at commitRoot (react-dom.development.js:23723)
    at runRootCallback (react-dom.development.js:22809)
    at react-dom.development.js:11886
    at unstable_runWithPriority (scheduler.development.js:674)
    at runWithPriority$2 (react-dom.development.js:11834)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11881)
    at flushSyncCallbackQueue (react-dom.development.js:11869)
    at scheduleUpdateOnFiber (react-dom.development.js:22667)
    at Object.enqueueForceUpdate (react-dom.development.js:13755)
    at DeckGL.push../node_modules/react/cjs/react.development.js.Component.forceUpdate (react.development.js:343)
    at DeckGL._customRender (deckgl.js:98)
    at Deck.redraw (deck.js:279)
    at Deck._onRenderFrame (deck.js:709)
    at AnimationLoop.onRender (animation-loop.js:278)
    at AnimationLoop._renderFrame (animation-loop.js:352)
    at AnimationLoop.redraw (animation-loop.js:170)
    at renderFrame (animation-loop.js:310)
checkUniformValues @ uniforms.js:180
setUniforms @ program.js:205
setUniforms @ base-model.js:98
draw @ icon-layer.js:238
(anonymous) @ layer.js:928
withParameters @ with-parameters.js:17
drawLayer @ layer.js:927
drawLayerInViewport @ layers-pass.js:164
(anonymous) @ layers-pass.js:136
drawLayersInViewport @ layers-pass.js:122
(anonymous) @ layers-pass.js:64
drawLayers @ layers-pass.js:58
(anonymous) @ layers-pass.js:27
withParameters @ with-parameters.js:17
render @ layers-pass.js:24
renderLayers @ deck-renderer.js:87
_drawLayers @ deck.js:663
_redrawDeck @ deckgl.js:86
componentDidUpdate @ deckgl.js:60
commitLifeCycles @ react-dom.development.js:21157
commitLayoutEffects @ react-dom.development.js:24138
callCallback @ react-dom.development.js:363
invokeGuardedCallbackDev @ react-dom.development.js:412
invokeGuardedCallback @ react-dom.development.js:466
commitRootImpl @ react-dom.development.js:23903
unstable_runWithPriority @ scheduler.development.js:674
runWithPriority$2 @ react-dom.development.js:11834
commitRoot @ react-dom.development.js:23723
runRootCallback @ react-dom.development.js:22809
(anonymous) @ react-dom.development.js:11886
unstable_runWithPriority @ scheduler.development.js:674
runWithPriority$2 @ react-dom.development.js:11834
flushSyncCallbackQueueImpl @ react-dom.development.js:11881
flushSyncCallbackQueue @ react-dom.development.js:11869
scheduleUpdateOnFiber @ react-dom.development.js:22667
enqueueForceUpdate @ react-dom.development.js:13755
push../node_modules/react/cjs/react.development.js.Component.forceUpdate @ react.development.js:343
_customRender @ deckgl.js:98
redraw @ deck.js:279
_onRenderFrame @ deck.js:709
onRender @ animation-loop.js:278
_renderFrame @ animation-loop.js:352
redraw @ animation-loop.js:170
renderFrame @ animation-loop.js:310
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
requestAnimationFrame (async)
requestAnimationFrame @ request-animation-frame.js:2
_requestAnimationFrame @ animation-loop.js:339
renderFrame @ animation-loop.js:312
Show 14 more frames
index.js:1375 The above error occurred in the <DeckGL> component:
    in DeckGL (at Map.jsx:161)
    in div (at Map.jsx:158)
    in RequestComponent (created by ConnectFunction)
    in ConnectFunction (created by Context.Consumer)
    in withRouter(Connect(RequestComponent)) (at Map.jsx:157)
    in MapComponent (created by WithStylesInner)
    in WithStylesInner (created by Context.Consumer)
    in WithStyles(MapComponent) (created by ConnectFunction)
    in ConnectFunction (at MainPage.jsx:130)
    in div (at MainPage.jsx:172)
    in RequestComponent (created by ConnectFunction)
    in ConnectFunction (created by Context.Consumer)
    in withRouter(Connect(RequestComponent)) (at MainPage.jsx:171)
    in RequestComponent (created by ConnectFunction)
    in ConnectFunction (created by Context.Consumer)
    in withRouter(Connect(RequestComponent)) (at MainPage.jsx:169)
    in MainPage (created by Context.Consumer)
    in withRouter(MainPage) (created by ConnectFunction)
    in ConnectFunction (at App.js:51)
    in Route (at App.js:59)
    in div (at App.js:58)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:57)
    in App (created by ConnectFunction)
    in ConnectFunction (at src/index.js:132)
    in Provider (at src/index.js:131)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

With some warnings from the WebGl :

Error: WebGL warning: texImage2D: Alpha-premult and y-flip are deprecated for non-DOM-Element uploads. before the error with Firefox.

WebGL: INVALID_OPERATION: texImage2D: no texture bound to target after the error with both Firefox and Chrome.

Thanks in advance for your help, I hope I provided enough information, ask if you need anything.

Pessimistress commented 5 years ago

Are you implementing a custom composite layer? If so, can you share the code?

When you say "it used to work", what was the last working release?

It's hard to tell what's wrong from your description, but you should make sure that when you "switch", the hexagon layer and the icon layer use different ids.

CorentinAmbroise commented 5 years ago

Here is the Code Pen that I wrote to reproduce the bug : https://codepen.io/CorentinAmbroise/pen/yLBOxPa?editors=1011

It used to work in a another version of the framework I guess, I'll dig deeper to find it. Yes they already use different ids.

Thanks !

CorentinAmbroise commented 5 years ago
import React, { Component } from 'react';
import { StaticMap } from 'react-map-gl';
import DeckGL from '@deck.gl/react';
import { IconLayer } from '@deck.gl/layers';
import { HexagonLayer } from '@deck.gl/aggregation-layers';

import { json } from 'd3';

const randomName = () => {
  const names = Object.keys(iconMapper);
  return names[Math.floor(Math.random() * names.length)];
}

class Heatmap extends HexagonLayer {}

Heatmap.defaultProps = {
  getPosition: { type: 'accessor', value: d => (d ? d.geometry.coordinates : null) },
  radius: 1000,
  colorRange: [
    [254, 235, 226, 255 * 0.5],
    [252, 197, 192, 255 * 0.6],
    [250, 159, 181, 255 * 0.6],
    [247, 104, 161, 255 * 0.7],
    [197, 27, 138, 255 * 0.8],
    [122, 1, 119, 255 * 0.8],
  ],
  opacity: 1,
};

const iconMapper = JSON.parse('{"001-goal":{"x":1536,"y":1023,"height":512,"width":512},"002-flag":{"x":1024,"y":1023,"height":512,"width":512},"003-tasks":{"x":511,"y":0,"height":511,"width":511},"004-cloud":{"x":0,"y":1535,"height":512,"width":512},"005-presentation":{"x":1536,"y":1535,"height":512,"width":512},"006-presentation-1":{"x":512,"y":1535,"height":512,"width":512},"007-briefcase":{"x":0,"y":0,"height":511,"width":511},"008-rating":{"x":1024,"y":1535,"height":512,"width":512},"009-rating-1":{"x":512,"y":1023,"height":512,"width":512},"010-badge":{"x":1536,"y":511,"height":512,"width":512},"011-trophy":{"x":0,"y":511,"height":512,"width":512},"012-clipboard":{"x":0,"y":1023,"height":512,"width":512},"013-rating-2":{"x":1022,"y":0,"height":511,"width":511},"014-success":{"x":1024,"y":511,"height":512,"width":512},"015-rating-3":{"x":512,"y":511,"height":512,"width":512},"016-trophy-1":{"x":1533,"y":0,"height":511,"width":511}}');

const spritesheetIcons = 'https://dl.dropboxusercontent.com/s/i99zfjzliuy6rn5/spritesheetIcons.png';

const data = json('https://dl.dropbox.com/s/hng2qrjvbn6x707/randomPointsInParis.json');

class Icon extends IconLayer {}

Icon.defaultProps = {
  iconAtlas: spritesheetIcons,
  iconMapping: iconMapper,
  dataTransform: data => data.map(feature => ({ position: feature.geometry.coordinates, icon: randomName() })),
  getSize: 1,
  sizeScale: 100,
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      width: window.innerWidth,
      height: window.innerHeight, // - this.props.header.height,
      viewState: {
        longitude: 2.3442,
        latitude: 48.8617,
        zoom: 11.7,
      },
      layers: []
    }
  }

  componentWillMount() {
    this.setState({ layers: [new Heatmap({ id: 'random-icon', data })] })
  }

  componentWillUpdate(nextProps, nextState) {
    const layers = [ ...this.state.layers ];
    if (nextState.viewState.zoom > 14) {
      layers[0] = new Icon({ id: 'icon-random', data });
      // layers[0] = new IconLayer({
      //   id: 'icon-random',
      //   data,
      //   dataTransform: data => data.map(feature => ({ position: feature.geometry.coordinates, icon: randomName() })),
      //   iconAtlas: spritesheetIcons,
      //   iconMapping: iconMapper,
      //   getSize: 1,
      //   sizeScale: 100,
      // });
    } else {
      layers[0] = new Heatmap({ id: 'random-heatmap', data });
    }
    if (nextState.viewState.zoom !== this.state.viewState.zoom) {
      this.setState({ layers });
    }
  }

  render() {
    return (
      <DeckGL
        initialViewState={this.state.viewState}
        viewState={this.state.viewState}
        onViewStateChange={({ viewState }) => this.setState({ viewState })}
        width={this.state.width}
        height={this.state.height}
        controller
        layers={this.state.layers}
      >
        <StaticMap
          mapStyle={`mapbox://styles/mapbox/basic-v9`}
          mapboxApiAccessToken="pk.eyJ1IjoiamVhbmlwYSIsImEiOiJjanFmNzIzbXY0bWEwNDNueWxjaHViYjBpIn0.86nUQxt2lIiqQpj5puy1TQ"
        />
      </DeckGL>
    );
  }
}

export default App;

Here is a React App that reproduces the bug if it is better for you to work with. The only other dependency, except from deck.gl and react is d3.

With the file as it is now, the bug will occur if you zoom enough on the map. To see the difference when I use the extended layer Icon instead of deck.gl's IconLayer, comment in componentWillUpdate the line 69 and uncomment lines from 70 to 78, and try again. The fact that Heatmap extends HexagonLayer doesn't change anything.

Thank you

Pessimistress commented 5 years ago

@CorentinAmbroise In Layer.defaultProps, each prop name maps to a prop type definition, something like {type, value, ...}. Usually, if you use a value that is not in this shape, such as sizeScale: 1, deck.gl will convert it to {type: 'number', value: 1} internally. In the case of the iconAtlas, if you want deck to automatically load an URL, the prop must be defined with async: true. Without the option, props.iconAtlas just returns a plain string.

To change the default prop values, you can copy a prop's definition from IconLayer.defaultProps, and modify the value field, e.g.:

MyLayer.defaultProps = {
  iconAtlas: {type: 'object', value: '<url>', async: true}
};
CorentinAmbroise commented 5 years ago

@CorentinAmbroise In Layer.defaultProps, each prop name maps to a prop type definition, something like {type, value, ...}. Usually, if you use a value that is not in this shape, such as sizeScale: 1, deck.gl will convert it to {type: 'number', value: 1} internally. In the case of the iconAtlas, if you want deck to automatically load an URL, the prop must be defined with async: true. Without the option, props.iconAtlas just returns a plain string.

To change the default prop values, you can copy a prop's definition from IconLayer.defaultProps, and modify the value field, e.g.:

MyLayer.defaultProps = {
  iconAtlas: {type: 'object', value: '<url>', async: true}
};

It was indeed the issue thank you (it works If I don't use iconAtlas as a defaultProps and just pass it to the constructor) and I understand better now. Nonetheless, your fix doesn't seem to be working either, are you sure this works ? I tried it with the App that I gave you in my last reply, and it is not working

Thank you very much

Pessimistress commented 5 years ago

Hmm looks like our async loading mechanism does not support using default values like this. When there is a default value it will skip "loading" and just use it as-is. Arguably it was never designed to be used this way... @ibgreen

ibgreen commented 5 years ago

That is correct (if I understand this correctly), I never anticipated that anyone would want to have a default url rather than a default value.

While I am open to discussion, my take right now is that this seems like a rather special use case. I am not convinced it makes sense to support it unless we see that this will be more commonly useful.

It is probably not a major change, but the async props implementation is quite complex as it stands, more test cases etc would be needed.

A minor observation is that, even if we implemented this, there probably needs to be a default value anyway (that the layer sees until the URL is loaded), so we might need to add another field to the prop type.

@CorentinAmbroise I am sure you already considered this, but an atlas is just a json file so it is easy to include in your bundle if you are using webpack, no need to load it dynamically.