Skip to content

Commit

Permalink
#432 Image Overlay Fixes (#433)
Browse files Browse the repository at this point in the history
  • Loading branch information
tariqksoliman committed Oct 4, 2023
1 parent f5bc3f9 commit 44ed04f
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 172 deletions.
20 changes: 16 additions & 4 deletions src/essence/Basics/Layers_/LayerConstructors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1238,16 +1238,28 @@ const imageOverlays = (geojson, layerObj, leafletLayerObject) => {
L.imageTransform(imageSettings.image, anchors, {
opacity: 1,
clip: anchors,
id: `${layerObj.name}${
imageSettings.image
}${angle}${JSON.stringify(center)}`,
}),
])
},
}
let existingOn = null
if (L_.layers.attachments[L_.asLayerUUID(layerObj.name)])
existingOn =
L_.layers.attachments[L_.asLayerUUID(layerObj.name)]
.image_overlays.on

const isOn =
existingOn != null
? existingOn
: imageVar.initialVisibility != null
? imageVar.initialVisibility
: true
return imageShow === 'always'
? {
on:
imageVar.initialVisibility != null
? imageVar.initialVisibility
: true,
on: isOn,
layer: L.geoJson(geojson, leafletLayerObjectImageOverlay),
title: 'Map rendered image overlays.',
}
Expand Down
2 changes: 1 addition & 1 deletion src/essence/Basics/Layers_/Layers_.js
Original file line number Diff line number Diff line change
Expand Up @@ -2591,7 +2591,7 @@ const L_ = {
return
}
L_.syncSublayerData(layerName)
L_.globeLithoLayerHelper(L_.layersNamed[layerName])
L_.globeLithoLayerHelper(L_.layers.layer[layerName])
} else {
console.warn(
'Warning: Unable to update vector layer as it does not exist: ' +
Expand Down
292 changes: 158 additions & 134 deletions src/external/Leaflet/leaflet-imageoverlay-rotated.js
Original file line number Diff line number Diff line change
@@ -1,145 +1,169 @@

L.ImageOverlay.Rotated = L.ImageOverlay.extend({

initialize: function (image, topleft, topright, bottomleft, options) {

if (typeof(image) === 'string') {
this._url = image;
} else {
// Assume that the first parameter is an instance of HTMLImage or HTMLCanvas
this._rawImage = image;
}

this._topLeft = L.latLng(topleft);
this._topRight = L.latLng(topright);
this._bottomLeft = L.latLng(bottomleft);

L.setOptions(this, options);
},


onAdd: function (map) {
if (!this._image) {
this._initImage();

if (this.options.opacity < 1) {
this._updateOpacity();
}
}

if (this.options.interactive) {
L.DomUtil.addClass(this._rawImage, 'leaflet-interactive');
this.addInteractiveTarget(this._rawImage);
}

map.on('zoomend resetview', this._reset, this);

this.getPane().appendChild(this._image);
this._reset();
},


onRemove: function(map) {
map.off('zoomend resetview', this._reset, this);
L.ImageOverlay.prototype.onRemove.call(this, map);
initialize: function (image, topleft, topright, bottomleft, options) {
if (typeof image === 'string') {
this._url = image
} else {
// Assume that the first parameter is an instance of HTMLImage or HTMLCanvas
this._rawImage = image
}

this._topLeft = L.latLng(topleft)
this._topRight = L.latLng(topright)
this._bottomLeft = L.latLng(bottomleft)

L.setOptions(this, options)
},


_initImage: function () {
var img = this._rawImage;
if (this._url) {
img = L.DomUtil.create('img');
img.style.display = 'none'; // Hide while the first transform (zero or one frames) is being done

if (this.options.crossOrigin) {
img.crossOrigin = '';
}

img.src = this._url;
this._rawImage = img;
}
L.DomUtil.addClass(img, 'leaflet-image-layer');

// this._image is reused by some of the methods of the parent class and
// must keep the name, even if it is counter-intuitive.
var div = this._image = L.DomUtil.create('div',
'leaflet-image-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : ''));

div.appendChild(img);

div.onselectstart = L.Util.falseFn;
div.onmousemove = L.Util.falseFn;

img.onload = function(){
this._reset();
img.style.display = 'block';
this.fire('load');
}.bind(this);
onAdd: function (map) {
if (!this._image) {
this._initImage()

img.alt = this.options.alt;
},
if (this.options.opacity < 1) {
this._updateOpacity()
}
}

if (this.options.interactive) {
L.DomUtil.addClass(this._rawImage, 'leaflet-interactive')
this.addInteractiveTarget(this._rawImage)
}

_reset: function () {
var div = this._image;
map.on('zoomend resetview', this._reset, this)

// Project control points to container-pixel coordinates
var pxTopLeft = this._map.latLngToLayerPoint(this._topLeft);
var pxTopRight = this._map.latLngToLayerPoint(this._topRight);
var pxBottomLeft = this._map.latLngToLayerPoint(this._bottomLeft);

// Infer coordinate of bottom right
var pxBottomRight = pxTopRight.subtract(pxTopLeft).add(pxBottomLeft);

// pxBounds is mostly for positioning the <div> container
var pxBounds = L.bounds([pxTopLeft, pxTopRight, pxBottomLeft, pxBottomRight]);
var size = pxBounds.getSize();
var pxTopLeftInDiv = pxTopLeft.subtract(pxBounds.min);

// Calculate the skew angles, both in X and Y
var vectorX = pxTopRight.subtract(pxTopLeft);
var vectorY = pxBottomLeft.subtract(pxTopLeft);
var skewX = Math.atan2( vectorX.y, vectorX.x );
var skewY = Math.atan2( vectorY.x, vectorY.y );

// LatLngBounds used for animations
this._bounds = L.latLngBounds( this._map.layerPointToLatLng(pxBounds.min),
this._map.layerPointToLatLng(pxBounds.max) );

L.DomUtil.setPosition(div, pxBounds.min);

div.style.width = size.x + 'px';
div.style.height = size.y + 'px';

var imgW = this._rawImage.width;
var imgH = this._rawImage.height;
if (!imgW || !imgH) {
return; // Probably because the image hasn't loaded yet.
}

var scaleX = pxTopLeft.distanceTo(pxTopRight) / imgW * Math.cos(skewX);
var scaleY = pxTopLeft.distanceTo(pxBottomLeft) / imgH * Math.cos(skewY);

this._rawImage.style.transformOrigin = '0 0';

this._rawImage.style.transform =
'translate(' + pxTopLeftInDiv.x + 'px, ' + pxTopLeftInDiv.y + 'px)' +
'skew(' + skewY + 'rad, ' + skewX + 'rad) ' +
'scale(' + scaleX + ', ' + scaleY + ') ';
},


reposition: function(topleft, topright, bottomleft) {
this._topLeft = L.latLng(topleft);
this._topRight = L.latLng(topright);
this._bottomLeft = L.latLng(bottomleft);
this._reset();
}
this.getPane().appendChild(this._image)
this._reset()
},

});
onRemove: function (map) {
map.off('zoomend resetview', this._reset, this)
L.ImageOverlay.prototype.onRemove.call(this, map)
},

_initImage: function () {
var img = this._rawImage
if (this._url) {
img = L.DomUtil.create('img')
img.style.display = 'none' // Hide while the first transform (zero or one frames) is being done

if (this.options.crossOrigin) {
img.crossOrigin = ''
}

img.src = this._url
this._rawImage = img
}
L.DomUtil.addClass(img, 'leaflet-image-layer')

// this._image is reused by some of the methods of the parent class and
// must keep the name, even if it is counter-intuitive.
var div = (this._image = L.DomUtil.create(
'div',
'leaflet-image-layer ' +
(this._zoomAnimated ? 'leaflet-zoom-animated' : '')
))

div.appendChild(img)

div.onselectstart = L.Util.falseFn
div.onmousemove = L.Util.falseFn

img.onload = function () {
this._reset()
img.style.display = 'block'
this.fire('load')
}.bind(this)

img.alt = this.options.alt
},

_reset: function () {
var div = this._image

// Project control points to container-pixel coordinates
var pxTopLeft = this._map.latLngToLayerPoint(this._topLeft)
var pxTopRight = this._map.latLngToLayerPoint(this._topRight)
var pxBottomLeft = this._map.latLngToLayerPoint(this._bottomLeft)

// Infer coordinate of bottom right
var pxBottomRight = pxTopRight.subtract(pxTopLeft).add(pxBottomLeft)

// pxBounds is mostly for positioning the <div> container
var pxBounds = L.bounds([
pxTopLeft,
pxTopRight,
pxBottomLeft,
pxBottomRight,
])
var size = pxBounds.getSize()
var pxTopLeftInDiv = pxTopLeft.subtract(pxBounds.min)

// Calculate the skew angles, both in X and Y
var vectorX = pxTopRight.subtract(pxTopLeft)
var vectorY = pxBottomLeft.subtract(pxTopLeft)
var skewX = Math.atan2(vectorX.y, vectorX.x)
var skewY = Math.atan2(vectorY.x, vectorY.y)

// LatLngBounds used for animations
this._bounds = L.latLngBounds(
this._map.layerPointToLatLng(pxBounds.min),
this._map.layerPointToLatLng(pxBounds.max)
)

L.DomUtil.setPosition(div, pxBounds.min)

div.style.width = size.x + 'px'
div.style.height = size.y + 'px'

var imgW = this._rawImage.width
var imgH = this._rawImage.height
if (!imgW || !imgH) {
return // Probably because the image hasn't loaded yet.
}

var scaleX = (pxTopLeft.distanceTo(pxTopRight) / imgW) * Math.cos(skewX)
var scaleY =
(pxTopLeft.distanceTo(pxBottomLeft) / imgH) * Math.cos(skewY)

this._rawImage.style.transformOrigin = '0 0'

this._rawImage.style.transform =
'translate(' +
pxTopLeftInDiv.x +
'px, ' +
pxTopLeftInDiv.y +
'px)' +
'skew(' +
skewY +
'rad, ' +
skewX +
'rad) ' +
'scale(' +
scaleX +
', ' +
scaleY +
') '
},

L.imageOverlay.rotated = function(imgSrc, topleft, topright, bottomleft, options) {
return new L.ImageOverlay.Rotated(imgSrc, topleft, topright, bottomleft, options);
};
reposition: function (topleft, topright, bottomleft) {
this._topLeft = L.latLng(topleft)
this._topRight = L.latLng(topright)
this._bottomLeft = L.latLng(bottomleft)
this._reset()
},
})

L.imageOverlay.rotated = function (
imgSrc,
topleft,
topright,
bottomleft,
options
) {
return new L.ImageOverlay.Rotated(
imgSrc,
topleft,
topright,
bottomleft,
options
)
}
Loading

0 comments on commit 44ed04f

Please sign in to comment.