minor code cleanup, more destructive point operations

This commit is contained in:
mourner 2012-08-10 22:40:55 +03:00
parent 7627d39700
commit 8980f2d224
10 changed files with 91 additions and 59 deletions

View File

@ -1,5 +1,5 @@
/* /*
* L.DomUtil contains various utility functions for working with DOM * L.DomUtil contains various utility functions for working with DOM.
*/ */
L.DomUtil = { L.DomUtil = {
@ -8,46 +8,49 @@ L.DomUtil = {
}, },
getStyle: function (el, style) { getStyle: function (el, style) {
var value = el.style[style]; var value = el.style[style];
if (!value && el.currentStyle) { if (!value && el.currentStyle) {
value = el.currentStyle[style]; value = el.currentStyle[style];
} }
if (!value || value === 'auto') { if (!value || value === 'auto') {
var css = document.defaultView.getComputedStyle(el, null); var css = document.defaultView.getComputedStyle(el, null);
value = css ? css[style] : null; value = css ? css[style] : null;
} }
return (value === 'auto' ? null : value);
return value === 'auto' ? null : value;
}, },
getViewportOffset: function (element) { getViewportOffset: function (element) {
var top = 0, var top = 0,
left = 0, left = 0,
el = element, el = element,
docBody = document.body; docBody = document.body,
pos;
do { do {
top += el.offsetTop || 0; top += el.offsetTop || 0;
left += el.offsetLeft || 0; left += el.offsetLeft || 0;
pos = L.DomUtil.getStyle(el, 'position');
if (el.offsetParent === docBody && if (el.offsetParent === docBody && pos === 'absolute') { break; }
L.DomUtil.getStyle(el, 'position') === 'absolute') {
break; if (pos === 'fixed') {
}
if (L.DomUtil.getStyle(el, 'position') === 'fixed') {
top += docBody.scrollTop || 0; top += docBody.scrollTop || 0;
left += docBody.scrollLeft || 0; left += docBody.scrollLeft || 0;
break; break;
} }
el = el.offsetParent; el = el.offsetParent;
} while (el); } while (el);
el = element; el = element;
do { do {
if (el === docBody) { if (el === docBody) { break; }
break;
}
top -= el.scrollTop || 0; top -= el.scrollTop || 0;
left -= el.scrollLeft || 0; left -= el.scrollLeft || 0;
@ -59,15 +62,19 @@ L.DomUtil = {
}, },
create: function (tagName, className, container) { create: function (tagName, className, container) {
var el = document.createElement(tagName); var el = document.createElement(tagName);
el.className = className; el.className = className;
if (container) { if (container) {
container.appendChild(el); container.appendChild(el);
} }
return el; return el;
}, },
disableTextSelection: function () { disableTextSelection: function () {
if (document.selection && document.selection.empty) { if (document.selection && document.selection.empty) {
document.selection.empty(); document.selection.empty();
} }
@ -94,12 +101,12 @@ L.DomUtil = {
}, },
removeClass: function (el, name) { removeClass: function (el, name) {
function replaceFn(w, match) { function replaceFn(w, match) {
if (match === name) { if (match === name) { return ''; }
return '';
}
return w; return w;
} }
el.className = el.className el.className = el.className
.replace(/(\S+)\s*/g, replaceFn) .replace(/(\S+)\s*/g, replaceFn)
.replace(/(^\s+|\s+$)/, ''); .replace(/(^\s+|\s+$)/, '');
@ -130,6 +137,7 @@ L.DomUtil = {
}, },
testProp: function (props) { testProp: function (props) {
var style = document.documentElement.style; var style = document.documentElement.style;
for (var i = 0; i < props.length; i++) { for (var i = 0; i < props.length; i++) {
@ -141,7 +149,7 @@ L.DomUtil = {
}, },
getTranslateString: function (point) { getTranslateString: function (point) {
// On webkit browsers (Chrome/Safari/MobileSafari/Android) using translate3d instead of translate // on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate
// makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care // makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care
// (same speed either way), Opera 12 doesn't support translate3d // (same speed either way), Opera 12 doesn't support translate3d
@ -153,6 +161,7 @@ L.DomUtil = {
}, },
getScaleString: function (scale, origin) { getScaleString: function (scale, origin) {
var preTranslateStr = L.DomUtil.getTranslateString(origin), var preTranslateStr = L.DomUtil.getTranslateString(origin),
scaleStr = ' scale(' + scale + ') ', scaleStr = ' scale(' + scale + ') ',
postTranslateStr = L.DomUtil.getTranslateString(origin.multiplyBy(-1)); postTranslateStr = L.DomUtil.getTranslateString(origin.multiplyBy(-1));
@ -160,8 +169,10 @@ L.DomUtil = {
return preTranslateStr + scaleStr + postTranslateStr; return preTranslateStr + scaleStr + postTranslateStr;
}, },
setPosition: function (el, point, disable3D) { setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean])
el._leaflet_pos = point; el._leaflet_pos = point;
if (!disable3D && L.Browser.any3d) { if (!disable3D && L.Browser.any3d) {
el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point); el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point);
@ -176,14 +187,21 @@ L.DomUtil = {
}, },
getPosition: function (el) { getPosition: function (el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance
return el._leaflet_pos; return el._leaflet_pos;
} }
}; };
L.Util.extend(L.DomUtil, {
TRANSITION: L.DomUtil.testProp(['transition', 'webkitTransition', 'OTransition', 'MozTransition', 'msTransition']),
TRANSFORM: L.DomUtil.testProp(['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform'])
});
L.DomUtil.TRANSITION_END = (L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ? // prefix style property names
L.DomUtil.TRANSITION + 'End' : 'transitionend');
L.DomUtil.TRANSFORM = L.DomUtil.testProp(
['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
L.DomUtil.TRANSITION = L.DomUtil.testProp(
['transition', 'webkitTransition', 'OTransition', 'MozTransition', 'msTransition']);
L.DomUtil.TRANSITION_END =
L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ?
L.DomUtil.TRANSITION + 'End' : 'transitionend';

View File

@ -8,10 +8,17 @@ L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) {
}; };
L.Point.prototype = { L.Point.prototype = {
clone: function () {
return new L.Point(this.x, this.y);
},
// non-destructive, returns a new point
add: function (point) { add: function (point) {
return this.clone()._add(L.point(point)); return this.clone()._add(L.point(point));
}, },
// destructive, used directly for performance in situations where it's safe to modify existing point
_add: function (point) { _add: function (point) {
this.x += point.x; this.x += point.x;
this.y += point.y; this.y += point.y;
@ -22,35 +29,36 @@ L.Point.prototype = {
return this.clone()._subtract(L.point(point)); return this.clone()._subtract(L.point(point));
}, },
// destructive subtract (faster)
_subtract: function (point) { _subtract: function (point) {
this.x -= point.x; this.x -= point.x;
this.y -= point.y; this.y -= point.y;
return this; return this;
}, },
divideBy: function (num, round) { divideBy: function (num) {
return new L.Point(this.x / num, this.y / num, round); return this.clone()._divideBy(num);
}, },
multiplyBy: function (num, round) { _divideBy: function (num) {
return new L.Point(this.x * num, this.y * num, round); this.x /= num;
this.y /= num;
return this;
}, },
distanceTo: function (point) { multiplyBy: function (num) {
point = L.point(point); return this.clone()._multiplyBy(num);
},
var x = point.x - this.x, _multiplyBy: function (num) {
y = point.y - this.y; this.x *= num;
this.y *= num;
return Math.sqrt(x * x + y * y); return this;
}, },
round: function () { round: function () {
return this.clone()._round(); return this.clone()._round();
}, },
// destructive round
_round: function () { _round: function () {
this.x = Math.round(this.x); this.x = Math.round(this.x);
this.y = Math.round(this.y); this.y = Math.round(this.y);
@ -67,8 +75,13 @@ L.Point.prototype = {
return this; return this;
}, },
clone: function () { distanceTo: function (point) {
return new L.Point(this.x, this.y); point = L.point(point);
var x = point.x - this.x,
y = point.y - this.y;
return Math.sqrt(x * x + y * y);
}, },
toString: function () { toString: function () {

View File

@ -94,10 +94,11 @@ L.ImageOverlay = L.Class.extend({
scale = map.getZoomScale(e.zoom), scale = map.getZoomScale(e.zoom),
nw = this._bounds.getNorthWest(), nw = this._bounds.getNorthWest(),
se = this._bounds.getSouthEast(), se = this._bounds.getSouthEast(),
topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center),
size = map._latLngToNewLayerPoint(se, e.zoom, e.center).subtract(topLeft), size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft),
currentSize = map.latLngToLayerPoint(se).subtract(map.latLngToLayerPoint(nw)), currentSize = map.latLngToLayerPoint(se)._subtract(map.latLngToLayerPoint(nw)),
origin = topLeft.add(size.subtract(currentSize).divideBy(2)); origin = topLeft._add(size._subtract(currentSize)._divideBy(2));
image.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; image.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') ';
}, },
@ -105,7 +106,7 @@ L.ImageOverlay = L.Class.extend({
_reset: function () { _reset: function () {
var image = this._image, var image = this._image,
topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()), topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
size = this._map.latLngToLayerPoint(this._bounds.getSouthEast()).subtract(topLeft); size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft);
L.DomUtil.setPosition(image, topLeft); L.DomUtil.setPosition(image, topLeft);

View File

@ -104,8 +104,8 @@ L.Map.include({
var p = L.Path.CLIP_PADDING, var p = L.Path.CLIP_PADDING,
size = this.getSize(), size = this.getSize(),
panePos = L.DomUtil.getPosition(this._mapPane), panePos = L.DomUtil.getPosition(this._mapPane),
min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)), min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()),
max = min.add(size.multiplyBy(1 + p * 2)); max = min.add(size.multiplyBy(1 + p * 2)._round());
this._pathViewport = new L.Bounds(min, max); this._pathViewport = new L.Bounds(min, max);
} }

View File

@ -205,6 +205,6 @@ L.Handler.PolyEdit = L.Handler.extend({
p1 = map.latLngToLayerPoint(marker1.getLatLng()), p1 = map.latLngToLayerPoint(marker1.getLatLng()),
p2 = map.latLngToLayerPoint(marker2.getLatLng()); p2 = map.latLngToLayerPoint(marker2.getLatLng());
return map.layerPointToLatLng(p1._add(p2).divideBy(2)); return map.layerPointToLatLng(p1._add(p2)._divideBy(2));
} }
}); });

View File

@ -211,7 +211,7 @@ L.Map = L.Class.extend({
if (!this._loaded) { return this; } if (!this._loaded) { return this; }
var offset = oldSize.subtract(this.getSize()).divideBy(2, true); var offset = oldSize._subtract(this.getSize())._divideBy(2)._round();
if (animate === true) { if (animate === true) {
this.panBy(offset); this.panBy(offset);
@ -318,7 +318,7 @@ L.Map = L.Class.extend({
this._sizeChanged = false; this._sizeChanged = false;
} }
return this._size; return this._size.clone();
}, },
getPixelBounds: function () { getPixelBounds: function () {
@ -620,7 +620,7 @@ L.Map = L.Class.extend({
}, },
_getNewTopLeftPoint: function (center, zoom) { _getNewTopLeftPoint: function (center, zoom) {
var viewHalf = this.getSize().divideBy(2); var viewHalf = this.getSize()._divideBy(2);
// TODO round on display, not calculation to increase precision? // TODO round on display, not calculation to increase precision?
return this.project(center, zoom)._subtract(viewHalf)._round(); return this.project(center, zoom)._subtract(viewHalf)._round();
}, },
@ -631,7 +631,7 @@ L.Map = L.Class.extend({
}, },
_getCenterLayerPoint: function () { _getCenterLayerPoint: function () {
return this.containerPointToLayerPoint(this.getSize().divideBy(2)); return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
}, },
_getCenterOffset: function (center) { _getCenterOffset: function (center) {

View File

@ -17,7 +17,7 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
if (!this.options.zoomAnimation) { return false; } if (!this.options.zoomAnimation) { return false; }
var scale = this.getZoomScale(zoom), var scale = this.getZoomScale(zoom),
offset = this._getCenterOffset(center).divideBy(1 - 1 / scale); offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);
// if offset does not exceed half of the view // if offset does not exceed half of the view
if (!this._offsetIsWithinView(offset, 1)) { return false; } if (!this._offsetIsWithinView(offset, 1)) { return false; }

View File

@ -80,7 +80,7 @@ L.Map.Drag = L.Handler.extend({
}, },
_onViewReset: function () { _onViewReset: function () {
var pxCenter = this._map.getSize().divideBy(2), var pxCenter = this._map.getSize()._divideBy(2),
pxWorldCenter = this._map.latLngToLayerPoint(new L.LatLng(0, 0)); pxWorldCenter = this._map.latLngToLayerPoint(new L.LatLng(0, 0));
this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;

View File

@ -41,17 +41,17 @@ L.Map.ScrollWheelZoom = L.Handler.extend({
if (!delta) { return; } if (!delta) { return; }
var newZoom = zoom + delta, var newZoom = zoom + delta,
newCenter = this._getCenterForScrollWheelZoom(this._lastMousePos, newZoom); newCenter = this._getCenterForScrollWheelZoom(newZoom);
map.setView(newCenter, newZoom); map.setView(newCenter, newZoom);
}, },
_getCenterForScrollWheelZoom: function (mousePos, newZoom) { _getCenterForScrollWheelZoom: function (newZoom) {
var map = this._map, var map = this._map,
scale = map.getZoomScale(newZoom), scale = map.getZoomScale(newZoom),
viewHalf = map.getSize().divideBy(2), viewHalf = map.getSize()._divideBy(2),
centerOffset = mousePos.subtract(viewHalf).multiplyBy(1 - 1 / scale), centerOffset = this._lastMousePos._subtract(viewHalf)._multiplyBy(1 - 1 / scale),
newCenterPoint = map._getTopLeftPoint().add(viewHalf).add(centerOffset); newCenterPoint = map._getTopLeftPoint()._add(viewHalf)._add(centerOffset);
return map.unproject(newCenterPoint); return map.unproject(newCenterPoint);
} }

View File

@ -24,7 +24,7 @@ L.Map.TouchZoom = L.Handler.extend({
p2 = map.mouseEventToLayerPoint(e.touches[1]), p2 = map.mouseEventToLayerPoint(e.touches[1]),
viewCenter = map._getCenterLayerPoint(); viewCenter = map._getCenterLayerPoint();
this._startCenter = p1.add(p2).divideBy(2, true); this._startCenter = p1._add(p2)._divideBy(2);
this._startDist = p1.distanceTo(p2); this._startDist = p1.distanceTo(p2);
this._moved = false; this._moved = false;
@ -48,7 +48,7 @@ L.Map.TouchZoom = L.Handler.extend({
p2 = map.mouseEventToLayerPoint(e.touches[1]); p2 = map.mouseEventToLayerPoint(e.touches[1]);
this._scale = p1.distanceTo(p2) / this._startDist; this._scale = p1.distanceTo(p2) / this._startDist;
this._delta = p1.add(p2).divideBy(2, true).subtract(this._startCenter); this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter);
if (this._scale === 1) { return; } if (this._scale === 1) { return; }