-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract Transform from Viewport into its own class
several things going on here: - Added a lot more checking for valid values - Transform as a class lets you do things like `instanceof Transform` - I wanted to add `.v` properties to both Viewport and Transform, this is an automatic incrementing version number that can be used to tell if something has changed. It will let us skip expensive steps like tiling if the viewport is the same as before. - This also marks a shift from the old idiomatic D3-style getter/setter methods to new ES6 class getters and setters. The old way where the same function does both things is worse for code optimization and type safety.
- Loading branch information
Showing
9 changed files
with
556 additions
and
289 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/** | ||
* 🕹️ Transform module | ||
* @module | ||
*/ | ||
|
||
import { TAU, MIN_K, MAX_K } from './constants'; | ||
import { numClamp, numWrap } from './number'; | ||
import { geoScaleToZoom, geoZoomToScale } from './geo'; | ||
import { Vec2 } from './vector'; | ||
|
||
|
||
/** `Transform` is a class for dealing with transform data | ||
* `x`,`y` - translation, (from origin coordinate [0,0], to top-left screen coordinate) | ||
* `k` - scale, (related to the map zoom, how many Mercator coordinates the world contains) | ||
* `r` - rotation, optionally applied post-projection to change the map bearing away from north-up | ||
*/ | ||
|
||
export class Transform { | ||
public x: number = 0; | ||
public y: number = 0; | ||
public k: number = 256 / Math.PI; // z1 | ||
public r: number = 0; | ||
private _v: number = 1; | ||
|
||
|
||
/** Constructs a new Transform | ||
* @param other | ||
*/ | ||
constructor(other?: Transform) { | ||
if (other) { | ||
this.props = other; | ||
} | ||
} | ||
|
||
|
||
/** version | ||
*/ | ||
get v(): number { | ||
return this._v; | ||
} | ||
set v(val: number) { | ||
this._v = val; | ||
} | ||
|
||
|
||
/** translation factor | ||
*/ | ||
get translation(): Vec2 { | ||
return [this.x, this.y]; | ||
} | ||
set translation(val: Vec2) { | ||
this.props = { x: val[0], y: val[1] }; | ||
} | ||
|
||
|
||
/** scale factor | ||
*/ | ||
get scale(): number { | ||
return this.k; | ||
} | ||
set scale(val: number) { | ||
const k = numClamp(+val, MIN_K, MAX_K); // constrain to z0..z24 | ||
this.props = { k: val }; | ||
} | ||
|
||
|
||
/** zoom factor | ||
* zoom is related to scale | ||
*/ | ||
get zoom(): number { | ||
return geoScaleToZoom(this.k); | ||
} | ||
set zoom(val: number) { | ||
this.props = { k: geoZoomToScale(+val) }; | ||
} | ||
|
||
|
||
/** rotation factor | ||
*/ | ||
get rotation(): number { | ||
return this.r; | ||
} | ||
set rotation(val: number) { | ||
this.props = { r: val }; | ||
} | ||
|
||
|
||
/** | ||
*/ | ||
get props(): Object { | ||
return { x: this.x, y: this.y, k: this.k, r: this.r }; | ||
} | ||
set props(val: any) { | ||
let changed = false; | ||
|
||
if (val.x !== undefined && val.x !== null) { | ||
const x = +val.x; | ||
if (!isNaN(x) && isFinite(x) && this.x !== x) { | ||
this.x = x; | ||
changed = true; | ||
} | ||
} | ||
|
||
if (val.y !== undefined && val.y !== null) { | ||
const y = +val.y; | ||
if (!isNaN(y) && isFinite(y) && this.y !== y) { | ||
this.y = y; | ||
changed = true; | ||
} | ||
} | ||
|
||
if (val.k !== undefined && val.k !== null) { | ||
let k = +val.k; | ||
if (!isNaN(k) && isFinite(k)) { | ||
k = numClamp(k, MIN_K, MAX_K); // constrain to z0..z24 | ||
if (this.k !== k) { | ||
this.k = k; | ||
changed = true; | ||
} | ||
} | ||
} | ||
|
||
if (val.r !== undefined && val.r !== null) { | ||
let r = +val.r; | ||
if (!isNaN(r) && isFinite(r)) { | ||
r = numWrap(r, 0, TAU); // wrap to 0..2π | ||
if (this.r !== r) { | ||
this.r = r; | ||
changed = true; | ||
} | ||
} | ||
} | ||
|
||
if (changed) { | ||
this.v++; | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.