Friday, February 17, 2017

Recipe for creating parallax effect of background image in Angular 2.0 Typescript

import { HostListener, Component, OnChanges, Directive, Input, Output, EventEmitter, SimpleChange, ElementRef} from '@angular/core';

Here is the directive:

@Directive({
    selector: '[track-scroll]',
    //host: {'(window:scroll)': 'track($event)'},
 
})

export class TrackScrollComponent {

  @Output() notify: EventEmitter = new EventEmitter();
  @HostListener('scroll', [''])
    track() {
        console.debug("Scroll Event");
        //console.debug(this._elementRef.nativeElement.scrollTop);
        this.notify.emit(this._elementRef.nativeElement.scrollTop);
    }
   constructor(private _elementRef: ElementRef) {}
}

It is worth noting that you'd want an event emitter which communicates changes in track-scroll directive back to the parent component.

Now as indicated in the previous posting on implementing in the parent component html you'd modify the tag with a on notify event handler:

<nav track-scroll (notify)='onNotify($event)' >
   <nav class='backgroundimageclass' style.background-image.position-y = "{{this.scrollpos}}px"
</nav>


Now in your parent component you'd need to make sure to have  scrollpos set as class instance object type number and ensure that the event function is defined with updates to scrollpos in this onNotify function:

@Component({
    moduleId: module.id,
  selector: 'parentcomponent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],

})

export class ParentComponent{
   scrollpos: number = 0.0;

   onNotify(message:number):void {
        this.scrollpos = message*0.2;
        console.log("hitting!");
        console.log(message);
    }
}

Thus the child directive is transmitting back through "message" the scroll position which is assigned to the parent class object scrollpos and this class object is interpolated back into the parent html style.background-image.position-y value...note we are scaling to a fractional value 0.2 the amount of change resembling parallax so that the background image is not equal to the shift in text.

Here is an example parent.component.css sheet for adding the background image:

