gars_v2
Version:
Geo Assistant Research System
185 lines (167 loc) • 5.95 kB
JavaScript
import Data from './data';
import fileUrl from 'file-url';
class Map {
constructor($parent) {
// wrap the absolute positioned $view to enable areaselector on $img
var $view = $('<div>').addClass('view').appendTo($parent);
var $img = $('<img>').addClass('img').appendTo($view);
var mc = new window.Hammer.Manager($view.get(0));
var pinch = new window.Hammer.Pinch();
var pan = new window.Hammer.Pan();
mc.add([pinch, pan]);
this.mc = mc;
this.$view = $view;
this.$img = $img;
this.loaded = false;
this.$parent = $parent;
$(window).resize(() => this.updateViewport());
this.start();
}
start() {
var panX, panY;
this.mc.on('panstart', () => {
panX = panY = 0;
});
this.mc.on("panmove", ev => {
console.log('panmove', ev);
var x = ev.deltaX - panX;
var y = ev.deltaY - panY;
this.translate(x, y);
panX = ev.deltaX;
panY = ev.deltaY;
});
var initScale;
this.mc.on("pinchstart", ev => {
console.log('pinchstart', ev);
initScale = this.scale;
});
this.mc.on("pinch", ev => {
console.log('pinch', ev);
this.zoom(initScale * ev.scale, ev.center.x, ev.center.y);
});
this.$view.on('wheel', e => {
console.log('wheel', e);
e = e.originalEvent;
if (e.wheelDelta === 0) return;
var scale = e.wheelDelta > 0 ? 0.05 : -0.05;
this.zoom(this.scale * (1 + scale), e.pageX, e.pageY);
});
}
stop() {
this.mc.off('panstart panmove pinchstart pinch');
this.$view.off('wheel');
}
updateViewport() {
var $parent = this.$parent;
this.parentWidth = $parent.width();
this.parentHeight = $parent.height();
if (this.width !== undefined) {
this.maxScale = 10;
this.minScale = Math.min(
this.parentWidth / this.width,
this.parentHeight / this.height
);
this.applyTransform();
}
}
zoom(scale, x2parent, y2parent) {
// do normalization
scale = limit(scale, this.minScale, this.maxScale);
x2parent = (x2parent === undefined) ? this.parentWidth / 2 : x2parent;
y2parent = (y2parent === undefined) ? this.parentHeight / 2 : y2parent;
console.log('zooming', scale, 'from x:', x2parent, 'y:', y2parent);
var x2img = x2parent - this.x;
var y2img = y2parent - this.y;
this.x -= x2img * (scale - this.scale) / this.scale;
this.y -= y2img * (scale - this.scale) / this.scale;
this.scale = scale;
this.applyTransform();
}
translate(x, y) {
this.x += x;
this.y += y;
this.applyTransform();
}
applyTransform() {
var x = this.x,
y = this.y,
s = this.scale;
s = limit(s, this.minScale, this.maxScale);
x = limit(x, this.parentWidth - this.width * s, 0);
y = limit(y, this.parentHeight - this.height * s, 0);
this.setSize(s * this.width, s * this.height);
this.setPosition(x, y);
this.scale = s;
this.x = x;
this.y = y;
}
setPosition(x, y) {
this.$view.css('left', `${x}px`);
this.$view.css('top', `${y}px`);
}
setSize(width, height) {
this.$img.css('width', `${width}px`);
this.$img.css('height', `${height}px`);
}
open(filepath) {
var url = fileUrl(filepath);
var $spin = $('<i>').addClass('fa fa-spin fa-cog').insertBefore(this.$view);
console.log('loading image:', url);
this.$img.attr('src', url);
this.loaded = false;
loadImage(filepath).then(({ width, height }) => {
console.log('image loaded, width:', width, 'height', height);
$spin.remove();
this.setSize(width, height);
this.loaded = true;
this.width = width;
this.height = height;
this.x = 0;
this.y = 0;
this.scale = 1;
this.updateViewport(); // sets minscale
this.zoom(this.minScale);
});
var data = new Data();
var datapath = filepath.replace(/\..+/, '.gars');
console.log('loading map data from', datapath);
return data.read(datapath).then(() => data);
}
reopen(filepath) {
var url = fileUrl(filepath);
console.log('loading image:', url);
var widthSav = this.width;
var heightSav = this.height;
this.$img.attr('src', url);
this.loaded = false;
loadImage(filepath).then(({ width, height }) => {
console.log('image loaded, width:', width, 'height', height);
this.setSize(widthSav, heightSav);
this.loaded = true;
this.width = widthSav;
this.height = heightSav;
this.updateViewport(); // sets minscale
});
var data = new Data();
var datapath = filepath.replace(/\..+/, '.gars');
console.log('loading map data from', datapath);
return data.read(datapath).then(() => data);
}
onclose() {}
}
function loadImage(src) {
var image = new Image();
image.src = src;
return new Promise(function(resolve) {
image.onload = function() {
resolve({
width: image.width,
height: image.height
});
};
});
}
function limit(x, lower, upper) {
return Math.min(upper, Math.max(lower, x));
}
export default Map;