diff --git a/index.html b/index.html
index 5dd1442..dd940fe 100644
--- a/index.html
+++ b/index.html
@@ -28,10 +28,10 @@
-
-
+
+
diff --git a/src/css/page.css b/src/css/page.css
index 86f8c6a..9cb222c 100644
--- a/src/css/page.css
+++ b/src/css/page.css
@@ -92,15 +92,5 @@
display: block;
}
-/*Koordinatenanzeige*/
-.gba-control-coordinates {
- background-color: rgb(250,250,250);
- background-color: rgba(250,250,250,0.8);
- text-align: center;
- box-shadow: 0 0 5px #bbb;
- padding: 0 5px;
- margin: 0;
- color: #333;
- font: 11px/1.500 'Open Sans', sans-serif;
-}
+
diff --git a/src/js/controls/Coordinates.css b/src/js/controls/Coordinates.css
new file mode 100644
index 0000000..4849fb6
--- /dev/null
+++ b/src/js/controls/Coordinates.css
@@ -0,0 +1,11 @@
+/*Koordinatenanzeige*/
+.gba-control-coordinates {
+ background-color: rgb(250,250,250);
+ background-color: rgba(250,250,250,0.8);
+ text-align: center;
+ box-shadow: 0 0 5px #bbb;
+ padding: 0 5px;
+ margin: 0;
+ color: #333;
+ font: 11px/1.500 'Open Sans', sans-serif;
+}
\ No newline at end of file
diff --git a/src/js/controls/Coordinates.js b/src/js/controls/Coordinates.js
index 36072b3..36fd6ea 100644
--- a/src/js/controls/Coordinates.js
+++ b/src/js/controls/Coordinates.js
@@ -5,7 +5,9 @@ import proj4 from 'proj4/dist/proj4';
import * as util from '../core/utilities';
import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera';
-class Coordinates extends Control {
+import './Coordinates.css';
+
+export class Coordinates extends Control {
options = {
position: 'bottomright',
@@ -110,5 +112,3 @@ class Coordinates extends Control {
}
}
-
-export { Coordinates };
\ No newline at end of file
diff --git a/src/js/controls/NorthArrow.css b/src/js/controls/NorthArrow.css
new file mode 100644
index 0000000..1609a38
--- /dev/null
+++ b/src/js/controls/NorthArrow.css
@@ -0,0 +1,53 @@
+#inset {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ border: none;
+ width: 120px;
+ height: 120px;
+ z-index: 9999999;
+}
+
+/* label */
+.label {
+ padding: 2px;
+ text-shadow: -1px -1px #FFF, 0 -1px #FFF, 1px -1px #FFF, -1px 0 #FFF, 1px 0 #FFF, -1px 1px #FFF, 0 1px #FFF, 1px 1px #FFF;
+ position: absolute;
+ pointer-events: none;
+}
+
+.red-label {
+ color: #f00;
+ padding: 2px;
+ text-shadow: -1px -1px #FFF, 0 -1px #FFF, 1px -1px #FFF, -1px 0 #FFF, 1px 0 #FFF, -1px 1px #FFF, 0 1px #FFF, 1px 1px #FFF;
+ position: absolute;
+ pointer-events: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
+
+.green-label {
+ color: #7cfc00;
+ padding: 2px;
+ text-shadow: -1px -1px #FFF, 0 -1px #FFF, 1px -1px #FFF, -1px 0 #FFF, 1px 0 #FFF, -1px 1px #FFF, 0 1px #FFF, 1px 1px #FFF;
+ position: absolute;
+ pointer-events: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
+
+.blue-label {
+ color: #00bfff;
+ padding: 2px;
+ text-shadow: -1px -1px #FFF, 0 -1px #FFF, 1px -1px #FFF, -1px 0 #FFF, 1px 0 #FFF, -1px 1px #FFF, 0 1px #FFF, 1px 1px #FFF;
+ position: absolute;
+ pointer-events: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
diff --git a/src/js/controls/NorthArrow.js b/src/js/controls/NorthArrow.js
new file mode 100644
index 0000000..b864666
--- /dev/null
+++ b/src/js/controls/NorthArrow.js
@@ -0,0 +1,214 @@
+import { Control } from "./Control";
+import { Group } from 'three/src/objects/Group';
+import { Vector3 } from 'three/src/math/Vector3';
+import { ArrowHelper } from 'three/src/helpers/ArrowHelper';
+import * as util from '../core/utilities';
+import * as dom from '../core/domUtil';
+import * as domEvent from '../core/domEvent';
+import { WebGLRenderer } from 'three/src/renderers/WebGLRenderer';
+import { Scene } from 'three/src/scenes/Scene';
+import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera';
+
+// import { SphereGeometry } from 'three/src/geometries/SphereGeometry';
+// import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial';
+// import { Mesh } from 'three/src/objects/Mesh';
+
+import './NorthArrow.css';
+
+export class NortArrow extends Control {
+
+ renderer;
+ _mainMap;
+ _scene;
+ _camera;
+ _center;
+ objectGroup;
+ labels = [];
+ options = {
+ position: 'bottomleft',
+ width: 120,
+ height: 120,
+ headLength: 1,
+ headWidth: 1,
+ };
+
+ constructor(options) {
+ super(options);
+
+ this.objectGroup = new Group();
+ this.objectGroup.visible = true;
+ util.setOptions(this, options);
+ }
+
+ onAdd(map) {
+ this._mainMap = map;
+ let container = this._container = dom.createDom("div", { "id": "inset", "class": "gba-control-minimap" });
+ this._container.style.width = this.options.width + 'px';
+ this._container.style.height = this.options.height + 'px';
+ domEvent.disableClickPropagation(this._container);
+ domEvent.on(this._container, 'mousewheel', domEvent.stopPropagation);
+
+ let renderer = this.renderer = new WebGLRenderer({ alpha: true });
+ renderer.setSize(120, 120);
+ // renderer.setSize(container.innerWidth, container.innerHeight);
+ container.appendChild(renderer.domElement);
+
+ this._scene = new Scene();
+ this._camera = new PerspectiveCamera(60, 1, 0.1, 1000);
+ this._camera.position.copy(map.camera.position);
+ this._camera.up = map.camera.up;
+ let center = this._center = new Vector3(0, 0, 0);
+ this._camera.lookAt(center);
+
+ // this._camera = map.camera.clone();
+ this._createArrow(this._scene);
+ this._buildLabels();
+ return container;
+ }
+
+ animate() {
+
+ this._camera.position.copy(this._mainMap.camera.position);
+ this._camera.position.setLength(18);
+ // this._camera.lookAt(this.options.center);
+ // this._camera.lookAt(this._mainMap.target);
+ this._camera.lookAt(this._scene.position);
+
+ this.renderer.render(this._scene, this._camera);
+ this._updateInsetLabelPositions();
+ }
+
+ _createArrow(app_scene) {
+ let from = new Vector3(0, 0, 0);
+ let headLength = 1;//this.options.headLength;//1;
+ let headWidth = this.options.headWidth;//1;
+
+ // let xTo = new Vector3(1, 0, 0);
+ let xTo = new Vector3(from.x + 1, from.y, from.z);
+ let xDirection = xTo.clone().sub(from);
+ this.objectGroup.add(new ArrowHelper(xDirection, from, 6, 0xf00000, headLength, headWidth)); // Red = x
+
+ // let yTo = new Vector3(0, 1, 0);
+ let yTo = new Vector3(from.x, from.y + 1, from.z);
+ let yDirection = yTo.clone().sub(from);
+ this.objectGroup.add(new ArrowHelper(yDirection, from, 6, 0x7cfc00, headLength, headWidth)); // Green = y
+
+ //let zTo = new Vector3(0, 0, 1);//blue z
+ let zTo = new Vector3(from.x, from.y, from.z + 1);
+ let zDirection = zTo.clone().sub(from);
+ this.objectGroup.add(new ArrowHelper(zDirection, from, 6, 0x00bfff, headLength, headWidth)); //8 is the length, Blue = z; 20 and 10 are head length and width
+
+ let opt = { r: 200, c: 0x38eeff, o: 0.8 };
+ // this._queryMarker = new Mesh(new SphereGeometry(opt.r),
+ // new MeshLambertMaterial({ color: opt.c, opacity: opt.o, transparent: false }));
+ // this._queryMarker.visible = true;
+ // this._queryMarker.position.set(0, 0, -1);
+
+ if (app_scene) {
+ app_scene.add(this.objectGroup);
+ }
+ }
+
+ _buildLabels() {
+
+ let f = [
+ { a: ["X"], cl: "red-label", centroid: [[7, 0, 0]] },
+ { a: ["Y"], cl: "green-label", centroid: [[0, 7, 0]] },
+ { a: ["Z"], cl: "blue-label", centroid: [[0, 0, 7]] }
+ ];
+
+ var zFunc, getPointsFunc = function (f) { return f.centroid; };
+
+
+ // create parent element for labels
+ var e = document.createElement("div");
+ this._container.appendChild(e);
+ e.style.display = (this.objectGroup.visible) ? "block" : "none";
+ let labelParentElement = e; //lable parent div for this layer
+
+ for (let i = 0, l = f.length; i < l; i++) {
+ var labelInfo = f[i];
+ // labelInfo.aElems = [];
+ // labelInfo.aObjs = [];
+ var text = labelInfo.a[0];
+ if (text === null || text === "") continue;
+
+ var classLabel = labelInfo.cl;
+ if (classLabel === undefined || classLabel === "") classLabel = "label";
+
+ //var horizontalShiftLabel = f.hs;
+ //if (horizontalShiftLabel === undefined || horizontalShiftLabel === "") horizontalShiftLabel = 0;
+
+ let pts = getPointsFunc(labelInfo);
+ for (let j = 0, m = pts.length; j < m; j++) {
+ let pt = pts[j];
+
+ // create div element for label
+ var e = document.createElement("div");
+ e.appendChild(document.createTextNode(text));
+ e.className = classLabel;// "label";
+ labelParentElement.appendChild(e);
+
+ var pt1 = new Vector3(pt[0], pt[1], pt[2]); // top
+
+ this.labels.push({ labelDiv: e, pt: pt1 });
+ }
+ }
+
+
+
+ }
+
+ _updateInsetLabelPositions() {
+ var widthHalf = this.options.width / 2;
+ var heightHalf = this.options.height / 2;
+ // var autosize = appSettings.Options.label.autoSize;
+ // var camera = app.camera2;
+ let camera_pos = this._camera.position;
+ let target = new Vector3(0, 0, 0);
+ let c2t = target.sub(camera_pos);
+ let c2l = new Vector3();
+ let v = new Vector3();
+
+ // make a list of [label index, distance to camera]
+ var idx_dist = [];
+ for (let i = 0, l = this.labels.length; i < l; i++) {
+ idx_dist.push([i, camera_pos.distanceTo(this.labels[i].pt)]);
+ }
+
+ // sort label indexes in descending order of distances
+ idx_dist.sort(function (a, b) {
+ if (a[1] < b[1]) return 1;
+ if (a[1] > b[1]) return -1;
+ return 0;
+ });
+
+ let label, labelDiv, x, y, dist, fontSize;
+ // var minFontSize = appSettings.Options.label.minFontSize;
+ for (let i = 0, l = idx_dist.length; i < l; i++) {
+ label = this.labels[idx_dist[i][0]];
+ labelDiv = label.labelDiv;
+ if (c2l.subVectors(label.pt, camera_pos).dot(c2t) > 0) {
+ // label is in front
+ // calculate label position
+ v.copy(label.pt);
+ v.project(this._camera);
+
+ x = (v.x * widthHalf) + widthHalf;
+ y = -(v.y * heightHalf) + heightHalf;
+
+ // set label position
+ labelDiv.style.display = "block";
+ labelDiv.style.left = (x - (labelDiv.offsetWidth / 2)) + "px";
+ labelDiv.style.top = (y - (labelDiv.offsetHeight / 2)) + "px";
+ labelDiv.style.zIndex = i + 1;
+
+ }
+ else {
+ // label is in back
+ labelDiv.style.display = "none";
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/js/core/Map.js b/src/js/core/Map.js
index 65664fd..9eaf209 100644
--- a/src/js/core/Map.js
+++ b/src/js/core/Map.js
@@ -15,6 +15,7 @@ class Map extends OrbitControls {
// call parent constructor of OrbitControls
super(size, center, camera, scene, domElement);
+ this.camera = camera;
this.container = container;
//init the control corners
diff --git a/src/js/core/browser.js b/src/js/core/browser.js
new file mode 100644
index 0000000..54bb844
--- /dev/null
+++ b/src/js/core/browser.js
@@ -0,0 +1,6 @@
+
+
+// @property pointer: Boolean
+// `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).
+export var pointer = !!(window.PointerEvent || msPointer);
+
diff --git a/src/js/core/domEvent.js b/src/js/core/domEvent.js
index 9f96e38..e196958 100644
--- a/src/js/core/domEvent.js
+++ b/src/js/core/domEvent.js
@@ -1,3 +1,6 @@
+import * as browser from '../core/browser';
+import * as util from '../core/utilities';
+
//static function
var stampForFn = (function () {
var lastId = 0,
@@ -74,6 +77,54 @@ export function addListener(obj, type, fn, context) { // (HTMLElement, String, F
// Alias to [`L.DomEvent.on`](#domevent-on)
export { addListener as on };
+
+function addOne(obj, type, fn, context) {
+
+
+ var id = type + util.stamp(fn) + (context ? '_' + util.stamp(context) : '');
+ var eventsKey = '_gba_' + type + id;
+
+ if (obj[eventsKey] && obj[eventsKey][id]) { return this; }
+
+ var handler = function (e) {
+ return fn.call(context || obj, e || window.event);
+ };
+
+ var originalHandler = handler;
+
+ if (browser.pointer && type.indexOf('touch') === 0) {
+ // Needs DomEvent.Pointer.js
+ addPointerListener(obj, type, handler, id);
+
+ } else if (browser.touch && (type === 'dblclick') && !browserFiresNativeDblClick()) {
+ addDoubleTapListener(obj, handler, id);
+
+ } else if ('addEventListener' in obj) {
+
+ if (type === 'touchstart' || type === 'touchmove' || type === 'wheel' || type === 'mousewheel') {
+ obj.addEventListener(mouseSubst[type] || type, handler, Browser.passiveEvents ? {passive: false} : false);
+
+ } else if (type === 'mouseenter' || type === 'mouseleave') {
+ handler = function (e) {
+ e = e || window.event;
+ if (isExternalTarget(obj, e)) {
+ originalHandler(e);
+ }
+ };
+ obj.addEventListener(mouseSubst[type], handler, false);
+
+ } else {
+ obj.addEventListener(type, originalHandler, false);
+ }
+
+ } else if ('attachEvent' in obj) {
+ obj.attachEvent('on' + type, handler);
+ }
+
+ obj[eventsKey] = obj[eventsKey] || {};
+ obj[eventsKey][id] = handler;
+}
+
export function removeListener(obj, type, fn) { // (HTMLElement, String, Function)
var id = stampForFn(fn);
@@ -81,13 +132,7 @@ export function removeListener(obj, type, fn) { // (HTMLElement, String, Functi
var handler = obj[key];
if (!handler) { return this; }
-
- //if (L.Browser.pointer && type.indexOf('touch') === 0) {
- // this.removePointerListener(obj, type, id);
- //} else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) {
- // this.removeDoubleTapListener(obj, id);
-
- //} else if ('removeEventListener' in obj) {
+
if ('removeEventListener' in obj) {
if (type === 'mousewheel') {
obj.removeEventListener('DOMMouseScroll', handler, false);
@@ -137,6 +182,16 @@ export function stopPropagation(e) {
return this;
}
+
+// @function disableClickPropagation(el: HTMLElement): this
+// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,
+// `'mousedown'` and `'touchstart'` events (plus browser variants).
+export function disableClickPropagation(el) {
+ addListener(el, 'mousedown touchstart dblclick', stopPropagation);
+ addOne(el, 'click', fakeStop);
+ return this;
+}
+
export function preventDefault(e) {
if (e.preventDefault) {
@@ -149,9 +204,22 @@ export function preventDefault(e) {
var skipEvents = {};
+export function fakeStop(e) {
+ // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)
+ skipEvents[e.type] = true;
+}
export function skipped(e) {
var skipped = skipEvents[e.type];
// reset when checking, as it's only used in map container and propagates outside of the map
skipEvents[e.type] = false;
return skipped;
-}
\ No newline at end of file
+}
+
+
+// @function stop(ev: DOMEvent): this
+// // Does `stopPropagation` and `preventDefault` at the same time.
+// export function stop(e) {
+// preventDefault(e);
+// stopPropagation(e);
+// return this;
+// }
\ No newline at end of file
diff --git a/src/js/core/utilities.js b/src/js/core/utilities.js
index 8d32312..86517ac 100644
--- a/src/js/core/utilities.js
+++ b/src/js/core/utilities.js
@@ -155,3 +155,14 @@ export function stamp (obj){
return obj[key];
}
+
+export function hasTouch () {
+ var phantomjs = navigator.userAgent.toLowerCase().indexOf('phantom') !== -1;
+
+ var isTouchDevice = phantomjs
+ || 'ontouchstart' in window
+ || (window.DocumentTouch && document instanceof window.DocumentTouch)
+ || ("onpointerdown" in document && navigator.maxTouchPoints > 0)
+ || window.navigator.msMaxTouchPoints;
+ return isTouchDevice;
+}
diff --git a/src/js/main.js b/src/js/main.js
index 66259db..7c87c7e 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -8,6 +8,7 @@ import { TinLayer } from './layer/TinLayer';
import { Map } from './core/Map';
import * as domEvent from './core/domEvent';
import { Coordinates } from './controls/Coordinates';
+import { NortArrow } from './controls/NorthArrow';
import { Mesh } from 'three/src/objects/Mesh';
import { SphereGeometry } from 'three/src/geometries/SphereGeometry';
import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial';
@@ -87,7 +88,7 @@ class Application {
let x = { min: 3955850, max: 4527300, avg: 4282010 };
let y = { min: 2183600, max: 2502700, avg: 2302070 };
let z = { min: -60066, max: 3574.94, avg: -13616.3 };
- const center = new Vector3(x.avg, y.avg, z.avg);
+ const center = new Vector3(x.avg, y.avg, 1000);
const size = Math.max(x.max - x.min, y.max - y.min, z.max - z.min);
const camDirection = new Vector3(-0.5, -Math.SQRT1_2, 0.5);
const camOffset = camDirection.multiplyScalar(size * 2);
@@ -98,16 +99,18 @@ class Application {
this.camera.updateProjectionMatrix();
// create map
- this.map = new Map(size, center, this.camera, this.scene, this.renderer.domElement, this.container);
- // this.map.target = center;
+ this.map = new Map(size, center, this.camera, this.scene, this.renderer.domElement, this.container);
// this.map.minDistance = size*0.75;
// this.map.maxDistance = size*15;
+
+ //add map controls:
let coordinates = new Coordinates({ camera: this.camera, crs: "EPSG:3034" }).addTo(this.map);
// coordinates.addListener('onPoint', (vector) => {
// this.queryMarker.position.set(vector.x, vector.y, vector.z);
- // this.queryMarker.updateMatrixWorld();
+ // // this.queryMarker.updateMatrixWorld();
// this.animate();
// }, this);
+ this.northArrow = new NortArrow({ headLength: 1, headWidth: 1 }).addTo(this.map);
let dxf134Layer = new TinLayer({
geomId: 134, q: true, type: "3dface", name: "South Alpine Superunit", description: "test", color: "907A5C"
@@ -225,13 +228,9 @@ class Application {
animate() {
this.renderer.render(this.scene, this.camera);
+ this.northArrow.animate();
}
}
var container = document.getElementById("webgl");
new Application(container);
-// app.add(new BoxLayer({
-// width: 10,
-// height: 10,
-// depth: 10
-// }));
\ No newline at end of file