.backgroundimageclass{
     background-image: url(../assets/MainNavHeader_V01.png);
    /*background: rgba(76, 175, 80, 1.0);*/
    /*background-color: black;*/
    /*background-size: 1200px 780px;*/
    padding-top: 10px;
    background-blend-mode: overlay;
    /*min-width: 1236px;*/
    /*min-height: 298px;*/
    /*width: 1236px;*/
    /*height: 298px;*/
    position: relative;
    left: 50px;
    -webkit-mask-image: -webkit-gradient(linear, left 70%, left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
    /*-webkit-mask-image: -webkit-gradient(linear, left 30%, left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));*/
    /*background-position-y: 100px;*/
    /*background-repeat: no-repeat;*/
    /*overflow: auto;
    clear: both;*/
}

I've included in this case a little webkit alpha mask also on the background image which feather fades the bottom border for instance.

Note my import statement above is done so assuming the parent and child directive are in the same file.  If you wanted to separate these, just make sure to update your import statements.

Please read my previous post for additional information on implementing the child directive in the parent.  Namely, you'll want to ensure that the directive is actually done through the app.module.ts declarations for most current versions of Angular 2.0

A little bit of GIS information: Acquiring DEM heightmap renderings and colorization



First it should be mentioned that if you are doing terrain colorization of your choosing, you may already be familiar with or not http://viewer.nationalmap.gov/ in obtaining both satellite terrain imagery and/or heightmap data.  The big challenge, however, comes in how to re purpose this data in the context of say a 3D modeler like Blender.  Adding that I would recommend a program called QGIS (http://www.qgis.org/en/site/)  which provides GIS rasterization (rendering) services specifically tailored to things like heightmap mosaicing and a lot more.  Mosaicing is particularly useful because often heightmaps tend to be parsed by coordinate range addresses.  Without any GIS program, you'd have to have some alternate graphics program properly align and stitch these mosaics together in their proper coordinate range addresses otherwise (which is not needed).  Secondly QGIS equalizes heightmap mosaics when they are merged into one heightmap handling overall differences between the two maps (which may not be absolute in the context of luminosity and light values over the range of greyscales for instance in greyscaling formats by analogy). 

Other prerequisites:  
In Ubuntu installation goes as follows:
https://trac.osgeo.org/ubuntugis/wiki/QuickStartGuide
apt-get install cgi-mapserver
Because a given heightmap is actually given by measurements which include the surface of the Earth which is curved we will need to however project a given map flat...in this case GDAL warp packages (doing this task) will need flat projection coordinates under a lambert-conformal conic transformation.   Don't worry there is a utility in java script to handle this task...though you will need access to java script.  I like node.js which makes use of package manager called npm to handle these sorts of packages for easy to directory installation.

I recommend utilizing a java script called Proj4js and if you use node.js the node package is proj4 (see https://github.com/proj4js/proj4js) which can be installed via npm (node package manager) at your terminal command line :
Using this command will install the node package in the given root directory at prompt.

npm install proj4

you can run node at terminal, once installed typing:
$ node

once node is running in terminal then:

> var proj4 = require("proj4");

You may also find it handy for input and output coordinate parameters using information given from
spatialreference.org

next we define the destination projection given from spatial reference.org

>proj4.defs('EPSG:2228',"+proj=lcc +lat_1=37.25 +lat_2=36 +lat_0=35.33333333333334 +lon_0=-119 +x_0=2000000.0001016 +y_0=500000.0001016001 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs");

if you type then 'proj4' and hit enter you should see the definition given..
with key value 'EPSG:2228'.

The source rule is already defined for longitude-latitude coordinates:
which is 'EPSG:4326'

so conversion at prompt is as follows:
> proj4('EPSG:4326','EPSG:2228',[-118,32.0170]);

// yields [ 6872583.317630408, 433558.88221227354 ]

You can use this to find projection coordinates from one coordinate system to another.  That being said QGIS also has handlers for Relief, Hillshade and Slope, Roughness, TRI, and TPI colorization and plugins in provisioning custom color gradients alongside providing users the ability to customize color gradient sets.

So the short workflow synopsis goes as follows:

With DEM dataset downloaded, you can load, for instance, .img sets on a new QGIS project session as follows:
Assuming that you have downloaded multiple filesets for a given geographic selection range, you may want to merge your heightmap files (merging these will equalize this files relative to one another...otherwise jump discontinuities may likely occur between them).

Merging Mosaics
1.  Choose 'Raster>Miscellaneous>Merge...'.
2.   Pressing 'ctrl' button select all necessary source files to be merged for source.
3.  Assign a destination file.  You may likely need to make sure the destination file type matches the source (this is not always given by default).
4.  Press 'Ok'.

All is done well and you should see a mosaic composition of all merged images shown in the QGIS visual browser window.

Selection cropping by latitude/longitude coordinates
1. Choose 'Raster>Extraction>Clipper'
2. At Dialog, longitudinal coordinates are X and latitude coordinates Y...or alternately you can select on the map visually coordinate boundaries.
3.  Assign destination file. You may likely need to make sure the destination file type matches the source (this is not always given by default).
4. Press 'Ok'.

Projection warp flattening the data set

1.  'Raster>Projection>Warp...'
2.   Default lat/long coordinate source SRS is usually provisioned depending on your file type, but you will likely need to indicate the target SRS (e.g.,  'EPSG:2228' above projection flattens coordinates for the state of California).
3.  As above source (e.g. merged file above) is selected and destination name assigned.
4.  Press 'Ok'.

Generating Hill Shade

Reading the scroll position of an html element in Angular 2.0 Typescript

I've seen some implement a component, which you can can do but this expects (to my knowledge) an html template.  I've used instead directive (which a component is but without the requirement of having an associated html template).

Here is my directive:
import { HostListener, Component, OnChanges, Directive, Input, Output, EventEmitter, SimpleChange, ElementRef} from '@angular/core';

@Directive({
    selector: '[track-scroll]',
    //host: {'(window:scroll)': 'track($event)'},
 
})

export class TrackScrollComponent {
  @HostListener('scroll', [''])
    track() {
        console.debug("Scroll Event");
        console.debug(this._elementRef.nativeElement.scrollTop);
    }
   constructor(private _elementRef: ElementRef) {}
}

I did use injection of the Element Ref, or as it is instanced from the 'div' tag the div ElementRef.

All directives in RC 6.0 (?) + go to the ngModule, or otherwise assigned in parent component.

Thus in my app.module.ts

@NgModule({
  imports: [ BrowserModule, AppRouting ],
  declarations: [TrackScrollComponent],
  bootstrap: [ App ]
})

Implementing in your component then goes to yourcomponent.html or template as follows:


<div track-scroll> </div>

 Sorry for some of the imports I hadn't tested which one were exclusively needed for this howTo.

There is mentions about not working directly with ElementRef, but at the moment I wanted to provide clarity for solution as opposed to creating added confusion for something that really should be simple.

Oblivion

 Between the fascination of an upcoming pandemic ridden college football season, Taylor Swift, and Kim Kardashian, wildfires, crazier weathe...