Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaflet.Path.Transform #246

Open
pip-install-python opened this issue Jul 9, 2024 · 1 comment
Open

Leaflet.Path.Transform #246

pip-install-python opened this issue Jul 9, 2024 · 1 comment

Comments

@pip-install-python
Copy link

DashDiscord-ezgif com-crop

Thought this was interesting:
https://milevski.co/Leaflet.Path.Transform/

was able to set it up in dash component boilerplate and thought it could be a useful addition to dash leaflet. The idea I've started to come up with is to expand the functionality of the component to extend further with drag, rotate and resize. Not entirely sure how it would all be setup but wanted to share what I was able to get setup in my react.js file:

import React, { useEffect, useRef } from 'react';
import L from 'leaflet';
import 'leaflet-path-drag';
import 'leaflet-path-transform';
import 'leaflet/dist/leaflet.css';

const dlpt = ({ id}) => {
    const mapRef = useRef(null);
    const leafletMap = useRef(null);

    useEffect(() => {
    if (!leafletMap.current) {
        leafletMap.current = L.map(mapRef.current, {
            // eslint-disable-next-line no-magic-numbers
            center: [51.505, -0.09],
            zoom: 13
        });

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 19,
            attribution: '© OpenStreetMap'
        }).addTo(leafletMap.current);

        const polygon = L.polygon([
            // eslint-disable-next-line no-magic-numbers
            [51.509, -0.08],
            // eslint-disable-next-line no-magic-numbers
            [51.503, -0.06],
            // eslint-disable-next-line no-magic-numbers
            [51.51, -0.047]
        ], { transform: true, draggable: true }).addTo(leafletMap.current);

        // Enable transformations
        polygon.transform.enable({
            rotation: true,
            scaling: true
        });

        // Enable dragging
        polygon.dragging.enable();
    }
}, []);


    return <div id={id} ref={mapRef} style={{ height: '100vh', width: '100vw' }}></div>;
};

export default dlpt;

Ideally It would be awesome if it could extend to images as they are difficult to position as overlays on the map, this would allow the user a way ideally to add an image, resize it and rotate it over the map to get that perfect fit. I wasn't able to get the rotation to work but was able to get the resize and drag to work with:

const dlpt = ({ id }) => {
    const mapRef = useRef(null);
    const leafletMap = useRef(null);

    useEffect(() => {
        if (!leafletMap.current) {
            leafletMap.current = L.map(mapRef.current, {
                // eslint-disable-next-line no-magic-numbers
                center: [51.505, -0.09],
                zoom: 13
            });

            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19,
                attribution: '© OpenStreetMap'
            }).addTo(leafletMap.current);

            const imageUrl = 'https://store-images.s-microsoft.com/image/apps.36868.bfb0e2ee-be9e-4c73-807f-e0a7b805b1be.712aff5d-5800-47e0-97be-58d17ada3fb8.a46845e6-ce94-44cf-892b-54637c6fcf06';
            const centerLat = 51.5095;
            const centerLng = -0.0635;
            const latHeight = 0.001;
            // eslint-disable-next-line no-magic-numbers
            const lngWidth = latHeight * (800 / 600);

            const imageBounds = [
                [centerLat - latHeight / 2, centerLng - lngWidth / 2],
                [centerLat + latHeight / 2, centerLng + lngWidth / 2]
            ];

            const image = L.imageOverlay(imageUrl, imageBounds, {
                opacity: 0.7,
                interactive: true
            }).addTo(leafletMap.current);

            const polygon = L.polygon([
                [centerLat - latHeight / 2, centerLng - lngWidth / 2],
                [centerLat - latHeight / 2, centerLng + lngWidth / 2],
                [centerLat + latHeight / 2, centerLng + lngWidth / 2],
                [centerLat + latHeight / 2, centerLng - lngWidth / 2]
            ], {
                color: 'transparent',
                transform: true,
                draggable: true
            }).addTo(leafletMap.current);

            polygon.transform.enable({
                rotation: true,
                scaling: true
            });

            polygon.on('dragend transform', function (e) {
                const newBounds = polygon.getBounds();
                image.setBounds(newBounds);

                if (e.rotation) {
                    // eslint-disable-next-line no-magic-numbers
                    const rotationDegrees = e.rotation * (180 / Math.PI);
                    const imageElement = image.getElement();
                    imageElement.style.transformOrigin = 'center center';
                    imageElement.style.transform = `rotate(${rotationDegrees}deg)`;
                }
            });
        }
    }, []);

    return <div id={id} ref={mapRef} style={{ height: '100vh', width: '100vw' }}></div>;
};

export default dlpt;

Outside of maping this could also expand into an interesting concept of being able to create the same functionality of the mac app Freeform if built upon. Just exploratory and figured it was worth sharing.

cheers,
Pip

@emilhe
Copy link
Owner

emilhe commented Jul 22, 2024

This is an interesting concept. One way to integrate it would be to add properties to the existing svg components that would enable this behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants