fbpx

The Line Has Been Drawn

Last week I was working in an Angular2 project. The feature called for us to draw a line on a canvas element.  The gotcha; the line had to fade out like a comet tail and we had maintain visibility of a background image.


Using this Tarik A’s free hand drawing implementation, to capture the points of the line, Greensock to animate the tail, and this bit of code.  We were able to achieve a nice fade out effect.
...

@Component({
  template: `
<div class="container" #container>
              <canvas #canvas></canvas>
              <svg #svg></svg>
            </div>

`
})

...

@ViewChild(‘svg') svg: ElementRef;
svgns = ‘http://www.w3.org/2000/svg';    

createLine(leader, follower) {
        const line = document.createElementNS(this.svgns, 'line');
        
        TweenMax.set(line, { stroke: `#FFFFFF`, strokeWidth: 3, alpha: 1 });
        line.setAttribute('x1', `${follower.x}`);
        line.setAttribute('y1', `${follower.y}`);
        line.setAttribute('x2', `${leader.x}`);
        line.setAttribute('y2', `${leader.y}`);

        this.svg.nativeElement.appendChild(line);        

        // fade out
        TweenMax.to(line, 0.5, { alpha: 0 });
    }

...

Using jQuery.queue() to call Functions Synchronously

This week I was working on a project that required me to add a css class to an element within a sequence of events. First I wanted to fadeOut() an array of elements, wait a moment, and then add a class to another element.

Because Javascript is asynchronous, on my first attempt everything executed, just not in the order I had anticipated.

Enter jQuery.queue().

This handy little function allows you to pass in a callback with next as a parameter, enabling you to call jQuery and Javascript synchronously.

someElements.fadeOut()
            .delay(200)
            .queue(function(next) {
              otherElements.removeClass('active');
              thisElement.addClass('active');
              next(); // continue to next line
            });
someElements.fadeIn();

Now we can call fadeOut() on someElements, handle adding and removing classes after our delay() and then fade someElements back in.

Testing time based activities in Angular

When testing time streams or promised based activities use ‘fakeAsync’ and ‘tick’.

For example, given a service:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class CountdownService {
  // counts down from given number to zero
  source(num: number): Observable<number> {
    return Observable.timer(1000, 1000)
    .map( (v) => num - v)
    .takeWhile( (v) => v !== -1);
  }
}

To test the CountDown class source method:

// … test setup above, inside describe function

it('should count down from 5 to 0', inject([CountdownService], fakeAsync( (service: CountdownService) => {
    let num: number = undefined;
    const count = service.source(5).subscribe( (value) => num = value);
    tick(7000)

    expect(num).toEqual(0);
})));

Wrap the ‘it’ callback function in fakeAsync() which creates a new zone for the asynchronous code to run.

Calling tick() with a time span in ms, simulates the code after that amount of time has passed.

Use tick() with no arguments for promise based code

My expectation is based on what happens after 7 seconds has passed.