jmix-framework / jmix

Jmix framework
https://www.jmix.io
Apache License 2.0
706 stars 124 forks source link

Maps add-on with Flow UI #1985

Closed knstvk closed 1 year ago

KremnevDmitry commented 1 year ago

Liked Studio issues:

Flaurite commented 1 year ago

Gradle coordinates

To work with add-on in a project, add the following dependencies to build.gradle:

implementation 'io.jmix.maps:jmix-maps-starter'
implementation 'io.jmix.maps:jmix-maps-flowui-starter'

Quick start

  1. Add to your View descriptor XSD schema to work with geoMap component:
    xmlns:maps="http://jmix.io/schema/maps/ui"

    2) Add component:

    <maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:layers>
        <maps:tile>
            <maps:osmSource/>
        </maps:tile>
    </maps:layers>
    </maps:geoMap>

    3) Launch the application

Map component

The component based on OpenLayers 8.1.0 version. By default all API works with CRS - "EPSG:4326". Component takes coordinates and geometries from JTS Topology Suite library

Layers and Sources

Component has three layers.

TileLayer

Layer is to work with XYZ tiles and WMS. Supports three sources:

1) OsmSource - predefined source for showing OpenStreetMap tiles. See example with OsmSource above.

2) XyzSource - to work services that supports XYZ format in URL template.

<maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:layers>
        <maps:tile>
            <maps:xyzSource
                    url="https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=YOUR_API_KEY">
            </maps:xyzSource>
        </maps:tile>
    </maps:layers>
</maps:geoMap>

3) WmsSource - to work with services that supports WMS specification.

<maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:layers>
        <maps:tile>
            <maps:tileWmsSource attributions="See Copyright and License in used service"
                                url="http://your.wms.service/service?">
                <maps:parameters>
                    <maps:parameter name="layers" value="SEE_VALUE_IN_USED_SERVICE"/>
                </maps:parameters>
            </maps:tileWmsSource>
        </maps:tile>
    </maps:layers>
</maps:geoMap>

ImageLayer

Layer is to work with static image or WMS image.

ImageStaticSource - to work with static image from URL or from classpath. Example of showing image from URL (is taken from: OpenLayers :: examples - Static image):

<maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:mapView centerX="512" centerY="479" zoom="2">
        <maps:projection code="static-image"
                         units="PIXELS">
            <maps:extent minX="0" minY="0" maxX="1024" maxY="968"/>
        </maps:projection>
    </maps:mapView>
    <maps:layers>
        <maps:image id="imageLayer">
            <maps:imageStaticSource projection="static-image"
                                    url="https://imgs.xkcd.com/comics/online_communities.png">
                <maps:projection code="static-image"
                                 units="PIXELS">
                    <maps:extent minX="0" minY="0" maxX="1024" maxY="968"/>
                </maps:projection>
                <maps:imageExtent minX="0" minY="0" maxX="1024" maxY="968"/>
            </maps:imageStaticSource>
        </maps:image>
    </maps:layers>
</maps:geoMap>

To show image from classpath define the same XML as in example above and change URL:

<maps:imageStaticSource projection="static-image"
                        url="icons/icon.png">

or in the controller add StreamResource:

@ViewComponent
protected GeoMap map;

