leaflet-distortableimage
Advanced tools
Comparing version 0.4.0 to 0.4.1
@@ -135,2 +135,9 @@ L.DomUtil = L.extend(L.DomUtil, { | ||
}; | ||
L.TrigUtil = { | ||
calcAngleDegrees: function(x, y) { | ||
return Math.atan2(y, x) * 180 / Math.PI; | ||
} | ||
}; | ||
L.EXIF = function getEXIFdata(img) { | ||
@@ -223,71 +230,76 @@ if (Object.keys(EXIF.getAllTags(img)).length !== 0) { | ||
L.EditHandle = L.Marker.extend({ | ||
initialize: function(overlay, corner, options) { | ||
var markerOptions, | ||
latlng = overlay._corners[corner]; | ||
initialize: function(overlay, corner, options) { | ||
var markerOptions, | ||
latlng = overlay._corners[corner]; | ||
L.setOptions(this, options); | ||
L.setOptions(this, options); | ||
this._handled = overlay; | ||
this._corner = corner; | ||
this._handled = overlay; | ||
this._corner = corner; | ||
markerOptions = { | ||
draggable: true, | ||
zIndexOffset: 10 | ||
}; | ||
markerOptions = { | ||
draggable: true, | ||
zIndexOffset: 10 | ||
}; | ||
if (options && options.hasOwnProperty("draggable")) { | ||
markerOptions.draggable = options.draggable; | ||
} | ||
if (options && options.hasOwnProperty('draggable')) { | ||
markerOptions.draggable = options.draggable; | ||
} | ||
L.Marker.prototype.initialize.call(this, latlng, markerOptions); | ||
}, | ||
L.Marker.prototype.initialize.call(this, latlng, markerOptions); | ||
}, | ||
onAdd: function(map) { | ||
L.Marker.prototype.onAdd.call(this, map); | ||
this._bindListeners(); | ||
onAdd: function(map) { | ||
L.Marker.prototype.onAdd.call(this, map); | ||
this._bindListeners(); | ||
this.updateHandle(); | ||
}, | ||
this.updateHandle(); | ||
onRemove: function(map) { | ||
this._unbindListeners(); | ||
L.Marker.prototype.onRemove.call(this, map); | ||
}, | ||
_onHandleDragStart: function() { | ||
this._handled.fire("editstart"); | ||
}, | ||
onRemove: function(map) { | ||
this._unbindListeners(); | ||
L.Marker.prototype.onRemove.call(this, map); | ||
_onHandleDragEnd: function() { | ||
this._fireEdit(); | ||
}, | ||
_onHandleDragStart: function() { | ||
this._handled.fire('editstart'); | ||
}, | ||
_fireEdit: function() { | ||
this._handled.edited = true; | ||
this._handled.fire("edit"); | ||
}, | ||
_onHandleDragEnd: function() { | ||
this._fireEdit(); | ||
}, | ||
_bindListeners: function() { | ||
this.on( | ||
{ | ||
dragstart: this._onHandleDragStart, | ||
drag: this._onHandleDrag, | ||
dragend: this._onHandleDragEnd | ||
}, | ||
this | ||
); | ||
_fireEdit: function() { | ||
this._handled.edited = true; | ||
this._handled.fire('edit'); | ||
}, | ||
this._handled._map.on("zoomend", this.updateHandle, this); | ||
_bindListeners: function() { | ||
this.on({ | ||
'dragstart': this._onHandleDragStart, | ||
'drag': this._onHandleDrag, | ||
'dragend': this._onHandleDragEnd | ||
}, this); | ||
this._handled.on("update", this.updateHandle, this); | ||
}, | ||
this._handled._map.on('zoomend', this.updateHandle, this); | ||
_unbindListeners: function() { | ||
this.off( | ||
{ | ||
dragstart: this._onHandleDragStart, | ||
drag: this._onHandleDrag, | ||
dragend: this._onHandleDragEnd | ||
}, | ||
this | ||
); | ||
this._handled.on('update', this.updateHandle, this); | ||
}, | ||
_unbindListeners: function() { | ||
this.off({ | ||
'dragstart': this._onHandleDragStart, | ||
'drag': this._onHandleDrag, | ||
'dragend': this._onHandleDragEnd | ||
}, this); | ||
this._handled._map.off('zoomend', this.updateHandle, this); | ||
this._handled.off('update', this.updateHandle, this); | ||
} | ||
this._handled._map.off("zoomend", this.updateHandle, this); | ||
this._handled.off("update", this.updateHandle, this); | ||
} | ||
}); | ||
@@ -317,20 +329,22 @@ | ||
L.DistortHandle = L.EditHandle.extend({ | ||
options: { | ||
TYPE: 'distort', | ||
icon: new L.Icon({ | ||
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAChSURBVO3BIU4DURgGwNkvL2B6AkQTLBqP4QCoSm7DDXoBLBZHDbfgICAIZjEV3YTn9uVHdMZZtcnCfI13bIzxg0emg6Nm6QVbYz3jylEsXRrvwommb49X67jFkz80fR9Mb1YxTzqiWBSLYlEsikWxKBbFolgUi2JRLIpFsSgWxaJY03fHHOu40dH07bAzWCx9Ge/TiWbpHgdsjPGNB2f/yS+7xRCyiiZPJQAAAABJRU5ErkJggg==', | ||
iconSize: [32, 32], | ||
iconAnchor: [16, 16]} | ||
) | ||
}, | ||
options: { | ||
TYPE: "distort", | ||
icon: new L.Icon({ | ||
iconUrl: | ||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAChSURBVO3BIU4DURgGwNkvL2B6AkQTLBqP4QCoSm7DDXoBLBZHDbfgICAIZjEV3YTn9uVHdMZZtcnCfI13bIzxg0emg6Nm6QVbYz3jylEsXRrvwommb49X67jFkz80fR9Mb1YxTzqiWBSLYlEsikWxKBbFolgUi2JRLIpFsSgWxaJY03fHHOu40dH07bAzWCx9Ge/TiWbpHgdsjPGNB2f/yS+7xRCyiiZPJQAAAABJRU5ErkJggg==", | ||
iconSize: [32, 32], | ||
iconAnchor: [16, 16] | ||
}) | ||
}, | ||
updateHandle: function() { | ||
this.setLatLng(this._handled._corners[this._corner]); | ||
updateHandle: function() { | ||
this.setLatLng(this._handled._corners[this._corner]); | ||
}, | ||
_onHandleDrag: function() { | ||
this._handled._updateCorner(this._corner, this.getLatLng()); | ||
_onHandleDrag: function() { | ||
this._handled._updateCorner(this._corner, this.getLatLng()); | ||
this._handled.fire('update'); | ||
} | ||
this._handled.fire("update"); | ||
this._handled.editing._showToolbar(); | ||
} | ||
}); | ||
@@ -356,4 +370,2 @@ | ||
overlay.editing._hideToolbar(); | ||
overlay.editing._rotateBy(angle); | ||
@@ -376,2 +388,4 @@ | ||
this._handled.editing._showToolbar(); | ||
}, | ||
@@ -436,7 +450,7 @@ | ||
overlay.editing._hideToolbar(); | ||
overlay.editing._rotateBy(angle); | ||
overlay.editing._rotateBy(angle); | ||
overlay.fire('update'); | ||
overlay.fire('update'); | ||
this._handled.editing._showToolbar(); | ||
}, | ||
@@ -505,2 +519,4 @@ | ||
overlay.fire('update'); | ||
this._handled.editing._showToolbar(); | ||
}, | ||
@@ -772,2 +788,6 @@ | ||
getCorner: function(i) { | ||
return this._corners[i]; | ||
}, | ||
/* | ||
@@ -797,2 +817,11 @@ * Calculates the centroid of the image. | ||
_calcCenterTwoCornerPoints: function (topLeft, topRight) { | ||
var toolPoint = { x: "", y: "" }; | ||
toolPoint.x = topRight.x + (topLeft.x - topRight.x) / 2; | ||
toolPoint.y = topRight.y + (topLeft.y - topRight.y) / 2; | ||
return toolPoint; | ||
}, | ||
_calculateProjectiveTransform: function(latLngToCartesian) { | ||
@@ -847,10 +876,11 @@ /* Setting reasonable but made-up image defaults | ||
/** | ||
/** | ||
* the box zoom override works, but there is a bug involving click event propogation. | ||
* keeping uncommented for now so that it isn't used as a multi-select mechanism | ||
*/ | ||
*/ | ||
// L.DomEvent.on(map, "boxzoomend", this._addSelections, this); | ||
this.eachLayer(function(layer) { | ||
L.DomEvent.on(layer._image, 'mousedown', this._deselectOthers, this); | ||
L.DomEvent.on(layer._image, "mousedown", this._deselectOthers, this); | ||
L.DomEvent.on(layer, "dragstart", this._dragStartMultiple, this); | ||
@@ -869,3 +899,3 @@ L.DomEvent.on(layer, "drag", this._dragMultiple, this); | ||
this.eachLayer(function(layer) { | ||
L.DomEvent.off(layer._image, 'mousedown', this._deselectOthers, this); | ||
L.DomEvent.off(layer._image, "mousedown", this._deselectOthers, this); | ||
L.DomEvent.off(layer, "dragstart", this._dragStartMultiple, this); | ||
@@ -876,11 +906,11 @@ L.DomEvent.off(layer, "drag", this._dragMultiple, this); | ||
isSelected: function (overlay) { | ||
isSelected: function(overlay) { | ||
return L.DomUtil.hasClass(overlay.getElement(), "selected"); | ||
}, | ||
_toggleMultiSelect: function (event, edit) { | ||
if (edit._mode === 'lock') { return; } | ||
_toggleMultiSelect: function(event, edit) { | ||
if (edit._mode === "lock") { return; } | ||
if (event.metaKey || event.ctrlKey) { | ||
L.DomUtil.toggleClass(event.target, 'selected'); | ||
L.DomUtil.toggleClass(event.target, "selected"); | ||
} | ||
@@ -890,12 +920,12 @@ }, | ||
_deselectOthers: function(event) { | ||
this.eachLayer(function (layer) { | ||
this.eachLayer(function(layer) { | ||
var edit = layer.editing; | ||
if (layer._image !== event.target) { | ||
edit._hideMarkers(); | ||
edit._hideToolbar(); | ||
} else { | ||
edit._showMarkers(); | ||
this._toggleMultiSelect(event, edit); | ||
} | ||
}, this); | ||
L.DomEvent.stopPropagation(event); | ||
}, | ||
@@ -909,5 +939,7 @@ | ||
var edit = layer.editing; | ||
if (edit.toolbar) { edit._hideToolbar(); } | ||
if (edit.toolbar) { | ||
edit._hideToolbar(); | ||
} | ||
for (i = 0; i < 4; i++) { | ||
if (box.contains(layer.getCorners()[i]) && edit._mode !== "lock") { | ||
if (box.contains(layer.getCorner(i)) && edit._mode !== "lock") { | ||
L.DomUtil.addClass(layer.getElement(), "selected"); | ||
@@ -920,4 +952,4 @@ break; | ||
_onKeyDown: function (e) { | ||
if (e.key === 'Escape') { | ||
_onKeyDown: function(e) { | ||
if (e.key === "Escape") { | ||
this._deselectAll(); | ||
@@ -931,3 +963,5 @@ } | ||
if (!this.isSelected(overlay)) { return; } | ||
if (!this.isSelected(overlay)) { | ||
return; | ||
} | ||
@@ -940,3 +974,3 @@ this.eachLayer(function(layer) { | ||
layer._dragStartPoints[i] = layer._map.latLngToLayerPoint( | ||
layer.getCorners()[i] | ||
layer.getCorner(i) | ||
); | ||
@@ -952,3 +986,5 @@ } | ||
if (!this.isSelected(overlay)) { return; } | ||
if (!this.isSelected(overlay)) { | ||
return; | ||
} | ||
@@ -958,5 +994,5 @@ overlay._dragPoints = {}; | ||
for (i = 0; i < 4; i++) { | ||
overlay._dragPoints[i] = map.latLngToLayerPoint(overlay.getCorners()[i]); | ||
overlay._dragPoints[i] = map.latLngToLayerPoint(overlay.getCorner(i)); | ||
} | ||
var cpd = overlay._calcCornerPointDelta(); | ||
@@ -972,3 +1008,5 @@ | ||
L.DomUtil.removeClass(layer.getElement(), "selected"); | ||
if (edit.toolbar) { edit._hideToolbar(); } | ||
if (edit.toolbar) { | ||
edit._hideToolbar(); | ||
} | ||
edit._hideMarkers(); | ||
@@ -992,3 +1030,2 @@ }); | ||
) { | ||
layer._cpd = {}; | ||
@@ -1012,6 +1049,3 @@ | ||
_updateCollectionFromPoints: function(cpd, overlay) { | ||
var layersToMove = this._calcCollectionFromPoints( | ||
cpd, | ||
overlay | ||
); | ||
var layersToMove = this._calcCollectionFromPoints(cpd, overlay); | ||
@@ -1024,2 +1058,6 @@ layersToMove.forEach(function(layer) { | ||
}); | ||
L.distortableCollection = function(id, options) { | ||
return new L.DistortableCollection(id, options); | ||
}; | ||
L.DistortableImage = L.DistortableImage || {}; | ||
@@ -1115,2 +1153,3 @@ | ||
editing._toggleRotateDistort(); | ||
editing._showToolbar(); | ||
this.disable(); | ||
@@ -1182,5 +1221,27 @@ } | ||
EnableEXIF, | ||
ToggleOrder | ||
] | ||
} | ||
ToggleOrder | ||
] | ||
}, | ||
// todo: move to some sort of util class, these methods could be useful in future | ||
_rotateToolbarAngleDeg: function(angle) { | ||
var div = this._container, | ||
divStyle = div.style; | ||
var oldTransform = divStyle.transform; | ||
divStyle.transform = oldTransform + "rotate(" + angle + "deg)"; | ||
divStyle.transformOrigin = "1080% 650%"; | ||
this._rotateToolbarIcons(angle); | ||
}, | ||
_rotateToolbarIcons: function(angle) { | ||
var icons = document.querySelectorAll(".fa"); | ||
for (var i = 0; i < icons.length; i++) { | ||
icons.item(i).style.transform = "rotate(" + -angle + "deg)"; | ||
} | ||
}, | ||
}); | ||
@@ -1191,350 +1252,396 @@ | ||
L.DistortableImage.Edit = L.Handler.extend({ | ||
options: { | ||
opacity: 0.7, | ||
outline: '1px solid red', | ||
keymap: { | ||
8: '_removeOverlay', // backspace windows / delete mac | ||
46: '_removeOverlay', // delete windows / delete + fn mac | ||
20: '_toggleRotate', // CAPS | ||
27: '_deselect', // esc | ||
68: '_toggleRotateDistort', // d | ||
69: '_toggleIsolate', // e | ||
73: '_toggleIsolate', // i | ||
74: '_sendUp', // j | ||
75: '_sendDown', // k | ||
76: '_toggleLock', // l | ||
79: '_toggleOutline', // o | ||
82: '_toggleRotateDistort', // r | ||
83: '_toggleScale', // s | ||
84: '_toggleTransparency', // t | ||
} | ||
}, | ||
options: { | ||
opacity: 0.7, | ||
outline: "1px solid red", | ||
keymap: { | ||
8: "_removeOverlay", // backspace windows / delete mac | ||
46: "_removeOverlay", // delete windows / delete + fn mac | ||
20: "_toggleRotate", // CAPS | ||
27: "_deselect", // esc | ||
68: "_toggleRotateDistort", // d | ||
69: "_toggleIsolate", // e | ||
73: "_toggleIsolate", // i | ||
74: "_sendUp", // j | ||
75: "_sendDown", // k | ||
76: "_toggleLock", // l | ||
79: "_toggleOutline", // o | ||
82: "_toggleRotateDistort", // r | ||
83: "_toggleScale", // s | ||
84: "_toggleTransparency" // t | ||
} | ||
}, | ||
initialize: function(overlay) { | ||
this._overlay = overlay; | ||
this._toggledImage = false; | ||
initialize: function(overlay) { | ||
this._overlay = overlay; | ||
this._toggledImage = false; | ||
/* Interaction modes. */ | ||
this._mode = this._overlay.options.mode || 'distort'; | ||
this._transparent = false; | ||
this._outlined = false; | ||
}, | ||
/* Interaction modes. */ | ||
this._mode = this._overlay.options.mode || "distort"; | ||
this._transparent = false; | ||
this._outlined = false; | ||
}, | ||
/* Run on image selection. */ | ||
addHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
i; | ||
/* Run on image selection. */ | ||
addHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
i; | ||
this._lockHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._lockHandles.addLayer(new L.LockHandle(overlay, i, { draggable: false })); | ||
} | ||
this._lockHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._lockHandles.addLayer( | ||
new L.LockHandle(overlay, i, { draggable: false }) | ||
); | ||
} | ||
this._distortHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._distortHandles.addLayer(new L.DistortHandle(overlay, i)); | ||
} | ||
this._distortHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._distortHandles.addLayer(new L.DistortHandle(overlay, i)); | ||
} | ||
this._rotateHandles = new L.LayerGroup(); // handle includes rotate AND scale | ||
for (i = 0; i < 4; i++) { | ||
this._rotateHandles.addLayer(new L.RotateAndScaleHandle(overlay, i)); | ||
} | ||
this._rotateHandles = new L.LayerGroup(); // handle includes rotate AND scale | ||
for (i = 0; i < 4; i++) { | ||
this._rotateHandles.addLayer(new L.RotateAndScaleHandle(overlay, i)); | ||
} | ||
this._scaleHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._scaleHandles.addLayer(new L.ScaleHandle(overlay, i)); | ||
} | ||
this._scaleHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._scaleHandles.addLayer(new L.ScaleHandle(overlay, i)); | ||
} | ||
this.__rotateHandles = new L.LayerGroup(); // individual rotate | ||
for (i = 0; i < 4; i++) { | ||
this.__rotateHandles.addLayer(new L.RotateHandle(overlay, i)); | ||
} | ||
this.__rotateHandles = new L.LayerGroup(); // individual rotate | ||
for (i = 0; i < 4; i++) { | ||
this.__rotateHandles.addLayer(new L.RotateHandle(overlay, i)); | ||
} | ||
this._handles = { | ||
'lock': this._lockHandles, | ||
'distort': this._distortHandles, | ||
'rotate': this._rotateHandles, | ||
'scale': this._scaleHandles, | ||
'rotateStandalone': this.__rotateHandles | ||
}; | ||
this._handles = { | ||
lock: this._lockHandles, | ||
distort: this._distortHandles, | ||
rotate: this._rotateHandles, | ||
scale: this._scaleHandles, | ||
rotateStandalone: this.__rotateHandles | ||
}; | ||
if (this._mode === 'lock') { | ||
map.addLayer(this._lockHandles); | ||
} else { | ||
this._mode = 'distort'; | ||
map.addLayer(this._distortHandles); | ||
this._distortHandles.eachLayer(function (layer) { | ||
layer.setOpacity(0); | ||
layer.dragging.disable(); | ||
layer.options.draggable = false; | ||
}); | ||
this._enableDragging(); | ||
} | ||
if (this._mode === "lock") { | ||
map.addLayer(this._lockHandles); | ||
} else { | ||
this._mode = "distort"; | ||
map.addLayer(this._distortHandles); | ||
this._distortHandles.eachLayer(function(layer) { | ||
layer.setOpacity(0); | ||
layer.dragging.disable(); | ||
layer.options.draggable = false; | ||
}); | ||
this._enableDragging(); | ||
} | ||
this._overlay._dragStartPoints = { | ||
0: new L.point(0, 0), | ||
1: new L.point(0, 0), | ||
2: new L.point(0, 0), | ||
3: new L.point(0, 0) | ||
}; | ||
this._initToolbar(); | ||
L.DomEvent.on(map, "click", this._deselect, this); | ||
L.DomEvent.on(overlay._image, 'click', this._select, this); | ||
this._overlay._dragStartPoints = { | ||
0: new L.point(0, 0), | ||
1: new L.point(0, 0), | ||
2: new L.point(0, 0), | ||
3: new L.point(0, 0) | ||
}; | ||
/* Enable hotkeys. */ | ||
L.DomEvent.on(window, 'keydown', this._onKeyDown, this); | ||
L.DomEvent.on(map, "click", this._deselect, this); | ||
L.DomEvent.on(overlay._image, "click", this._select, this); | ||
overlay.fire('select'); | ||
}, | ||
/* Enable hotkeys. */ | ||
L.DomEvent.on(window, "keydown", this._onKeyDown, this); | ||
/* Run on image deselection. */ | ||
removeHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
overlay.fire("select"); | ||
}, | ||
L.DomEvent.off(map, "click", this._deselect, this); | ||
L.DomEvent.off(overlay._image, 'click', this._select, this); | ||
/* Run on image deselection. */ | ||
removeHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
// First, check if dragging exists - it may be off due to locking | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
L.DomEvent.off(map, "click", this._deselect, this); | ||
L.DomEvent.off(overlay._image, "click", this._select, this); | ||
if (this.toolbar) { this._hideToolbar(); } | ||
if (this.editing) { this.editing.disable(); } | ||
// First, check if dragging exists - it may be off due to locking | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
map.removeLayer(this._handles[this._mode]); | ||
if (this.toolbar) { this._hideToolbar(); } | ||
if (this.editing) { this.editing.disable(); } | ||
/* Disable hotkeys. */ | ||
L.DomEvent.off(window, 'keydown', this._onKeyDown, this); | ||
map.removeLayer(this._handles[this._mode]); | ||
overlay.fire('deselect'); | ||
/* Disable hotkeys. */ | ||
L.DomEvent.off(window, "keydown", this._onKeyDown, this); | ||
overlay.fire("deselect"); | ||
}, | ||
confirmDelete: function () { | ||
_initToolbar: function() { | ||
this._showToolbar(); | ||
this.toolbar._hide(); | ||
this.toolbar._tip.style.opacity = 0; | ||
}, | ||
confirmDelete: function() { | ||
return window.confirm("Are you sure you want to delete?"); | ||
}, | ||
}, | ||
_rotateBy: function(angle) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, p, q; | ||
_rotateBy: function(angle) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, | ||
p, | ||
q; | ||
for (i = 0; i < 4; i++) { | ||
p = map.latLngToLayerPoint(overlay._corners[i]).subtract(center); | ||
q = new L.Point( | ||
Math.cos(angle)*p.x - Math.sin(angle)*p.y, | ||
Math.sin(angle)*p.x + Math.cos(angle)*p.y | ||
); | ||
overlay._corners[i] = map.layerPointToLatLng(q.add(center)); | ||
} | ||
for (i = 0; i < 4; i++) { | ||
p = map.latLngToLayerPoint(overlay._corners[i]).subtract(center); | ||
q = new L.Point( | ||
Math.cos(angle) * p.x - Math.sin(angle) * p.y, | ||
Math.sin(angle) * p.x + Math.cos(angle) * p.y | ||
); | ||
overlay._corners[i] = map.layerPointToLatLng(q.add(center)); | ||
} | ||
overlay._reset(); | ||
}, | ||
overlay._reset(); | ||
}, | ||
_scaleBy: function(scale) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, p; | ||
_scaleBy: function(scale) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, | ||
p; | ||
for (i = 0; i < 4; i++) { | ||
p = map.latLngToLayerPoint(overlay._corners[i]) | ||
.subtract(center) | ||
.multiplyBy(scale) | ||
.add(center); | ||
overlay._corners[i] = map.layerPointToLatLng(p); | ||
} | ||
for (i = 0; i < 4; i++) { | ||
p = map | ||
.latLngToLayerPoint(overlay._corners[i]) | ||
.subtract(center) | ||
.multiplyBy(scale) | ||
.add(center); | ||
overlay._corners[i] = map.layerPointToLatLng(p); | ||
} | ||
overlay._reset(); | ||
}, | ||
overlay._reset(); | ||
}, | ||
_enableDragging: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
_enableDragging: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
this.dragging = new L.Draggable(overlay._image); | ||
this.dragging.enable(); | ||
this.dragging = new L.Draggable(overlay._image); | ||
this.dragging.enable(); | ||
/* Hide toolbars and markers while dragging; click will re-show it */ | ||
this.dragging.on('dragstart', function () { | ||
overlay.fire('dragstart'); | ||
this._hideToolbar(); | ||
}, this); | ||
/* Hide toolbars and markers while dragging; click will re-show it */ | ||
this.dragging.on("dragstart", function() { | ||
overlay.fire("dragstart"); | ||
this._hideToolbar(); | ||
},this); | ||
/* | ||
* Adjust default behavior of L.Draggable. | ||
* By default, L.Draggable overwrites the CSS3 distort transform | ||
* that we want when it calls L.DomUtil.setPosition. | ||
*/ | ||
this.dragging._updatePosition = function() { | ||
var delta = this._newPos.subtract(map.latLngToLayerPoint(overlay._corners[0])), | ||
currentPoint, i; | ||
/* | ||
* Adjust default behavior of L.Draggable. | ||
* By default, L.Draggable overwrites the CSS3 distort transform | ||
* that we want when it calls L.DomUtil.setPosition. | ||
*/ | ||
this.dragging._updatePosition = function() { | ||
var delta = this._newPos.subtract( | ||
map.latLngToLayerPoint(overlay._corners[0]) | ||
), | ||
currentPoint, | ||
i; | ||
this.fire('predrag'); | ||
this.fire("predrag"); | ||
for (i = 0; i < 4; i++) { | ||
currentPoint = map.latLngToLayerPoint(overlay._corners[i]); | ||
overlay._corners[i] = map.layerPointToLatLng(currentPoint.add(delta)); | ||
for (i = 0; i < 4; i++) { | ||
currentPoint = map.latLngToLayerPoint(overlay._corners[i]); | ||
overlay._corners[i] = map.layerPointToLatLng(currentPoint.add(delta)); | ||
} | ||
overlay._reset(); | ||
overlay.fire('update'); | ||
overlay.fire('drag'); | ||
overlay._reset(); | ||
overlay.fire("update"); | ||
overlay.fire("drag"); | ||
this.fire('drag'); | ||
}; | ||
}, | ||
this.fire("drag"); | ||
}; | ||
}, | ||
_onKeyDown: function(event) { | ||
var keymap = this.options.keymap, | ||
handlerName = keymap[event.which]; | ||
_onKeyDown: function(event) { | ||
var keymap = this.options.keymap, | ||
handlerName = keymap[event.which]; | ||
if (handlerName !== undefined && this._overlay.options.suppressToolbar !== true) { | ||
this[handlerName].call(this); | ||
} | ||
}, | ||
if (handlerName !== undefined && this._overlay.options.suppressToolbar !== true) { | ||
this[handlerName].call(this); | ||
} | ||
}, | ||
_toggleRotateDistort: function() { | ||
var map = this._overlay._map; | ||
_toggleRotateDistort: function() { | ||
var map = this._overlay._map; | ||
map.removeLayer(this._handles[this._mode]); | ||
map.removeLayer(this._handles[this._mode]); | ||
/* Switch mode. */ | ||
if (this._mode === 'rotate') { this._mode = 'distort'; } | ||
else { this._mode = 'rotate'; } | ||
/* Switch mode. */ | ||
if (this._mode === "rotate") { this._mode = "distort"; } | ||
else { this._mode = "rotate"; } | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
this._showToolbar(); | ||
_toggleScale: function() { | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
_toggleScale: function() { | ||
var map = this._overlay._map; | ||
if (this._mode === "lock") { return; } | ||
map.removeLayer(this._handles[this._mode]); | ||
this._mode = 'scale'; | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
_toggleRotate: function() { | ||
if (this._mode === "scale") { this._mode = "distort"; } | ||
else { this._mode = "scale"; } | ||
this._showToolbar(); | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
_toggleRotate: function() { | ||
var map = this._overlay._map; | ||
if (this._mode === "lock") { return; } | ||
map.removeLayer(this._handles[this._mode]); | ||
this._mode = 'rotateStandalone'; | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
this._mode = "rotateStandalone"; | ||
_toggleTransparency: function() { | ||
var image = this._overlay._image, | ||
opacity; | ||
this._showToolbar(); | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
this._transparent = !this._transparent; | ||
opacity = this._transparent ? this.options.opacity : 1; | ||
_toggleTransparency: function() { | ||
var image = this._overlay._image, | ||
opacity; | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute('opacity', opacity); | ||
}, | ||
this._transparent = !this._transparent; | ||
opacity = this._transparent ? this.options.opacity : 1; | ||
_toggleOutline: function() { | ||
var image = this._overlay._image, | ||
opacity, outline; | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute("opacity", opacity); | ||
}, | ||
this._outlined = !this._outlined; | ||
opacity = this._outlined ? this.options.opacity / 2 : 1; | ||
outline = this._outlined ? this.options.outline : 'none'; | ||
_toggleOutline: function() { | ||
var image = this._overlay._image, | ||
opacity, | ||
outline; | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute('opacity', opacity); | ||
this._outlined = !this._outlined; | ||
opacity = this._outlined ? this.options.opacity / 2 : 1; | ||
outline = this._outlined ? this.options.outline : "none"; | ||
image.style.outline = outline; | ||
}, | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute("opacity", opacity); | ||
_sendUp: function() { | ||
this._overlay.bringToFront(); | ||
}, | ||
image.style.outline = outline; | ||
}, | ||
_sendDown: function() { | ||
this._overlay.bringToBack(); | ||
}, | ||
_sendUp: function() { | ||
this._overlay.bringToFront(); | ||
}, | ||
_toggleLock: function() { | ||
var map = this._overlay._map; | ||
_sendDown: function() { | ||
this._overlay.bringToBack(); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
/* Switch mode. */ | ||
if (this._mode === 'lock') { | ||
this._mode = 'distort'; | ||
this._enableDragging(); | ||
} else { | ||
this._mode = 'lock'; | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
} | ||
_toggleLock: function() { | ||
var map = this._overlay._map; | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
/* Switch mode. */ | ||
if (this._mode === "lock") { | ||
this._mode = "distort"; | ||
this._enableDragging(); | ||
} else { | ||
this._mode = "lock"; | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
} | ||
_select: function (event) { | ||
this._showToolbar(event); | ||
this._showMarkers(); | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
L.DomEvent.stopPropagation(event); | ||
}, | ||
_select: function(event) { | ||
this._showToolbar(event); | ||
this._showMarkers(); | ||
_deselect: function (event) { | ||
this._hideToolbar(event); | ||
this._hideMarkers(); | ||
}, | ||
L.DomEvent.stopPropagation(event); | ||
}, | ||
_hideToolbar: function() { | ||
var map = this._overlay._map; | ||
if (this.toolbar) { | ||
map.removeLayer(this.toolbar); | ||
this.toolbar = false; | ||
} | ||
}, | ||
_deselect: function(event) { | ||
this._hideToolbar(event); | ||
this._hideMarkers(); | ||
}, | ||
_showMarkers: function() { | ||
if (this._mode === 'lock') { return; } | ||
this._distortHandles.eachLayer(function (layer) { | ||
layer.setOpacity(1); | ||
layer.dragging.enable(); | ||
layer.options.draggable = true; | ||
}); | ||
}, | ||
_hideToolbar: function() { | ||
var map = this._overlay._map; | ||
if (this.toolbar) { | ||
map.removeLayer(this.toolbar); | ||
this.toolbar = false; | ||
} | ||
}, | ||
_hideMarkers: function() { | ||
this._distortHandles.eachLayer(function (layer) { | ||
var drag = layer.dragging, | ||
opts = layer.options; | ||
_showMarkers: function() { | ||
if (this._mode === "lock") { return; } | ||
var currentHandle = this._handles[this._mode]; | ||
currentHandle.eachLayer(function(layer) { | ||
layer.setOpacity(1); | ||
layer.dragging.enable(); | ||
layer.options.draggable = true; | ||
}); | ||
}, | ||
layer.setOpacity(0); | ||
if (drag) { drag.disable(); } | ||
if (opts.draggable) { opts.draggable = false; } | ||
}); | ||
}, | ||
// TODO: toolbar for multiple image selection | ||
_showToolbar: function(event) { | ||
var overlay = this._overlay, | ||
target = event.target, | ||
map = overlay._map; | ||
_hideMarkers: function() { | ||
var currentHandle = this._handles[this._mode]; | ||
currentHandle.eachLayer(function(layer) { | ||
var drag = layer.dragging, | ||
opts = layer.options; | ||
/* Ensure that there is only ever one toolbar attached to each image. */ | ||
this._hideToolbar(); | ||
var point; | ||
if (event.containerPoint) { point = event.containerPoint; } | ||
else { point = target._leaflet_pos; } | ||
var raised_point = map.containerPointToLatLng(new L.Point(point.x,point.y-20)); | ||
raised_point.lng = overlay.getCenter().lng; | ||
if (this._overlay.options.suppressToolbar !== true) { | ||
this.toolbar = new L.DistortableImage.EditToolbar(raised_point).addTo(map, overlay); | ||
overlay.fire('toolbar:created'); | ||
} | ||
}, | ||
layer.setOpacity(0); | ||
if (drag) { | ||
drag.disable(); | ||
} | ||
if (opts.draggable) { | ||
opts.draggable = false; | ||
} | ||
}); | ||
}, | ||
_removeOverlay: function () { | ||
// TODO: toolbar for multiple image selection | ||
_showToolbar: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
/* Ensure that there is only ever one toolbar attached to each image. */ | ||
this._hideToolbar(); | ||
//Find the topmost point on the image. | ||
var corners = overlay.getCorners(); | ||
var maxLat = -Infinity; | ||
for (var i = 0; i < corners.length; i++) { | ||
if (corners[i].lat > maxLat) { | ||
maxLat = corners[i].lat; | ||
} | ||
} | ||
//Longitude is based on the centroid of the image. | ||
var raised_point = overlay.getCenter(); | ||
raised_point.lat = maxLat; | ||
if (this._overlay.options.suppressToolbar !== true) { | ||
this.toolbar = new L.DistortableImage.EditToolbar(raised_point).addTo( | ||
map, | ||
overlay | ||
); | ||
overlay.fire("toolbar:created"); | ||
} | ||
}, | ||
_removeOverlay: function() { | ||
var overlay = this._overlay; | ||
@@ -1544,105 +1651,100 @@ if (this._mode !== "lock") { | ||
if (choice) { | ||
this._hideToolbar(); | ||
this._hideToolbar(); | ||
overlay._map.removeLayer(overlay); | ||
overlay.fire('delete'); | ||
overlay.fire("delete"); | ||
this.disable(); | ||
} | ||
} | ||
}, | ||
// compare this to using overlay zIndex | ||
_toggleOrder: function () { | ||
if (this._toggledImage) { | ||
this._overlay.bringToFront(); | ||
this._toggledImage = false; | ||
} | ||
else { | ||
this._overlay.bringToBack(); | ||
this._toggledImage = true; | ||
} | ||
}, | ||
}, | ||
// Based on https://github.com/publiclab/mapknitter/blob/8d94132c81b3040ae0d0b4627e685ff75275b416/app/assets/javascripts/mapknitter/Map.js#L47-L82 | ||
_toggleExport: function (){ | ||
var map = this._overlay._map; | ||
var overlay = this._overlay; | ||
// compare this to using overlay zIndex | ||
_toggleOrder: function() { | ||
if (this._toggledImage) { | ||
this._overlay.bringToFront(); | ||
this._toggledImage = false; | ||
} else { | ||
this._overlay.bringToBack(); | ||
this._toggledImage = true; | ||
} | ||
}, | ||
// make a new image | ||
var downloadable = new Image(); | ||
// Based on https://github.com/publiclab/mapknitter/blob/8d94132c81b3040ae0d0b4627e685ff75275b416/app/assets/javascripts/mapknitter/Map.js#L47-L82 | ||
_toggleExport: function() { | ||
var map = this._overlay._map; | ||
var overlay = this._overlay; | ||
downloadable.id = downloadable.id || "tempId12345"; | ||
$('body').append(downloadable); | ||
// make a new image | ||
var downloadable = new Image(); | ||
downloadable.onload = function onLoadDownloadableImage() { | ||
downloadable.id = downloadable.id || "tempId12345"; | ||
$("body").append(downloadable); | ||
var height = downloadable.height, | ||
width = downloadable.width, | ||
nw = map.latLngToLayerPoint(overlay._corners[0]), | ||
ne = map.latLngToLayerPoint(overlay._corners[1]), | ||
sw = map.latLngToLayerPoint(overlay._corners[2]), | ||
se = map.latLngToLayerPoint(overlay._corners[3]); | ||
downloadable.onload = function onLoadDownloadableImage() { | ||
var height = downloadable.height, | ||
width = downloadable.width, | ||
nw = map.latLngToLayerPoint(overlay._corners[0]), | ||
ne = map.latLngToLayerPoint(overlay._corners[1]), | ||
sw = map.latLngToLayerPoint(overlay._corners[2]), | ||
se = map.latLngToLayerPoint(overlay._corners[3]); | ||
// I think this is to move the image to the upper left corner, | ||
// jywarren: i think we may need these or the image goes off the edge of the canvas | ||
// jywarren: but these seem to break the distortion math... | ||
// I think this is to move the image to the upper left corner, | ||
// jywarren: i think we may need these or the image goes off the edge of the canvas | ||
// jywarren: but these seem to break the distortion math... | ||
// jywarren: i think it should be rejiggered so it | ||
// finds the most negative values of x and y and then | ||
// adds those to all coordinates | ||
// jywarren: i think it should be rejiggered so it | ||
// finds the most negative values of x and y and then | ||
// adds those to all coordinates | ||
//nw.x -= nw.x; | ||
//ne.x -= nw.x; | ||
//se.x -= nw.x; | ||
//sw.x -= nw.x; | ||
//nw.x -= nw.x; | ||
//ne.x -= nw.x; | ||
//se.x -= nw.x; | ||
//sw.x -= nw.x; | ||
//nw.y -= nw.y; | ||
//ne.y -= nw.y; | ||
//se.y -= nw.y; | ||
//sw.y -= nw.y; | ||
//nw.y -= nw.y; | ||
//ne.y -= nw.y; | ||
//se.y -= nw.y; | ||
//sw.y -= nw.y; | ||
// run once warping is complete | ||
downloadable.onload = function() { | ||
$(downloadable).remove(); | ||
}; | ||
// run once warping is complete | ||
downloadable.onload = function() { | ||
$(downloadable).remove(); | ||
}; | ||
if (window && window.hasOwnProperty('warpWebGl')) { | ||
warpWebGl( | ||
downloadable.id, | ||
[0, 0, width, 0, width, height, 0, height], | ||
[nw.x, nw.y, ne.x, ne.y, se.x, se.y, sw.x, sw.y], | ||
true // trigger download | ||
); | ||
} | ||
if (window && window.hasOwnProperty("warpWebGl")) { | ||
warpWebGl( | ||
downloadable.id, | ||
[0, 0, width, 0, width, height, 0, height], | ||
[nw.x, nw.y, ne.x, ne.y, se.x, se.y, sw.x, sw.y], | ||
true // trigger download | ||
); | ||
} | ||
}; | ||
}; | ||
downloadable.src = overlay.options.fullResolutionSrc || overlay._image.src; | ||
}, | ||
downloadable.src = overlay.options.fullResolutionSrc || overlay._image.src; | ||
}, | ||
toggleIsolate: function() { | ||
// this.isolated = !this.isolated; | ||
// if (this.isolated) { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = false; | ||
// img.setOpacity(1); | ||
// }); | ||
// } else { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = true; | ||
// img.setOpacity(0); | ||
// }); | ||
// } | ||
// this.hidden = false; | ||
// this.setOpacity(1); | ||
} | ||
toggleIsolate: function() { | ||
// this.isolated = !this.isolated; | ||
// if (this.isolated) { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = false; | ||
// img.setOpacity(1); | ||
// }); | ||
// } else { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = true; | ||
// img.setOpacity(0); | ||
// }); | ||
// } | ||
// this.hidden = false; | ||
// this.setOpacity(1); | ||
} | ||
}); | ||
L.DistortableImageOverlay.addInitHook(function() { | ||
this.editing = new L.DistortableImage.Edit(this); | ||
this.editing = new L.DistortableImage.Edit(this); | ||
if (this.options.editable) { | ||
L.DomEvent.on(this._image, 'load', this.editing.enable, this.editing); | ||
} | ||
if (this.options.editable) { | ||
L.DomEvent.on(this._image, "load", this.editing.enable, this.editing); | ||
} | ||
@@ -1653,2 +1755,3 @@ this.on('remove', function () { | ||
}); | ||
L.Map.mergeOptions({ boxSelector: true, boxZoom: false }); | ||
@@ -1655,0 +1758,0 @@ |
{ | ||
"name": "leaflet-distortableimage", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "Leaflet plugin enabling image overlays to be distorted, stretched, and warped (built for Public Lab's MapKnitter: http://publiclab.org).", | ||
@@ -44,4 +44,4 @@ "scripts": { | ||
"grunt-karma": "^3.0.1", | ||
"jquery": "~> 3.3.1", | ||
"karma": "^3.1.4", | ||
"jquery": "~> 3.4.0", | ||
"karma": "^4.1.0", | ||
"karma-coverage": "^1.1.1", | ||
@@ -48,0 +48,0 @@ "karma-mocha": "^1.3.0", |
@@ -116,6 +116,6 @@ Leaflet.DistortableImage | ||
// OPTION 1: Pass in images immediately | ||
new L.DistortableCollection([img, img2, img3]).addTo(map); | ||
L.distortableCollection([img, img2, img3]).addTo(map); | ||
// OPTION 2: Instantiate an empty collection and pass in images later | ||
var imageFeatureGroup = new L.DistortableCollection().addTo(map); | ||
var imageFeatureGroup = L.distortableCollection().addTo(map); | ||
@@ -153,14 +153,32 @@ imageFeatureGroup.addLayer(img); | ||
### Corners | ||
## Corners | ||
The corners are stored in `img._corners` as `L.latLng` objects, so after instantiating the image and moving it around, you can always access them like this: | ||
The corners are stored as `L.latLng` objects | ||
on the image, and can be accessed using our `getCorners()` method after the image is instantiated and added to the map. | ||
Useful usage example: | ||
```js | ||
// instantiate and add to map | ||
img = L.distortableImageOverlay(...); | ||
img.addTo(map); | ||
// move the image around | ||
JSON.stringify(img._corners) | ||
// grab the initial corner positions | ||
JSON.stringify(img.getCorners()) | ||
=> "[{"lat":51.52,"lng":-0.1},{"lat":51.52,"lng":-0.14},{"lat":51.5,"lng":-0.1},{"lat":51.5,"lng":-0.14}]" | ||
// ...move the image around... | ||
// check the new corner positions. | ||
JSON.stringify(img.getCorners()) | ||
=> "[{"lat":51.51091971397745,"lng":-0.015994012355804447},{"lat":51.51091971397745,"lng":-0.05599111318588257},{"lat":51.49093697986642,"lng":-0.015994012355804447},{"lat":51.49093697986642,"lng":-0.05599111318588257}]" | ||
// note there is an added level of precision after dragging the image for debugging purposes | ||
``` | ||
### Corner | ||
We further added a `getCorner(idx)` method used the same way as its plural counterpart but with an index passed to it. | ||
## Setup | ||
@@ -167,0 +185,0 @@ |
@@ -12,10 +12,11 @@ L.DistortableCollection = L.FeatureGroup.extend({ | ||
/** | ||
/** | ||
* the box zoom override works, but there is a bug involving click event propogation. | ||
* keeping uncommented for now so that it isn't used as a multi-select mechanism | ||
*/ | ||
*/ | ||
// L.DomEvent.on(map, "boxzoomend", this._addSelections, this); | ||
this.eachLayer(function(layer) { | ||
L.DomEvent.on(layer._image, 'mousedown', this._deselectOthers, this); | ||
L.DomEvent.on(layer._image, "mousedown", this._deselectOthers, this); | ||
L.DomEvent.on(layer, "dragstart", this._dragStartMultiple, this); | ||
@@ -34,3 +35,3 @@ L.DomEvent.on(layer, "drag", this._dragMultiple, this); | ||
this.eachLayer(function(layer) { | ||
L.DomEvent.off(layer._image, 'mousedown', this._deselectOthers, this); | ||
L.DomEvent.off(layer._image, "mousedown", this._deselectOthers, this); | ||
L.DomEvent.off(layer, "dragstart", this._dragStartMultiple, this); | ||
@@ -41,11 +42,11 @@ L.DomEvent.off(layer, "drag", this._dragMultiple, this); | ||
isSelected: function (overlay) { | ||
isSelected: function(overlay) { | ||
return L.DomUtil.hasClass(overlay.getElement(), "selected"); | ||
}, | ||
_toggleMultiSelect: function (event, edit) { | ||
if (edit._mode === 'lock') { return; } | ||
_toggleMultiSelect: function(event, edit) { | ||
if (edit._mode === "lock") { return; } | ||
if (event.metaKey || event.ctrlKey) { | ||
L.DomUtil.toggleClass(event.target, 'selected'); | ||
L.DomUtil.toggleClass(event.target, "selected"); | ||
} | ||
@@ -55,12 +56,12 @@ }, | ||
_deselectOthers: function(event) { | ||
this.eachLayer(function (layer) { | ||
this.eachLayer(function(layer) { | ||
var edit = layer.editing; | ||
if (layer._image !== event.target) { | ||
edit._hideMarkers(); | ||
edit._hideToolbar(); | ||
} else { | ||
edit._showMarkers(); | ||
this._toggleMultiSelect(event, edit); | ||
} | ||
}, this); | ||
L.DomEvent.stopPropagation(event); | ||
}, | ||
@@ -74,5 +75,7 @@ | ||
var edit = layer.editing; | ||
if (edit.toolbar) { edit._hideToolbar(); } | ||
if (edit.toolbar) { | ||
edit._hideToolbar(); | ||
} | ||
for (i = 0; i < 4; i++) { | ||
if (box.contains(layer.getCorners()[i]) && edit._mode !== "lock") { | ||
if (box.contains(layer.getCorner(i)) && edit._mode !== "lock") { | ||
L.DomUtil.addClass(layer.getElement(), "selected"); | ||
@@ -85,4 +88,4 @@ break; | ||
_onKeyDown: function (e) { | ||
if (e.key === 'Escape') { | ||
_onKeyDown: function(e) { | ||
if (e.key === "Escape") { | ||
this._deselectAll(); | ||
@@ -96,3 +99,5 @@ } | ||
if (!this.isSelected(overlay)) { return; } | ||
if (!this.isSelected(overlay)) { | ||
return; | ||
} | ||
@@ -105,3 +110,3 @@ this.eachLayer(function(layer) { | ||
layer._dragStartPoints[i] = layer._map.latLngToLayerPoint( | ||
layer.getCorners()[i] | ||
layer.getCorner(i) | ||
); | ||
@@ -117,3 +122,5 @@ } | ||
if (!this.isSelected(overlay)) { return; } | ||
if (!this.isSelected(overlay)) { | ||
return; | ||
} | ||
@@ -123,5 +130,5 @@ overlay._dragPoints = {}; | ||
for (i = 0; i < 4; i++) { | ||
overlay._dragPoints[i] = map.latLngToLayerPoint(overlay.getCorners()[i]); | ||
overlay._dragPoints[i] = map.latLngToLayerPoint(overlay.getCorner(i)); | ||
} | ||
var cpd = overlay._calcCornerPointDelta(); | ||
@@ -137,3 +144,5 @@ | ||
L.DomUtil.removeClass(layer.getElement(), "selected"); | ||
if (edit.toolbar) { edit._hideToolbar(); } | ||
if (edit.toolbar) { | ||
edit._hideToolbar(); | ||
} | ||
edit._hideMarkers(); | ||
@@ -157,3 +166,2 @@ }); | ||
) { | ||
layer._cpd = {}; | ||
@@ -177,6 +185,3 @@ | ||
_updateCollectionFromPoints: function(cpd, overlay) { | ||
var layersToMove = this._calcCollectionFromPoints( | ||
cpd, | ||
overlay | ||
); | ||
var layersToMove = this._calcCollectionFromPoints(cpd, overlay); | ||
@@ -188,2 +193,6 @@ layersToMove.forEach(function(layer) { | ||
} | ||
}); | ||
}); | ||
L.distortableCollection = function(id, options) { | ||
return new L.DistortableCollection(id, options); | ||
}; |
@@ -224,2 +224,6 @@ L.DistortableImageOverlay = L.ImageOverlay.extend({ | ||
getCorner: function(i) { | ||
return this._corners[i]; | ||
}, | ||
/* | ||
@@ -249,2 +253,11 @@ * Calculates the centroid of the image. | ||
_calcCenterTwoCornerPoints: function (topLeft, topRight) { | ||
var toolPoint = { x: "", y: "" }; | ||
toolPoint.x = topRight.x + (topLeft.x - topRight.x) / 2; | ||
toolPoint.y = topRight.y + (topLeft.y - topRight.y) / 2; | ||
return toolPoint; | ||
}, | ||
_calculateProjectiveTransform: function(latLngToCartesian) { | ||
@@ -251,0 +264,0 @@ /* Setting reasonable but made-up image defaults |
L.DistortableImage = L.DistortableImage || {}; | ||
L.DistortableImage.Edit = L.Handler.extend({ | ||
options: { | ||
opacity: 0.7, | ||
outline: '1px solid red', | ||
keymap: { | ||
8: '_removeOverlay', // backspace windows / delete mac | ||
46: '_removeOverlay', // delete windows / delete + fn mac | ||
20: '_toggleRotate', // CAPS | ||
27: '_deselect', // esc | ||
68: '_toggleRotateDistort', // d | ||
69: '_toggleIsolate', // e | ||
73: '_toggleIsolate', // i | ||
74: '_sendUp', // j | ||
75: '_sendDown', // k | ||
76: '_toggleLock', // l | ||
79: '_toggleOutline', // o | ||
82: '_toggleRotateDistort', // r | ||
83: '_toggleScale', // s | ||
84: '_toggleTransparency', // t | ||
} | ||
}, | ||
options: { | ||
opacity: 0.7, | ||
outline: "1px solid red", | ||
keymap: { | ||
8: "_removeOverlay", // backspace windows / delete mac | ||
46: "_removeOverlay", // delete windows / delete + fn mac | ||
20: "_toggleRotate", // CAPS | ||
27: "_deselect", // esc | ||
68: "_toggleRotateDistort", // d | ||
69: "_toggleIsolate", // e | ||
73: "_toggleIsolate", // i | ||
74: "_sendUp", // j | ||
75: "_sendDown", // k | ||
76: "_toggleLock", // l | ||
79: "_toggleOutline", // o | ||
82: "_toggleRotateDistort", // r | ||
83: "_toggleScale", // s | ||
84: "_toggleTransparency" // t | ||
} | ||
}, | ||
initialize: function(overlay) { | ||
this._overlay = overlay; | ||
this._toggledImage = false; | ||
initialize: function(overlay) { | ||
this._overlay = overlay; | ||
this._toggledImage = false; | ||
/* Interaction modes. */ | ||
this._mode = this._overlay.options.mode || 'distort'; | ||
this._transparent = false; | ||
this._outlined = false; | ||
}, | ||
/* Interaction modes. */ | ||
this._mode = this._overlay.options.mode || "distort"; | ||
this._transparent = false; | ||
this._outlined = false; | ||
}, | ||
/* Run on image selection. */ | ||
addHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
i; | ||
/* Run on image selection. */ | ||
addHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
i; | ||
this._lockHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._lockHandles.addLayer(new L.LockHandle(overlay, i, { draggable: false })); | ||
} | ||
this._lockHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._lockHandles.addLayer( | ||
new L.LockHandle(overlay, i, { draggable: false }) | ||
); | ||
} | ||
this._distortHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._distortHandles.addLayer(new L.DistortHandle(overlay, i)); | ||
} | ||
this._distortHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._distortHandles.addLayer(new L.DistortHandle(overlay, i)); | ||
} | ||
this._rotateHandles = new L.LayerGroup(); // handle includes rotate AND scale | ||
for (i = 0; i < 4; i++) { | ||
this._rotateHandles.addLayer(new L.RotateAndScaleHandle(overlay, i)); | ||
} | ||
this._rotateHandles = new L.LayerGroup(); // handle includes rotate AND scale | ||
for (i = 0; i < 4; i++) { | ||
this._rotateHandles.addLayer(new L.RotateAndScaleHandle(overlay, i)); | ||
} | ||
this._scaleHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._scaleHandles.addLayer(new L.ScaleHandle(overlay, i)); | ||
} | ||
this._scaleHandles = new L.LayerGroup(); | ||
for (i = 0; i < 4; i++) { | ||
this._scaleHandles.addLayer(new L.ScaleHandle(overlay, i)); | ||
} | ||
this.__rotateHandles = new L.LayerGroup(); // individual rotate | ||
for (i = 0; i < 4; i++) { | ||
this.__rotateHandles.addLayer(new L.RotateHandle(overlay, i)); | ||
} | ||
this.__rotateHandles = new L.LayerGroup(); // individual rotate | ||
for (i = 0; i < 4; i++) { | ||
this.__rotateHandles.addLayer(new L.RotateHandle(overlay, i)); | ||
} | ||
this._handles = { | ||
'lock': this._lockHandles, | ||
'distort': this._distortHandles, | ||
'rotate': this._rotateHandles, | ||
'scale': this._scaleHandles, | ||
'rotateStandalone': this.__rotateHandles | ||
}; | ||
this._handles = { | ||
lock: this._lockHandles, | ||
distort: this._distortHandles, | ||
rotate: this._rotateHandles, | ||
scale: this._scaleHandles, | ||
rotateStandalone: this.__rotateHandles | ||
}; | ||
if (this._mode === 'lock') { | ||
map.addLayer(this._lockHandles); | ||
} else { | ||
this._mode = 'distort'; | ||
map.addLayer(this._distortHandles); | ||
this._distortHandles.eachLayer(function (layer) { | ||
layer.setOpacity(0); | ||
layer.dragging.disable(); | ||
layer.options.draggable = false; | ||
}); | ||
this._enableDragging(); | ||
} | ||
if (this._mode === "lock") { | ||
map.addLayer(this._lockHandles); | ||
} else { | ||
this._mode = "distort"; | ||
map.addLayer(this._distortHandles); | ||
this._distortHandles.eachLayer(function(layer) { | ||
layer.setOpacity(0); | ||
layer.dragging.disable(); | ||
layer.options.draggable = false; | ||
}); | ||
this._enableDragging(); | ||
} | ||
this._overlay._dragStartPoints = { | ||
0: new L.point(0, 0), | ||
1: new L.point(0, 0), | ||
2: new L.point(0, 0), | ||
3: new L.point(0, 0) | ||
}; | ||
this._initToolbar(); | ||
L.DomEvent.on(map, "click", this._deselect, this); | ||
L.DomEvent.on(overlay._image, 'click', this._select, this); | ||
this._overlay._dragStartPoints = { | ||
0: new L.point(0, 0), | ||
1: new L.point(0, 0), | ||
2: new L.point(0, 0), | ||
3: new L.point(0, 0) | ||
}; | ||
/* Enable hotkeys. */ | ||
L.DomEvent.on(window, 'keydown', this._onKeyDown, this); | ||
L.DomEvent.on(map, "click", this._deselect, this); | ||
L.DomEvent.on(overlay._image, "click", this._select, this); | ||
overlay.fire('select'); | ||
}, | ||
/* Enable hotkeys. */ | ||
L.DomEvent.on(window, "keydown", this._onKeyDown, this); | ||
/* Run on image deselection. */ | ||
removeHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
overlay.fire("select"); | ||
}, | ||
L.DomEvent.off(map, "click", this._deselect, this); | ||
L.DomEvent.off(overlay._image, 'click', this._select, this); | ||
/* Run on image deselection. */ | ||
removeHooks: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
// First, check if dragging exists - it may be off due to locking | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
L.DomEvent.off(map, "click", this._deselect, this); | ||
L.DomEvent.off(overlay._image, "click", this._select, this); | ||
if (this.toolbar) { this._hideToolbar(); } | ||
if (this.editing) { this.editing.disable(); } | ||
// First, check if dragging exists - it may be off due to locking | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
map.removeLayer(this._handles[this._mode]); | ||
if (this.toolbar) { this._hideToolbar(); } | ||
if (this.editing) { this.editing.disable(); } | ||
/* Disable hotkeys. */ | ||
L.DomEvent.off(window, 'keydown', this._onKeyDown, this); | ||
map.removeLayer(this._handles[this._mode]); | ||
overlay.fire('deselect'); | ||
/* Disable hotkeys. */ | ||
L.DomEvent.off(window, "keydown", this._onKeyDown, this); | ||
overlay.fire("deselect"); | ||
}, | ||
confirmDelete: function () { | ||
_initToolbar: function() { | ||
this._showToolbar(); | ||
this.toolbar._hide(); | ||
this.toolbar._tip.style.opacity = 0; | ||
}, | ||
confirmDelete: function() { | ||
return window.confirm("Are you sure you want to delete?"); | ||
}, | ||
}, | ||
_rotateBy: function(angle) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, p, q; | ||
_rotateBy: function(angle) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, | ||
p, | ||
q; | ||
for (i = 0; i < 4; i++) { | ||
p = map.latLngToLayerPoint(overlay._corners[i]).subtract(center); | ||
q = new L.Point( | ||
Math.cos(angle)*p.x - Math.sin(angle)*p.y, | ||
Math.sin(angle)*p.x + Math.cos(angle)*p.y | ||
); | ||
overlay._corners[i] = map.layerPointToLatLng(q.add(center)); | ||
} | ||
for (i = 0; i < 4; i++) { | ||
p = map.latLngToLayerPoint(overlay._corners[i]).subtract(center); | ||
q = new L.Point( | ||
Math.cos(angle) * p.x - Math.sin(angle) * p.y, | ||
Math.sin(angle) * p.x + Math.cos(angle) * p.y | ||
); | ||
overlay._corners[i] = map.layerPointToLatLng(q.add(center)); | ||
} | ||
overlay._reset(); | ||
}, | ||
overlay._reset(); | ||
}, | ||
_scaleBy: function(scale) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, p; | ||
_scaleBy: function(scale) { | ||
var overlay = this._overlay, | ||
map = overlay._map, | ||
center = map.latLngToLayerPoint(overlay.getCenter()), | ||
i, | ||
p; | ||
for (i = 0; i < 4; i++) { | ||
p = map.latLngToLayerPoint(overlay._corners[i]) | ||
.subtract(center) | ||
.multiplyBy(scale) | ||
.add(center); | ||
overlay._corners[i] = map.layerPointToLatLng(p); | ||
} | ||
for (i = 0; i < 4; i++) { | ||
p = map | ||
.latLngToLayerPoint(overlay._corners[i]) | ||
.subtract(center) | ||
.multiplyBy(scale) | ||
.add(center); | ||
overlay._corners[i] = map.layerPointToLatLng(p); | ||
} | ||
overlay._reset(); | ||
}, | ||
overlay._reset(); | ||
}, | ||
_enableDragging: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
_enableDragging: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
this.dragging = new L.Draggable(overlay._image); | ||
this.dragging.enable(); | ||
this.dragging = new L.Draggable(overlay._image); | ||
this.dragging.enable(); | ||
/* Hide toolbars and markers while dragging; click will re-show it */ | ||
this.dragging.on('dragstart', function () { | ||
overlay.fire('dragstart'); | ||
this._hideToolbar(); | ||
}, this); | ||
/* Hide toolbars and markers while dragging; click will re-show it */ | ||
this.dragging.on("dragstart", function() { | ||
overlay.fire("dragstart"); | ||
this._hideToolbar(); | ||
},this); | ||
/* | ||
* Adjust default behavior of L.Draggable. | ||
* By default, L.Draggable overwrites the CSS3 distort transform | ||
* that we want when it calls L.DomUtil.setPosition. | ||
*/ | ||
this.dragging._updatePosition = function() { | ||
var delta = this._newPos.subtract(map.latLngToLayerPoint(overlay._corners[0])), | ||
currentPoint, i; | ||
/* | ||
* Adjust default behavior of L.Draggable. | ||
* By default, L.Draggable overwrites the CSS3 distort transform | ||
* that we want when it calls L.DomUtil.setPosition. | ||
*/ | ||
this.dragging._updatePosition = function() { | ||
var delta = this._newPos.subtract( | ||
map.latLngToLayerPoint(overlay._corners[0]) | ||
), | ||
currentPoint, | ||
i; | ||
this.fire('predrag'); | ||
this.fire("predrag"); | ||
for (i = 0; i < 4; i++) { | ||
currentPoint = map.latLngToLayerPoint(overlay._corners[i]); | ||
overlay._corners[i] = map.layerPointToLatLng(currentPoint.add(delta)); | ||
for (i = 0; i < 4; i++) { | ||
currentPoint = map.latLngToLayerPoint(overlay._corners[i]); | ||
overlay._corners[i] = map.layerPointToLatLng(currentPoint.add(delta)); | ||
} | ||
overlay._reset(); | ||
overlay.fire('update'); | ||
overlay.fire('drag'); | ||
overlay._reset(); | ||
overlay.fire("update"); | ||
overlay.fire("drag"); | ||
this.fire('drag'); | ||
}; | ||
}, | ||
this.fire("drag"); | ||
}; | ||
}, | ||
_onKeyDown: function(event) { | ||
var keymap = this.options.keymap, | ||
handlerName = keymap[event.which]; | ||
_onKeyDown: function(event) { | ||
var keymap = this.options.keymap, | ||
handlerName = keymap[event.which]; | ||
if (handlerName !== undefined && this._overlay.options.suppressToolbar !== true) { | ||
this[handlerName].call(this); | ||
} | ||
}, | ||
if (handlerName !== undefined && this._overlay.options.suppressToolbar !== true) { | ||
this[handlerName].call(this); | ||
} | ||
}, | ||
_toggleRotateDistort: function() { | ||
var map = this._overlay._map; | ||
_toggleRotateDistort: function() { | ||
var map = this._overlay._map; | ||
map.removeLayer(this._handles[this._mode]); | ||
map.removeLayer(this._handles[this._mode]); | ||
/* Switch mode. */ | ||
if (this._mode === 'rotate') { this._mode = 'distort'; } | ||
else { this._mode = 'rotate'; } | ||
/* Switch mode. */ | ||
if (this._mode === "rotate") { this._mode = "distort"; } | ||
else { this._mode = "rotate"; } | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
this._showToolbar(); | ||
_toggleScale: function() { | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
_toggleScale: function() { | ||
var map = this._overlay._map; | ||
if (this._mode === "lock") { return; } | ||
map.removeLayer(this._handles[this._mode]); | ||
this._mode = 'scale'; | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
_toggleRotate: function() { | ||
if (this._mode === "scale") { this._mode = "distort"; } | ||
else { this._mode = "scale"; } | ||
this._showToolbar(); | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
_toggleRotate: function() { | ||
var map = this._overlay._map; | ||
if (this._mode === "lock") { return; } | ||
map.removeLayer(this._handles[this._mode]); | ||
this._mode = 'rotateStandalone'; | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
this._mode = "rotateStandalone"; | ||
_toggleTransparency: function() { | ||
var image = this._overlay._image, | ||
opacity; | ||
this._showToolbar(); | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
this._transparent = !this._transparent; | ||
opacity = this._transparent ? this.options.opacity : 1; | ||
_toggleTransparency: function() { | ||
var image = this._overlay._image, | ||
opacity; | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute('opacity', opacity); | ||
}, | ||
this._transparent = !this._transparent; | ||
opacity = this._transparent ? this.options.opacity : 1; | ||
_toggleOutline: function() { | ||
var image = this._overlay._image, | ||
opacity, outline; | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute("opacity", opacity); | ||
}, | ||
this._outlined = !this._outlined; | ||
opacity = this._outlined ? this.options.opacity / 2 : 1; | ||
outline = this._outlined ? this.options.outline : 'none'; | ||
_toggleOutline: function() { | ||
var image = this._overlay._image, | ||
opacity, | ||
outline; | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute('opacity', opacity); | ||
this._outlined = !this._outlined; | ||
opacity = this._outlined ? this.options.opacity / 2 : 1; | ||
outline = this._outlined ? this.options.outline : "none"; | ||
image.style.outline = outline; | ||
}, | ||
L.DomUtil.setOpacity(image, opacity); | ||
image.setAttribute("opacity", opacity); | ||
_sendUp: function() { | ||
this._overlay.bringToFront(); | ||
}, | ||
image.style.outline = outline; | ||
}, | ||
_sendDown: function() { | ||
this._overlay.bringToBack(); | ||
}, | ||
_sendUp: function() { | ||
this._overlay.bringToFront(); | ||
}, | ||
_toggleLock: function() { | ||
var map = this._overlay._map; | ||
_sendDown: function() { | ||
this._overlay.bringToBack(); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
/* Switch mode. */ | ||
if (this._mode === 'lock') { | ||
this._mode = 'distort'; | ||
this._enableDragging(); | ||
} else { | ||
this._mode = 'lock'; | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
} | ||
_toggleLock: function() { | ||
var map = this._overlay._map; | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
map.removeLayer(this._handles[this._mode]); | ||
/* Switch mode. */ | ||
if (this._mode === "lock") { | ||
this._mode = "distort"; | ||
this._enableDragging(); | ||
} else { | ||
this._mode = "lock"; | ||
if (this.dragging) { this.dragging.disable(); } | ||
delete this.dragging; | ||
} | ||
_select: function (event) { | ||
this._showToolbar(event); | ||
this._showMarkers(); | ||
map.addLayer(this._handles[this._mode]); | ||
}, | ||
L.DomEvent.stopPropagation(event); | ||
}, | ||
_select: function(event) { | ||
this._showToolbar(event); | ||
this._showMarkers(); | ||
_deselect: function (event) { | ||
this._hideToolbar(event); | ||
this._hideMarkers(); | ||
}, | ||
L.DomEvent.stopPropagation(event); | ||
}, | ||
_hideToolbar: function() { | ||
var map = this._overlay._map; | ||
if (this.toolbar) { | ||
map.removeLayer(this.toolbar); | ||
this.toolbar = false; | ||
} | ||
}, | ||
_deselect: function(event) { | ||
this._hideToolbar(event); | ||
this._hideMarkers(); | ||
}, | ||
_showMarkers: function() { | ||
if (this._mode === 'lock') { return; } | ||
this._distortHandles.eachLayer(function (layer) { | ||
layer.setOpacity(1); | ||
layer.dragging.enable(); | ||
layer.options.draggable = true; | ||
}); | ||
}, | ||
_hideToolbar: function() { | ||
var map = this._overlay._map; | ||
if (this.toolbar) { | ||
map.removeLayer(this.toolbar); | ||
this.toolbar = false; | ||
} | ||
}, | ||
_hideMarkers: function() { | ||
this._distortHandles.eachLayer(function (layer) { | ||
var drag = layer.dragging, | ||
opts = layer.options; | ||
_showMarkers: function() { | ||
if (this._mode === "lock") { return; } | ||
var currentHandle = this._handles[this._mode]; | ||
currentHandle.eachLayer(function(layer) { | ||
layer.setOpacity(1); | ||
layer.dragging.enable(); | ||
layer.options.draggable = true; | ||
}); | ||
}, | ||
layer.setOpacity(0); | ||
if (drag) { drag.disable(); } | ||
if (opts.draggable) { opts.draggable = false; } | ||
}); | ||
}, | ||
// TODO: toolbar for multiple image selection | ||
_showToolbar: function(event) { | ||
var overlay = this._overlay, | ||
target = event.target, | ||
map = overlay._map; | ||
_hideMarkers: function() { | ||
var currentHandle = this._handles[this._mode]; | ||
currentHandle.eachLayer(function(layer) { | ||
var drag = layer.dragging, | ||
opts = layer.options; | ||
/* Ensure that there is only ever one toolbar attached to each image. */ | ||
this._hideToolbar(); | ||
var point; | ||
if (event.containerPoint) { point = event.containerPoint; } | ||
else { point = target._leaflet_pos; } | ||
var raised_point = map.containerPointToLatLng(new L.Point(point.x,point.y-20)); | ||
raised_point.lng = overlay.getCenter().lng; | ||
if (this._overlay.options.suppressToolbar !== true) { | ||
this.toolbar = new L.DistortableImage.EditToolbar(raised_point).addTo(map, overlay); | ||
overlay.fire('toolbar:created'); | ||
} | ||
}, | ||
layer.setOpacity(0); | ||
if (drag) { | ||
drag.disable(); | ||
} | ||
if (opts.draggable) { | ||
opts.draggable = false; | ||
} | ||
}); | ||
}, | ||
_removeOverlay: function () { | ||
// TODO: toolbar for multiple image selection | ||
_showToolbar: function() { | ||
var overlay = this._overlay, | ||
map = overlay._map; | ||
/* Ensure that there is only ever one toolbar attached to each image. */ | ||
this._hideToolbar(); | ||
//Find the topmost point on the image. | ||
var corners = overlay.getCorners(); | ||
var maxLat = -Infinity; | ||
for (var i = 0; i < corners.length; i++) { | ||
if (corners[i].lat > maxLat) { | ||
maxLat = corners[i].lat; | ||
} | ||
} | ||
//Longitude is based on the centroid of the image. | ||
var raised_point = overlay.getCenter(); | ||
raised_point.lat = maxLat; | ||
if (this._overlay.options.suppressToolbar !== true) { | ||
this.toolbar = new L.DistortableImage.EditToolbar(raised_point).addTo( | ||
map, | ||
overlay | ||
); | ||
overlay.fire("toolbar:created"); | ||
} | ||
}, | ||
_removeOverlay: function() { | ||
var overlay = this._overlay; | ||
@@ -356,105 +402,100 @@ if (this._mode !== "lock") { | ||
if (choice) { | ||
this._hideToolbar(); | ||
this._hideToolbar(); | ||
overlay._map.removeLayer(overlay); | ||
overlay.fire('delete'); | ||
overlay.fire("delete"); | ||
this.disable(); | ||
} | ||
} | ||
}, | ||
// compare this to using overlay zIndex | ||
_toggleOrder: function () { | ||
if (this._toggledImage) { | ||
this._overlay.bringToFront(); | ||
this._toggledImage = false; | ||
} | ||
else { | ||
this._overlay.bringToBack(); | ||
this._toggledImage = true; | ||
} | ||
}, | ||
}, | ||
// Based on https://github.com/publiclab/mapknitter/blob/8d94132c81b3040ae0d0b4627e685ff75275b416/app/assets/javascripts/mapknitter/Map.js#L47-L82 | ||
_toggleExport: function (){ | ||
var map = this._overlay._map; | ||
var overlay = this._overlay; | ||
// compare this to using overlay zIndex | ||
_toggleOrder: function() { | ||
if (this._toggledImage) { | ||
this._overlay.bringToFront(); | ||
this._toggledImage = false; | ||
} else { | ||
this._overlay.bringToBack(); | ||
this._toggledImage = true; | ||
} | ||
}, | ||
// make a new image | ||
var downloadable = new Image(); | ||
// Based on https://github.com/publiclab/mapknitter/blob/8d94132c81b3040ae0d0b4627e685ff75275b416/app/assets/javascripts/mapknitter/Map.js#L47-L82 | ||
_toggleExport: function() { | ||
var map = this._overlay._map; | ||
var overlay = this._overlay; | ||
downloadable.id = downloadable.id || "tempId12345"; | ||
$('body').append(downloadable); | ||
// make a new image | ||
var downloadable = new Image(); | ||
downloadable.onload = function onLoadDownloadableImage() { | ||
downloadable.id = downloadable.id || "tempId12345"; | ||
$("body").append(downloadable); | ||
var height = downloadable.height, | ||
width = downloadable.width, | ||
nw = map.latLngToLayerPoint(overlay._corners[0]), | ||
ne = map.latLngToLayerPoint(overlay._corners[1]), | ||
sw = map.latLngToLayerPoint(overlay._corners[2]), | ||
se = map.latLngToLayerPoint(overlay._corners[3]); | ||
downloadable.onload = function onLoadDownloadableImage() { | ||
var height = downloadable.height, | ||
width = downloadable.width, | ||
nw = map.latLngToLayerPoint(overlay._corners[0]), | ||
ne = map.latLngToLayerPoint(overlay._corners[1]), | ||
sw = map.latLngToLayerPoint(overlay._corners[2]), | ||
se = map.latLngToLayerPoint(overlay._corners[3]); | ||
// I think this is to move the image to the upper left corner, | ||
// jywarren: i think we may need these or the image goes off the edge of the canvas | ||
// jywarren: but these seem to break the distortion math... | ||
// I think this is to move the image to the upper left corner, | ||
// jywarren: i think we may need these or the image goes off the edge of the canvas | ||
// jywarren: but these seem to break the distortion math... | ||
// jywarren: i think it should be rejiggered so it | ||
// finds the most negative values of x and y and then | ||
// adds those to all coordinates | ||
// jywarren: i think it should be rejiggered so it | ||
// finds the most negative values of x and y and then | ||
// adds those to all coordinates | ||
//nw.x -= nw.x; | ||
//ne.x -= nw.x; | ||
//se.x -= nw.x; | ||
//sw.x -= nw.x; | ||
//nw.x -= nw.x; | ||
//ne.x -= nw.x; | ||
//se.x -= nw.x; | ||
//sw.x -= nw.x; | ||
//nw.y -= nw.y; | ||
//ne.y -= nw.y; | ||
//se.y -= nw.y; | ||
//sw.y -= nw.y; | ||
//nw.y -= nw.y; | ||
//ne.y -= nw.y; | ||
//se.y -= nw.y; | ||
//sw.y -= nw.y; | ||
// run once warping is complete | ||
downloadable.onload = function() { | ||
$(downloadable).remove(); | ||
}; | ||
// run once warping is complete | ||
downloadable.onload = function() { | ||
$(downloadable).remove(); | ||
}; | ||
if (window && window.hasOwnProperty('warpWebGl')) { | ||
warpWebGl( | ||
downloadable.id, | ||
[0, 0, width, 0, width, height, 0, height], | ||
[nw.x, nw.y, ne.x, ne.y, se.x, se.y, sw.x, sw.y], | ||
true // trigger download | ||
); | ||
} | ||
if (window && window.hasOwnProperty("warpWebGl")) { | ||
warpWebGl( | ||
downloadable.id, | ||
[0, 0, width, 0, width, height, 0, height], | ||
[nw.x, nw.y, ne.x, ne.y, se.x, se.y, sw.x, sw.y], | ||
true // trigger download | ||
); | ||
} | ||
}; | ||
}; | ||
downloadable.src = overlay.options.fullResolutionSrc || overlay._image.src; | ||
}, | ||
downloadable.src = overlay.options.fullResolutionSrc || overlay._image.src; | ||
}, | ||
toggleIsolate: function() { | ||
// this.isolated = !this.isolated; | ||
// if (this.isolated) { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = false; | ||
// img.setOpacity(1); | ||
// }); | ||
// } else { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = true; | ||
// img.setOpacity(0); | ||
// }); | ||
// } | ||
// this.hidden = false; | ||
// this.setOpacity(1); | ||
} | ||
toggleIsolate: function() { | ||
// this.isolated = !this.isolated; | ||
// if (this.isolated) { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = false; | ||
// img.setOpacity(1); | ||
// }); | ||
// } else { | ||
// $.each($L.images,function(i,img) { | ||
// img.hidden = true; | ||
// img.setOpacity(0); | ||
// }); | ||
// } | ||
// this.hidden = false; | ||
// this.setOpacity(1); | ||
} | ||
}); | ||
L.DistortableImageOverlay.addInitHook(function() { | ||
this.editing = new L.DistortableImage.Edit(this); | ||
this.editing = new L.DistortableImage.Edit(this); | ||
if (this.options.editable) { | ||
L.DomEvent.on(this._image, 'load', this.editing.enable, this.editing); | ||
} | ||
if (this.options.editable) { | ||
L.DomEvent.on(this._image, "load", this.editing.enable, this.editing); | ||
} | ||
@@ -464,2 +505,2 @@ this.on('remove', function () { | ||
}); | ||
}); | ||
}); |
@@ -91,2 +91,3 @@ L.DistortableImage = L.DistortableImage || {}; | ||
editing._toggleRotateDistort(); | ||
editing._showToolbar(); | ||
this.disable(); | ||
@@ -158,5 +159,27 @@ } | ||
EnableEXIF, | ||
ToggleOrder | ||
] | ||
} | ||
ToggleOrder | ||
] | ||
}, | ||
// todo: move to some sort of util class, these methods could be useful in future | ||
_rotateToolbarAngleDeg: function(angle) { | ||
var div = this._container, | ||
divStyle = div.style; | ||
var oldTransform = divStyle.transform; | ||
divStyle.transform = oldTransform + "rotate(" + angle + "deg)"; | ||
divStyle.transformOrigin = "1080% 650%"; | ||
this._rotateToolbarIcons(angle); | ||
}, | ||
_rotateToolbarIcons: function(angle) { | ||
var icons = document.querySelectorAll(".fa"); | ||
for (var i = 0; i < icons.length; i++) { | ||
icons.item(i).style.transform = "rotate(" + -angle + "deg)"; | ||
} | ||
}, | ||
}); |
L.DistortHandle = L.EditHandle.extend({ | ||
options: { | ||
TYPE: 'distort', | ||
icon: new L.Icon({ | ||
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAChSURBVO3BIU4DURgGwNkvL2B6AkQTLBqP4QCoSm7DDXoBLBZHDbfgICAIZjEV3YTn9uVHdMZZtcnCfI13bIzxg0emg6Nm6QVbYz3jylEsXRrvwommb49X67jFkz80fR9Mb1YxTzqiWBSLYlEsikWxKBbFolgUi2JRLIpFsSgWxaJY03fHHOu40dH07bAzWCx9Ge/TiWbpHgdsjPGNB2f/yS+7xRCyiiZPJQAAAABJRU5ErkJggg==', | ||
iconSize: [32, 32], | ||
iconAnchor: [16, 16]} | ||
) | ||
}, | ||
options: { | ||
TYPE: "distort", | ||
icon: new L.Icon({ | ||
iconUrl: | ||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAklEQVR4AewaftIAAAChSURBVO3BIU4DURgGwNkvL2B6AkQTLBqP4QCoSm7DDXoBLBZHDbfgICAIZjEV3YTn9uVHdMZZtcnCfI13bIzxg0emg6Nm6QVbYz3jylEsXRrvwommb49X67jFkz80fR9Mb1YxTzqiWBSLYlEsikWxKBbFolgUi2JRLIpFsSgWxaJY03fHHOu40dH07bAzWCx9Ge/TiWbpHgdsjPGNB2f/yS+7xRCyiiZPJQAAAABJRU5ErkJggg==", | ||
iconSize: [32, 32], | ||
iconAnchor: [16, 16] | ||
}) | ||
}, | ||
updateHandle: function() { | ||
this.setLatLng(this._handled._corners[this._corner]); | ||
updateHandle: function() { | ||
this.setLatLng(this._handled._corners[this._corner]); | ||
}, | ||
_onHandleDrag: function() { | ||
this._handled._updateCorner(this._corner, this.getLatLng()); | ||
_onHandleDrag: function() { | ||
this._handled._updateCorner(this._corner, this.getLatLng()); | ||
this._handled.fire('update'); | ||
} | ||
this._handled.fire("update"); | ||
this._handled.editing._showToolbar(); | ||
} | ||
}); |
L.EditHandle = L.Marker.extend({ | ||
initialize: function(overlay, corner, options) { | ||
var markerOptions, | ||
latlng = overlay._corners[corner]; | ||
initialize: function(overlay, corner, options) { | ||
var markerOptions, | ||
latlng = overlay._corners[corner]; | ||
L.setOptions(this, options); | ||
L.setOptions(this, options); | ||
this._handled = overlay; | ||
this._corner = corner; | ||
this._handled = overlay; | ||
this._corner = corner; | ||
markerOptions = { | ||
draggable: true, | ||
zIndexOffset: 10 | ||
}; | ||
markerOptions = { | ||
draggable: true, | ||
zIndexOffset: 10 | ||
}; | ||
if (options && options.hasOwnProperty("draggable")) { | ||
markerOptions.draggable = options.draggable; | ||
} | ||
if (options && options.hasOwnProperty('draggable')) { | ||
markerOptions.draggable = options.draggable; | ||
} | ||
L.Marker.prototype.initialize.call(this, latlng, markerOptions); | ||
}, | ||
L.Marker.prototype.initialize.call(this, latlng, markerOptions); | ||
}, | ||
onAdd: function(map) { | ||
L.Marker.prototype.onAdd.call(this, map); | ||
this._bindListeners(); | ||
onAdd: function(map) { | ||
L.Marker.prototype.onAdd.call(this, map); | ||
this._bindListeners(); | ||
this.updateHandle(); | ||
}, | ||
this.updateHandle(); | ||
onRemove: function(map) { | ||
this._unbindListeners(); | ||
L.Marker.prototype.onRemove.call(this, map); | ||
}, | ||
_onHandleDragStart: function() { | ||
this._handled.fire("editstart"); | ||
}, | ||
onRemove: function(map) { | ||
this._unbindListeners(); | ||
L.Marker.prototype.onRemove.call(this, map); | ||
_onHandleDragEnd: function() { | ||
this._fireEdit(); | ||
}, | ||
_onHandleDragStart: function() { | ||
this._handled.fire('editstart'); | ||
}, | ||
_fireEdit: function() { | ||
this._handled.edited = true; | ||
this._handled.fire("edit"); | ||
}, | ||
_onHandleDragEnd: function() { | ||
this._fireEdit(); | ||
}, | ||
_bindListeners: function() { | ||
this.on( | ||
{ | ||
dragstart: this._onHandleDragStart, | ||
drag: this._onHandleDrag, | ||
dragend: this._onHandleDragEnd | ||
}, | ||
this | ||
); | ||
_fireEdit: function() { | ||
this._handled.edited = true; | ||
this._handled.fire('edit'); | ||
}, | ||
this._handled._map.on("zoomend", this.updateHandle, this); | ||
_bindListeners: function() { | ||
this.on({ | ||
'dragstart': this._onHandleDragStart, | ||
'drag': this._onHandleDrag, | ||
'dragend': this._onHandleDragEnd | ||
}, this); | ||
this._handled.on("update", this.updateHandle, this); | ||
}, | ||
this._handled._map.on('zoomend', this.updateHandle, this); | ||
_unbindListeners: function() { | ||
this.off( | ||
{ | ||
dragstart: this._onHandleDragStart, | ||
drag: this._onHandleDrag, | ||
dragend: this._onHandleDragEnd | ||
}, | ||
this | ||
); | ||
this._handled.on('update', this.updateHandle, this); | ||
}, | ||
_unbindListeners: function() { | ||
this.off({ | ||
'dragstart': this._onHandleDragStart, | ||
'drag': this._onHandleDrag, | ||
'dragend': this._onHandleDragEnd | ||
}, this); | ||
this._handled._map.off('zoomend', this.updateHandle, this); | ||
this._handled.off('update', this.updateHandle, this); | ||
} | ||
this._handled._map.off("zoomend", this.updateHandle, this); | ||
this._handled.off("update", this.updateHandle, this); | ||
} | ||
}); |
@@ -19,4 +19,2 @@ L.RotateAndScaleHandle = L.EditHandle.extend({ | ||
overlay.editing._hideToolbar(); | ||
overlay.editing._rotateBy(angle); | ||
@@ -39,2 +37,4 @@ | ||
this._handled.editing._showToolbar(); | ||
}, | ||
@@ -41,0 +41,0 @@ |
@@ -17,7 +17,7 @@ L.RotateHandle = L.EditHandle.extend({ | ||
overlay.editing._hideToolbar(); | ||
overlay.editing._rotateBy(angle); | ||
overlay.editing._rotateBy(angle); | ||
overlay.fire('update'); | ||
overlay.fire('update'); | ||
this._handled.editing._showToolbar(); | ||
}, | ||
@@ -24,0 +24,0 @@ |
@@ -21,2 +21,4 @@ L.ScaleHandle = L.EditHandle.extend({ | ||
overlay.fire('update'); | ||
this._handled.editing._showToolbar(); | ||
}, | ||
@@ -23,0 +25,0 @@ |
@@ -6,2 +6,20 @@ beforeEach(function() { | ||
/* Chain global testing utilites below to chai*/ | ||
/* | ||
* simulate mouse events manually in the DOM on a passed element. | ||
* - (Most) useful parameters: | ||
* 1) type: string - this is for 'mousedown'. Other options include 'click', 'dblick', 'mouseup', 'mouseover', 'mouseout', 'mousemove | ||
* 2) the booleans after the list of 0s simulate the presence (or lack of) the following keys (in order) during the mouse event: 'ctrlKey', 'altKey', 'shiftKey', 'metaKey' | ||
*/ | ||
chai.simulateCommandMousedown = function simulateCommandMousedownFn(el) { | ||
if (document.createEvent) { | ||
var e = document.createEvent('MouseEvents'); | ||
e.initMouseEvent('mousedown', true, true, window, 0, 0, 0, 0, 0, true, false, false, true, 0, null); | ||
return el.dispatchEvent(e); | ||
} | ||
}; | ||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ | ||
/* | ||
@@ -8,0 +26,0 @@ * Asserts that two latlngs are close. |
@@ -1,10 +0,1 @@ | ||
function simulateCommandMousedown(el) { | ||
if (document.createEvent) { | ||
var e = document.createEvent('MouseEvents'); | ||
e.initMouseEvent('mousedown', true, true, window, | ||
0, 0, 0, 0, 0, true, false, false, true, 0, null); | ||
return el.dispatchEvent(e); | ||
} | ||
}; | ||
describe("L.DistortableCollection", function () { | ||
@@ -17,5 +8,5 @@ var map, | ||
beforeEach(function (done) { | ||
map = new L.Map(L.DomUtil.create('div', '', document.body)).setView([41.7896, -87.5996], 15); | ||
map = L.map(L.DomUtil.create('div', '', document.body)).setView([41.7896, -87.5996], 15); | ||
overlay = new L.DistortableImageOverlay('/examples/example.png', { | ||
overlay = L.distortableImageOverlay('/examples/example.png', { | ||
corners: [ | ||
@@ -29,3 +20,3 @@ new L.LatLng(41.7934, -87.6052), | ||
overlay2 = new L.DistortableImageOverlay('/examples/example.png', { | ||
overlay2 = L.distortableImageOverlay('/examples/example.png', { | ||
corners: [ | ||
@@ -58,3 +49,3 @@ new L.LatLng(41.7934, -87.6050), | ||
describe("_deselectAll", function () { | ||
describe("#_deselectAll", function () { | ||
it("Should deselect all images on map click", function() { | ||
@@ -74,6 +65,6 @@ L.DomUtil.addClass(overlay.getElement(), "selected"); | ||
describe("_toggleMultiSelect", function () { | ||
describe("#_toggleMultiSelect", function () { | ||
it("Should allow selection of multiple images on command + click", function() { | ||
simulateCommandMousedown(overlay.getElement()); | ||
simulateCommandMousedown(overlay2.getElement()); | ||
chai.simulateCommandMousedown(overlay.getElement()); | ||
chai.simulateCommandMousedown(overlay2.getElement()); | ||
@@ -91,3 +82,3 @@ var classStr = L.DomUtil.getClass(overlay.getElement()); | ||
simulateCommandMousedown(overlay.getElement()); | ||
chai.simulateCommandMousedown(overlay.getElement()); | ||
var classStr = L.DomUtil.getClass(overlay.getElement()); | ||
@@ -94,0 +85,0 @@ |
@@ -9,3 +9,3 @@ describe("L.DistortableImageOverlay", function() { | ||
map = new L.Map(mapContainer).setView([41.7896,-87.5996], 15); | ||
map = L.map(mapContainer).setView([41.7896,-87.5996], 15); | ||
@@ -18,3 +18,3 @@ /* Map and its containing elements need to have height and width set. */ | ||
distortable = new L.DistortableImageOverlay('/examples/example.png', { | ||
distortable = L.distortableImageOverlay('/examples/example.png', { | ||
corners: [ | ||
@@ -42,3 +42,3 @@ new L.LatLng(41.7934, -87.6052), | ||
describe("getCenter", function() { | ||
describe("#_getCenter", function() { | ||
it("Should return the center when the outline of the image is a rectangle.", function(done) { | ||
@@ -45,0 +45,0 @@ distortable.addTo(map); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1521407
49
3557
204