- Coordinates control: styleing in extra file

- NorthArrow control
- add browser utilities
This commit is contained in:
Arno Kaimbacher 2020-11-25 17:19:26 +01:00
parent 6315458d51
commit 7b1ca85519
11 changed files with 387 additions and 34 deletions

View File

@ -28,10 +28,10 @@
<body> <body>
<div id="webgl" class="mapDesktop"> <div id="webgl" class="mapDesktop">
<div id="inset"></div> <!-- <div id="inset"></div> -->
<div id="progressArea"> <!-- <div id="progressArea">
<img id="loadingImg" alt="" src="images/map/loading.gif" style="display:none;" /> <img id="loadingImg" alt="" src="images/map/loading.gif" style="display:none;" />
</div> </div> -->
</div> </div>
<script src="dist/main.js"></script> <script src="dist/main.js"></script>

View File

@ -92,15 +92,5 @@
display: block; 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;
}

View File

@ -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;
}

View File

@ -5,7 +5,9 @@ import proj4 from 'proj4/dist/proj4';
import * as util from '../core/utilities'; import * as util from '../core/utilities';
import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera'; import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera';
class Coordinates extends Control { import './Coordinates.css';
export class Coordinates extends Control {
options = { options = {
position: 'bottomright', position: 'bottomright',
@ -110,5 +112,3 @@ class Coordinates extends Control {
} }
} }
export { Coordinates };

View File

@ -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;
}

View File

@ -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";
}
}
}
}

View File

@ -15,6 +15,7 @@ class Map extends OrbitControls {
// call parent constructor of OrbitControls // call parent constructor of OrbitControls
super(size, center, camera, scene, domElement); super(size, center, camera, scene, domElement);
this.camera = camera;
this.container = container; this.container = container;
//init the control corners //init the control corners

6
src/js/core/browser.js Normal file
View File

@ -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);

View File

@ -1,3 +1,6 @@
import * as browser from '../core/browser';
import * as util from '../core/utilities';
//static function //static function
var stampForFn = (function () { var stampForFn = (function () {
var lastId = 0, var lastId = 0,
@ -74,6 +77,54 @@ export function addListener(obj, type, fn, context) { // (HTMLElement, String, F
// Alias to [`L.DomEvent.on`](#domevent-on) // Alias to [`L.DomEvent.on`](#domevent-on)
export { addListener as 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) export function removeListener(obj, type, fn) { // (HTMLElement, String, Function)
var id = stampForFn(fn); var id = stampForFn(fn);
@ -82,12 +133,6 @@ export function removeListener(obj, type, fn) { // (HTMLElement, String, Functi
if (!handler) { return this; } 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 ('removeEventListener' in obj) {
if (type === 'mousewheel') { if (type === 'mousewheel') {
obj.removeEventListener('DOMMouseScroll', handler, false); obj.removeEventListener('DOMMouseScroll', handler, false);
@ -137,6 +182,16 @@ export function stopPropagation(e) {
return this; 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) { export function preventDefault(e) {
if (e.preventDefault) { if (e.preventDefault) {
@ -149,9 +204,22 @@ export function preventDefault(e) {
var skipEvents = {}; 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) { export function skipped(e) {
var skipped = skipEvents[e.type]; var skipped = skipEvents[e.type];
// reset when checking, as it's only used in map container and propagates outside of the map // reset when checking, as it's only used in map container and propagates outside of the map
skipEvents[e.type] = false; skipEvents[e.type] = false;
return skipped; return skipped;
} }
// @function stop(ev: DOMEvent): this
// // Does `stopPropagation` and `preventDefault` at the same time.
// export function stop(e) {
// preventDefault(e);
// stopPropagation(e);
// return this;
// }

View File

@ -155,3 +155,14 @@ export function stamp (obj){
return obj[key]; 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;
}

View File

@ -8,6 +8,7 @@ import { TinLayer } from './layer/TinLayer';
import { Map } from './core/Map'; import { Map } from './core/Map';
import * as domEvent from './core/domEvent'; import * as domEvent from './core/domEvent';
import { Coordinates } from './controls/Coordinates'; import { Coordinates } from './controls/Coordinates';
import { NortArrow } from './controls/NorthArrow';
import { Mesh } from 'three/src/objects/Mesh'; import { Mesh } from 'three/src/objects/Mesh';
import { SphereGeometry } from 'three/src/geometries/SphereGeometry'; import { SphereGeometry } from 'three/src/geometries/SphereGeometry';
import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial'; import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial';
@ -87,7 +88,7 @@ class Application {
let x = { min: 3955850, max: 4527300, avg: 4282010 }; let x = { min: 3955850, max: 4527300, avg: 4282010 };
let y = { min: 2183600, max: 2502700, avg: 2302070 }; let y = { min: 2183600, max: 2502700, avg: 2302070 };
let z = { min: -60066, max: 3574.94, avg: -13616.3 }; 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 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 camDirection = new Vector3(-0.5, -Math.SQRT1_2, 0.5);
const camOffset = camDirection.multiplyScalar(size * 2); const camOffset = camDirection.multiplyScalar(size * 2);
@ -99,15 +100,17 @@ class Application {
// create map // create map
this.map = new Map(size, center, this.camera, this.scene, this.renderer.domElement, this.container); this.map = new Map(size, center, this.camera, this.scene, this.renderer.domElement, this.container);
// this.map.target = center;
// this.map.minDistance = size*0.75; // this.map.minDistance = size*0.75;
// this.map.maxDistance = size*15; // this.map.maxDistance = size*15;
//add map controls:
let coordinates = new Coordinates({ camera: this.camera, crs: "EPSG:3034" }).addTo(this.map); let coordinates = new Coordinates({ camera: this.camera, crs: "EPSG:3034" }).addTo(this.map);
// coordinates.addListener('onPoint', (vector) => { // coordinates.addListener('onPoint', (vector) => {
// this.queryMarker.position.set(vector.x, vector.y, vector.z); // this.queryMarker.position.set(vector.x, vector.y, vector.z);
// this.queryMarker.updateMatrixWorld(); // // this.queryMarker.updateMatrixWorld();
// this.animate(); // this.animate();
// }, this); // }, this);
this.northArrow = new NortArrow({ headLength: 1, headWidth: 1 }).addTo(this.map);
let dxf134Layer = new TinLayer({ let dxf134Layer = new TinLayer({
geomId: 134, q: true, type: "3dface", name: "South Alpine Superunit", description: "test", color: "907A5C" geomId: 134, q: true, type: "3dface", name: "South Alpine Superunit", description: "test", color: "907A5C"
@ -225,13 +228,9 @@ class Application {
animate() { animate() {
this.renderer.render(this.scene, this.camera); this.renderer.render(this.scene, this.camera);
this.northArrow.animate();
} }
} }
var container = document.getElementById("webgl"); var container = document.getElementById("webgl");
new Application(container); new Application(container);
// app.add(new BoxLayer({
// width: 10,
// height: 10,
// depth: 10
// }));