Skip to content

Commit

Permalink
Polygon draw working
Browse files Browse the repository at this point in the history
  • Loading branch information
pierotofy committed Jul 29, 2024
1 parent 2046a6f commit 8813050
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 3 deletions.
Binary file added app/static/app/img/accept.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
207 changes: 204 additions & 3 deletions app/static/app/js/components/MapPreview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import exifr from '../vendor/exifr';
import '../vendor/leaflet/leaflet-markers-canvas';
import { _, interpolate } from '../classes/gettext';

const Colors = {
fill: '#fff',
stroke: '#1a1a1a'
};

class MapPreview extends React.Component {
static defaultProps = {
getFiles: null
Expand Down Expand Up @@ -47,12 +52,15 @@ class MapPreview extends React.Component {
maxZoom: 24
});

this.group = L.layerGroup();
this.group.addTo(this.map);

// For some reason, in production this class is not added (but we need it)
// leaflet bug?
$(this.container).addClass("leaflet-touch");

//add zoom control with your options
let zoomControl = Leaflet.control.zoom({
Leaflet.control.zoom({
position:'bottomleft'
}).addTo(this.map);

Expand Down Expand Up @@ -241,11 +249,204 @@ _('Example:'),
const { cropping } = this.state;

let crop = !cropping;
if (!crop) this.cropButton.blur();
if (!crop) {
if (this.captureMarker) {
this.captureMarker.off('click', this.handleMarkerClick);
this.captureMarker.off('dblclick', this.handleMarkerDblClick);
this.captureMarker.off('mousemove', this.handleMarkerMove);
this.captureMarker.off('contextmenu', this.handleMarkerContextMenu);

this.map.off('move', this.onMapMove);
this.map.off('resize', this.onMapResize);

this.group.removeLayer(this.captureMarker);
this.captureMarker = null;
}

if (this.acceptMarker) {
this.group.removeLayer(this.acceptMarker);
this.acceptMarker = null;
}
if (this.measureBoundary) {
this.group.removeLayer(this.measureBoundary);
this.measureBoundary = null;
}
if (this.measureArea) {
this.group.removeLayer(this.measureArea);
this.measureArea = null;
}
this.cropButton.blur();
}
else{
if (!this.captureMarker) {
this.captureMarker = L.marker(this.map.getCenter(), {
clickable: true,
zIndexOffset: 10001
}).setIcon(L.divIcon({
iconSize: this.map.getSize().multiplyBy(2),
className: "map-preview-marker-layer"
})).addTo(this.group);

this.captureMarker.on('click', this.handleMarkerClick);
this.captureMarker.on('dblclick', this.handleMarkerDblClick);
this.captureMarker.on('mousemove', this.handleMarkerMove);
this.captureMarker.on('contextmenu', this.handleMarkerContextMenu);

this.map.on('move', this.onMapMove);
this.map.on('resize', this.onMapResize);
}

if (this.polygon){
this.group.removeLayer(this.polygon);
this.polygon = null;
}

// Reset latlngs
this.latlngs = [];
}


this.setState({cropping: !cropping});
}

handleMarkerClick = e => {
L.DomEvent.stop(e);

const latlng = this.map.mouseEventToLatLng(e.originalEvent);
this.uniqueLatLonPush(latlng);

if (this.latlngs.length >= 1) {
if (!this.measureBoundary) {
this.measureBoundary = L.polyline(this.latlngs.concat(latlng), {
clickable: false,
color: Colors.stroke,
weight: 2,
opacity: 0.9,
fill: false,
}).addTo(this.group);
} else {
this.measureBoundary.setLatLngs(this.latlngs.concat(latlng));
}
}

if (this.latlngs.length >= 2) {
if (!this.measureArea) {
this.measureArea = L.polygon(this.latlngs.concat(latlng), {
clickable: false,
stroke: false,
fillColor: Colors.fill,
fillOpacity: 0.2,
}).addTo(this.group);
} else {
this.measureArea.setLatLngs(this.latlngs.concat(latlng));
}
}

if (this.latlngs.length >= 3) {
if (this.acceptMarker) {
this.group.removeLayer(this.acceptMarker);
this.acceptMarker = null;
}

const onAccept = e => {
L.DomEvent.stop(e);
this.confirmPolygon();
return false;
};

let acceptLatlng = this.latlngs[0];

this.acceptMarker = L.marker(acceptLatlng, {
icon: L.icon({
iconUrl: `/static/app/img/accept.png`,
iconSize: [20, 20],
iconAnchor: [10, 10],
className: "map-preview-accept-button",
}),
zIndexOffset: 99999
}).addTo(this.group)
.on("click", onAccept)
.on("contextmenu", onAccept);
}
};

confirmPolygon = () => {
if (this.latlngs.length >= 3){
const popupContainer = L.DomUtil.create('div');
popupContainer.className = "map-preview-delete";
const deleteLink = L.DomUtil.create('a');
deleteLink.href = "javascript:void(0)";
deleteLink.innerHTML = `<i class="fa fa-trash"></i> ${_("Delete")}`;
deleteLink.onclick = (e) => {
L.DomEvent.stop(e);
if (this.polygon){
this.group.removeLayer(this.polygon);
this.polygon = null;
}
};
popupContainer.appendChild(deleteLink);

this.polygon = L.polygon(this.latlngs, {
clickable: true,
weight: 3,
opacity: 0.9,
color: "#ffa716",
fillColor: "#ffa716",
fillOpacity: 0.2
}).bindPopup(popupContainer).addTo(this.group);
}

this.toggleCrop();
}

uniqueLatLonPush = latlng => {
if (this.latlngs.length === 0) this.latlngs.push(latlng);
else{
const last = this.latlngs[this.latlngs.length - 1];
if (last.lat !== latlng.lat && last.lng !== latlng.lng) this.latlngs.push(latlng);
}
};

handleMarkerDblClick = e => {
if (this.latlngs.length >= 2){
const latlng = this.map.mouseEventToLatLng(e.originalEvent);
this.uniqueLatLonPush(latlng);
this.confirmPolygon();
}
}

handleMarkerMove = e => {
const latlng = this.map.mouseEventToLatLng(e.originalEvent);
let lls = this.latlngs.concat(latlng);
lls.push(lls[0]);
if (this.measureBoundary) {
this.measureBoundary.setLatLngs(lls);
}
if (this.measureArea) {
this.measureArea.setLatLngs(lls);
}
}

handleMarkerContextMenu = e => {
if (this.latlngs.length >= 2){
const latlng = this.map.mouseEventToLatLng(e.originalEvent);
this.uniqueLatLonPush(latlng);
this.confirmPolygon();
}

return false;
}

onMapMove = () => {
if (this.captureMarker) this.captureMarker.setLatLng(this.map.getCenter());
};

onMapResize = () => {
if (this.captureMarker) this.captureMarker.setIcon(L.divIcon({
iconSize: this._map.getSize().multiplyBy(2)
}));
}

download = format => {
let output = "";
let filename = `images.${format}`;
Expand Down Expand Up @@ -288,7 +489,7 @@ _('Example:'),

{this.state.error === "" ?
<div className="crop-control">
<button ref={(domNode) => {this.cropButton = domNode; }} type="button" onClick={this.toggleCrop} className={"btn btn-sm " + (this.state.cropping ? "btn-default" : "btn-secondary")} title={_("Set Crop Area (optional)")}>
<button ref={(domNode) => {this.cropButton = domNode; }} type="button" onClick={this.toggleCrop} className={"btn btn-sm " + (this.state.cropping ? "btn-default" : "btn-secondary")} title={_("Set Reconstruction Area (optional)")}>
<i className="fa fa-crop-alt"></i>
</button>
</div>
Expand Down
17 changes: 17 additions & 0 deletions app/static/app/js/css/MapPreview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,25 @@
}

.leaflet-control-layers-expanded{
.leaflet-control-layers-base{
overflow: hidden;
}
height: 200px;
overflow: hidden;
}

.map-preview-marker-layer{
&:hover{
cursor: crosshair;
}
}

.map-preview-accept-button{
&:hover{
cursor: pointer;
}
}
.map-preview-delete{
min-width: 70px;
}
}

0 comments on commit 8813050

Please sign in to comment.