@h21-map/google-zoom-box
Version:
A library of Google Map JS API
246 lines (203 loc) • 8.91 kB
JavaScript
var ZoomBox = function () {
try {
google;
} catch (e) {
throw Error('Google Map JS API is not ready yet!');
}
this.extend(ZoomBox, google.maps.OverlayView);
this.opts = {
zoomType: 0,
strokeWeight: 1,
};
this._isOpen = true;
this._fDiv = null;
this._div = null;
}
ZoomBox.prototype.extend = function (obj1, obj2) {
return (function (object) {
var property;
for (property in object.prototype) {
this.prototype[property] = object.prototype[property];
}
return this;
}).apply(obj1, [obj2]);
};
ZoomBox.prototype._bind = function () {
var me = this;
if (!me._isOpen) {
return;
}
};
ZoomBox.prototype.onAdd = function () {
var me = this;
me._map = this.getMap();
me.mousem = null;
me.mouseup = null;
this._isOpen = true;
if (!this._div) {
let div = this.container = document.createElement('div');
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
let size = {}
size.width = me._map.getDiv().offsetWidth;
size.height = me._map.getDiv().offsetHeight;
div.style.cssText = "z-index: 1; position:absolute; width:" + size.width + "px;height:" + size.height + "px";
this.getPanes().overlayMouseTarget.appendChild(div);
this._div = div;
}
let beginDrawRect = function (e) {
e = window.event || e;
if (e.button != 2) { return; }
if (!me._isOpen) { return; }
me._bind.isZooming = true;
this._isBeginDrawBinded = true;
me._bind.mx = e.layerX || e.offsetX || 0;
me._bind.my = e.layerY || e.offsetY || 0;
me._bind.ix = e.pageX || e.clientX || 0;
me._bind.iy = e.pageY || e.clientY || 0;
if (!me._fDiv) {
me._fDiv = document.createElement("div");
me._fDiv.style.opacity = 0.69;
me._fDiv.style.backgroundColor = "#a5b8e35e";
me._fDiv.style.cursor = "crosshair";
me._fDiv.style.zIndex = 999999;
me._fDiv.style.position = 'absolute';
me._fDiv.style.width = 0;
me._fDiv.style.height = 0;
me._fDiv.style.border = " 2px solid #0051FF";
me._map.getDiv().appendChild(me._fDiv);
me._fDiv.style.width = "0";
me._fDiv.style.height = "0";
me._fDiv.style.left = me._bind.mx + "px";
me._fDiv.style.top = me._bind.my + "px";
me.mousem = google.maps.event.addDomListener(me._map.getDiv(), "mousemove", drawingRect);
me.mouseup = google.maps.event.addDomListener(me._map.getDiv(), "mouseup", endDrawRect);
}
};
let drawingRect = function (e) {
if (me._isOpen == true && me._bind.isZooming == true) {
var e = window.event || e;
var curX = e.pageX || e.clientX || 0;
var curY = e.pageY || e.clientY || 0;
var dx = me._bind.dx = curX - me._bind.ix;
var dy = me._bind.dy = curY - me._bind.iy;
var tw = Math.abs(dx) - me.opts.strokeWeight;
var th = Math.abs(dy) - me.opts.strokeWeight;
me._fDiv.style.width = (tw < 0 ? 0 : tw) + "px";
me._fDiv.style.height = (th < 0 ? 0 : th) + "px";
var mapSize = [me._map.getDiv().clientWidth, me._map.getDiv().clientHeight];
if (dx >= 0) {
me._fDiv.style.right = "auto";
me._fDiv.style.left = me._bind.mx + "px";
if (me._bind.mx + dx >= mapSize[0] - 2 * me.opts.strokeWeight) {
me._fDiv.style.width = mapSize[0] - me._bind.mx - 2 * me.opts.strokeWeight + "px";
}
} else {
me._fDiv.style.left = "auto";
me._fDiv.style.right = mapSize[0] - me._bind.mx + "px";
if (me._bind.mx + dx <= 2 * me.opts.strokeWeight) {
me._fDiv.style.width = me._bind.mx - 2 * me.opts.strokeWeight + "px";
}
}
if (dy >= 0) {
me._fDiv.style.bottom = "auto";
me._fDiv.style.top = me._bind.my + "px";
if (me._bind.my + dy >= mapSize[1] - 2 * me.opts.strokeWeight) {
me._fDiv.style.height = mapSize[1] - me._bind.my - 2 * me.opts.strokeWeight + "px";
}
} else {
me._fDiv.style.top = "auto";
me._fDiv.style.bottom = mapSize[1] - me._bind.my + "px";
if (me._bind.my + dy <= 2 * me.opts.strokeWeight) {
me._fDiv.style.height = me._bind.my - 2 * me.opts.strokeWeight + "px";
}
}
}
};
let endDrawRect = function () {
if (me._isOpen == true) {
google.maps.event.removeListener(me.mousem);
google.maps.event.removeListener(me.mouseup);
var centerX = parseInt(me._fDiv.style.left) + parseInt(me._fDiv.style.width) / 2;
var centerY = parseInt(me._fDiv.style.top) + parseInt(me._fDiv.style.height) / 2;
var mapSize = [me._map.getDiv().clientWidth, me._map.getDiv().clientHeight];
if (isNaN(centerX)) {
centerX = mapSize[0] - parseInt(me._fDiv.style.right) - parseInt(me._fDiv.style.width) / 2;
}
if (isNaN(centerY)) {
centerY = mapSize[1] - parseInt(me._fDiv.style.bottom) - parseInt(me._fDiv.style.height) / 2;
}
var ratio = Math.min(mapSize[0] / Math.abs(me._bind.dx), mapSize[1] / Math.abs(me._bind.dy));
ratio = Math.floor(ratio);
delete me._bind.dx;
delete me._bind.dy;
delete me._bind.ix;
delete me._bind.iy;
if (!isNaN(ratio)) {
targetZoomLv = Math.round(me._map.getZoom() + (Math.log(ratio) / Math.log(2)));
if (targetZoomLv < me._map.getZoom()) {
targetZoomLv = me._map.getZoom();
}
} else {
targetZoomLv = me._map.getZoom() + (me.opts.zoomType == 0 ? 1 : -1);
}
var ne = me._map.getBounds().getNorthEast();
var sw = me._map.getBounds().getSouthWest();
var projection = me._map.getProjection();
var topRight = projection.fromLatLngToPoint(ne);
var bottomLeft = projection.fromLatLngToPoint(sw);
var scale = 1 << me._map.getZoom();
var newLatlng = projection.fromPointToLatLng(new google.maps.Point(centerX / scale + bottomLeft.x, centerY / scale + topRight.y));
if(ratio < 450){
me._map.setCenter(newLatlng);
me._map.setZoom(targetZoomLv);
}
me._bind.isZooming = false;
me._map.setOptions({
draggable: true,
draggableCursor: 'default',
});
me._fDiv.parentNode.removeChild(me._fDiv);
me._fDiv = null;
}
rect = null;
};
if (!this._isBeginDrawBinded) {
google.maps.event.addDomListener(me._div, "mousedown", (e) => {
if (e.which === 3) {
this._isBeginDrawBinded = true;
document.oncontextmenu = function () { return false };
google.maps.event.clearListeners(me._map.getDiv(), 'mousemove');
me._map.setOptions({
draggable: false,
draggableCursor: 'crosshair'
});
beginDrawRect(e);
}
});
}
};
ZoomBox.prototype.draw = function () {
const bounds = this.getMap().getBounds();
const projection = this.getProjection();
const topRight = projection.fromLatLngToDivPixel(bounds.getNorthEast());
const bottomLeft = projection.fromLatLngToDivPixel(bounds.getSouthWest());
this.container.width = Math.round(topRight.x - bottomLeft.x) + "px";
this.container.style.height = Math.round(bottomLeft.y - topRight.y) + "px";
this.container.style.left = bottomLeft.x + "px";
this.container.style.top = topRight.y + "px";
};
ZoomBox.prototype.onRemove = function () {
me = this;
if (!this._isOpen) {
return;
}
me._div.parentNode.removeChild(me._div);
me._div = null;
google.maps.event.clearListeners(me._map.getDiv(), 'mousemove');
google.maps.event.clearListeners(me._map.getDiv(), 'mousedown');
};
if (typeof module == 'object') {
module.exports = { default: ZoomBox, ZoomBox: ZoomBox };
};