@Subscribe
protected void onInit(final InitEvent event) {
    ImageLayer imageLayer = map.getLayer("imageLayer");
    ImageStaticSource staticSource = imageLayer.getSource();
    staticSource.setResource(new StreamResource("icon.png", () -> {
        try {
            return new ClassPathResource("META-INF/resources/icons/icon.png").getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }));
}

ImageWmsSource - to work with images from WMS. Example is take from: OpenLayers :: examples - Single Image WMS.

<maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:layers>
        <maps:tile>
            <maps:osmSource/>
        </maps:tile>
        <maps:image>
            <maps:imageWmsSource url="https://ahocevar.com/geoserver/wms"
                                 ratio="1"
                                 serverType="GEO_SERVER">
                <maps:parameters>
                    <maps:parameter name="LAYERS" value="topp:states"/>
                </maps:parameters>
            </maps:imageWmsSource>
            <maps:extent minX="-124.43" minY="24.57" maxX="-66.58" maxY="49.22"/>
        </maps:image>
    </maps:layers>
</maps:geoMap>

VectorLayer

Layer is to work with geometries.

VectorSource - to work with features (Polygon, LineString, Point).

XML

<maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:layers>
        <maps:tile>
            <maps:osmSource/>
        </maps:tile>
        <maps:vector id="vectorLayer">
            <maps:vectorSource/>
        </maps:vector>
    </maps:layers>
</maps:geoMap>

Java

@ViewComponent
private GeoMap map;
@Subscribe
protected void onInit(final InitEvent event) {
    VectorLayer vectorLayer = map.getLayer("vectorLayer");
    VectorSource vectorSource = vectorLayer.getSource();
    vectorSource.addFeature(new MarkerFeature(createPoint(0, 0)));
}

DataVectorSource - supports data binding with Jmix data containers. Note, entity must have only one property with Geo type (Point, LineString, Polygon) and @Geometry annotation.

<maps:geoMap id="map"
             width="100%"
             height="100%">
    <maps:layers>
        <maps:tile>
            <maps:osmSource/>
        </maps:tile>
        <maps:vector>
            <maps:dataVectorSource dataContainer="officesDc"/>
        </maps:vector>
    </maps:layers>
</maps:geoMap>

Features and Geometries

In GeoMap available the following features: 1) MarkerFeature - displayed as marker. marker30x39 Example:

 protected void addMarker(VectorSource source) {
    Point point = GeometryUtils.createPoint(-0.12081, 51.51592);
    source.addFeature(new MarkerFeature(point));
}

2) PointFeature - simple point in OpenLayers. Example:

protected void addPoint(VectorSource source) {
    Point point = GeometryUtils.createPoint(13.046446, 47.797916);
    source.addFeature(new PointFeature(point));
}

3) LineStringFeature - simple polyline in OpenLayers. Example

protected void addLineString(VectorSource source) {
    GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory();
    LineString lineString = geometryFactory.createLineString(new Coordinate[]{
            new Coordinate(11.013511, 50.978630),
            new Coordinate(2.392612, 48.782472),
            new Coordinate(-3.674846, 40.353581)});
    source.addFeature(new LineStringFeature(lineString));
}

4) PolygonFeature - simple polygon in OpenLayers. Example:

protected void addPolygons(VectorSource source) {
    GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory();
    LinearRing shell = geometryFactory.createLinearRing(new Coordinate[]{
            new Coordinate(9.844944, 44.011077),
            new Coordinate(12.286243, 44.525239),
            new Coordinate(18.389491, 40.011935),
            new Coordinate(15.732783, 38.003544),
            new Coordinate(9.844944, 44.011077),
    });
    Polygon polygon = geometryFactory.createPolygon(shell);
    source.addFeature(new PolygonFeature(polygon));
}

Style

VectorLayer and features supports styling. For instance: 1) PointFeature

new PointFeature(GeometryUtils.createPoint(0, 0))
                .addStyles(new Style()
                        .withImage(new CircleStyle()
                                .withRadius(7)
                                .withFill(new Fill("#E7003E"))
                                .withStroke(new Stroke()
                                        .withWidth(2.0)
                                        .withColor("#710067"))));

2) PolygonFeature

new PolygonFeature(geometries.createPolygon(shell))
        .addStyles(new Style()
                .withFill(new Fill("rgba(1, 147, 154, 0.2)"))
                .withStroke(new Stroke()
                        .withWidth(3.)
                        .withColor("#123EAB")));

3) LineStringFeature

new LineStringFeature(lineString)
        .addStyles(new Style()
                .withStroke(new Stroke()
                        .withWidth(3.0)
                        .withColor("#F60018")));

Events

Map and features has the following events: