Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement about ArcLayer point-to-point animation #2531

Open
hijiangtao opened this issue Dec 29, 2018 · 1 comment

Comments

@hijiangtao
Copy link
Contributor

commented Dec 29, 2018

Update: Enhancement about ArcLayer animation, see #2531 (comment)


Original Post (problem deprecated):

As mentioned in the title, I want to draw an animation with ArcLayer. As iuntroduced by deck.gl website, the Arc Layer renders raised arcs joining pairs of source and target points, specified as latitude/longitude coordinates, all arcs will be rendered at the same time, so can I animate it from source to target with some time latency?

By looking through the docs, I couldn't find a way to do that, however I found some documents may be useful for me, such as Animation and attribute-manager ,but I couldn't find concrete example of these usage.

However, I found some similar issues, like "How to animate ArcLayer arcs individually?" #633 It seems the developer want to draw different arcs at different time, and your team gave him an approach to do it with updateTriggers. I also need to animation the arc, but not different arcs. I want to draw arc with animation from source to target with some time, as I mentioned above.

I did some trying with his method. I look through the usage of updateTriggers and change the ArcLayer Demo codes with this property (updateTriggers method and getTargetPosition method):

_renderLayers() {
    const {strokeWidth = 2} = this.props;

    return [
      new ArcLayer({
        id: 'arc',
        data: this.state.arcs,
        getSourcePosition: d => d.source,
        getTargetPosition: d => [
          d.target[0] + Math.random()*2,
          d.target[1] + Math.random()*2,
        ],
        getSourceColor: d => (d.gain > 0 ? inFlowColors : outFlowColors)[d.quantile],
        getTargetColor: d => (d.gain > 0 ? outFlowColors : inFlowColors)[d.quantile],
        updateTriggers: {
          getTargetPosition: [time], // time is a variable that can be changed within a `setInterval` 
        },
        strokeWidth,
      }),
    ];
  }

However, I found it can only change arcs suddenly like this, not the animation I want.

image

Any ideas on it? Thanks very much.

@hijiangtao

This comment has been minimized.

Copy link
Contributor Author

commented Dec 29, 2018

background

Thanks for Yaryna Serkez's work on animating arcs:

The idea is pretty straightforward -- each arc has a gradient that varies from the actual color to its fully opaque equivalent. Changing the opacity point updates the length of the arc.

Though I need more time to understand the ideas of drawing animating arcs with help of colors and opactiy, I think the framework of this kind of AnimationArclayer is clear.

For normal ArcLayer, we can enhance it's interaction by providing a point-to-point (from source point to target point) animation.

Approaches

  • Way One: Animate the point-to-point externally by Layer itself.
import {ArcLayer} from 'deck.gl';

class ArcBrushingLayer extends ArcLayer {
  // custom shader with step function to create opacity gradient with colorA and colorB
  // More at https://thebookofshaders.com/05/
  getShaders() {
    return Object.assign({}, super.getShaders(), {
      inject: {
        'vs:#decl': `
         uniform float coef;
        `,
        'vs:#main-end': `
        if (coef > 0.0) {
          vec4 pct = vec4(segmentRatio);
          pct.a = step(coef, segmentRatio);
          vec4 colorA = instanceTargetColors;
          vec4 colorB = vec4(instanceTargetColors.r, instanceTargetColors.g, instanceTargetColors.b, 0.0);
          vec4 color = mix(colorA, colorB, pct) / 255.;
          vColor = color;
        }
                    `,
                    'fs:#main-start': `
        if (vColor.a == 0.0) discard;
                    `,
      },
    });
  }
  
  // overwrite draw fucntion
  draw(opts) {
    const {coef} = this.props;
    // add uniforms
    const uniforms = Object.assign({}, opts.uniforms, { coef });
    super.draw(Object.assign({}, opts, {uniforms}));
  }
}

And for deck.gl developers, we can provide the same API as Arclayer, except one more property called coef, to let them control the drawing process of each arc. The value should be assigned from 0 to 1, in Number type.

The usage can be formatted like this:

new ArcBrushingLayer({
   ... // other properties
   coef, // [0, 1]
});
  • Way Two: Animate the point-to-point internally by Layer itself.

The idea is pretty similar to the first approach, except we let Layer handle the drawing process by itself.

We should add a setInterval to the constructor, and provide a speed property to developers, rather than the pure progress rate coef:

constructor(props) {
	super(props);

	this.state = {
		coef: 0.001,
	};
      
    this.animationArcs();
}

animationArcs() {
	const {coef} = this.state;
	const = {speed} = this.props || 0.005;
	const animationInterval = setInterval(()=> {
        coef += 0.005;
        if (coef >= 1.0) {
          clearInterval(animationInterval);
        }
        this.setState({
          coef,
        })
      }, 10);
}

Last, we get coef from component's state, rather than its props.

@hijiangtao hijiangtao changed the title Is there any approach in drawing point-to-point animation ArcLayer? Enhancement about ArcLayer point-to-point animation Dec 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.