Select to view content in your preferred language

Edit Box Symbology doesn't move with graphic when updating with sketchViewModel

162
2
a month ago
RileyLum2
New Contributor

Hi All,

I've created a sketchViewModel to create and edit graphics in a graphics layer following this sample: SketchViewModel Styler | Sample Code | ArcGIS Maps SDK for JavaScript 4.30 | Esri Developer

Though I am experiencing some odd behaviour where the orange 'edit' box stays behind as I drag the graphics around, see the below screenshot.

RileyLum2_1-1721008290528.png

Does anyone know what the issue is or has any tips for debugging?

Here is a code pen of the relevant code.

 

HTML:

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.25/esri/themes/light/main.css">
    <link rel="stylesheet" href="./index.css">
    <script src="https://js.arcgis.com/4.25/"></script>
</head>
<body>
    <div class="grid-container">
        <div class="grid-item header"></div>
        <div class="grid-item left-panel"></div>
        <div class="grid-item map-panel">
            <div id="viewDiv"></div>
            <div id="sketchDiv" class="esri-widget">
                <img src="./icons/select.svg" id="select-btn">
                <img src="./icons/pin.svg" id="pin-btn">
                <img src="./icons/line.svg" id="line-btn">
                <img src="./icons/polygon.svg" id="polygon-btn">
                <img src="./icons/rectangle.svg" id="rectangle-btn">
                <img src="./icons/circle.svg" id="circle-btn">
                <img src="./icons/trash.svg" id="trash-btn">
            </div>
        </div>
        <div class="grid-item right-panel"></div>
        <div class="grid-item footer">
            <div class="symbol-list">
                <div class="friendly"><img data-src="./milsym/friendly_50.svg" data-height="34px" data-width="50px" src="./milsym/friendly_50.svg"></div>
                <div class="hostile"><img data-src="./milsym/hostile_50.svg" data-height="50px" data-width="50px" src="./milsym/hostile_50.svg"></div>
                <div class="neutral"><img data-src="./milsym/neutral_50.svg" data-height="50px" data-width="50px" src="./milsym/neutral_50.svg"></div>
                <div class="unknown"><img data-src="./milsym/unknown_50.svg" data-height="50px" data-width="50px" src="./milsym/unknown_50.svg"></div>
            </div>
        </div>
    </div>

</body>
    <script type="module" src="./index.js"></script>
</html>

 

CSS:

 

html,
body,
.grid-container,
#viewDiv {
    padding:0;
    margin:0;
    height:100%;
    width:100%;
    background-color: darkslategray;
}

#sketchDiv {
    width: auto;
    height: 50px;
    display: flex;
    align-items: center;
}

#sketchDiv img {
    padding: 10px;
    max-height: 36px;
    max-width: 36px;
    width: auto;
    height: auto;
}

.grid-container {
    display: grid;
    grid-template-columns: 10% auto 10%;
    grid-template-rows: 10% auto 10%;
}

.grid-item {
    border: black 1px solid;
}

.grid-item.header,
.grid-item.footer {
    grid-column: 1/4;
}

.grid-item.header {
    grid-row: 1;
}

.grid-item.footer {
    grid-row: 3;
}

.symbol-list {
    height:100%;
    width:100%;
    display: flex;
    align-items: center;
}

.symbol-list div{
    padding:15px;
}

 

JS:

 

// const { LatLngToMGRS } = require('./helpers/coordinate_conv.js')
import { LatLngToMGRS } from "./helpers/coordinate_conv.js";

// https://github.com/spatialillusions/milsymbol could add this for milsymbology
// examples hosted in esri https://storymaps.arcgis.com/collections/10b51783610a4df9b9a768bcde25ae0b

console.log(LatLngToMGRS(-34.847,138.505))


require(["esri/Map",
    "esri/views/MapView",
    "esri/Graphic",
    "esri/layers/GraphicsLayer",
    "esri/symbols/CIMSymbol",
    "esri/widgets/Sketch",
    "esri/widgets/Sketch/SketchViewModel",
    "esri/widgets/Compass",
    "esri/widgets/ScaleBar"], 
    (Map, MapView, Graphic, GraphicsLayer, CIMSymbol, Sketch, SketchViewModel, Compass, ScaleBar) => {
    
    // CREATING MAP
    const graphicsLayer = new GraphicsLayer({title: "graphicsLayer"});

    const map = new Map({
        basemap: "gray-vector",
        layers: [graphicsLayer]
    });

    const view = new MapView({
        container: "viewDiv",
        map: map,
        zoom: 15,
        center: [138.505,-34.847],
        // highlightOptions: {
        //     color: [255, 255, 0, 1],
        //     haloOpacity: 0.9,
        //     fillOpacity: 0.2
        //   }
    });

    // ADDING MAP WIDGETS

    view.ui.add("sketchDiv","top-right")

    const compass = new Compass({
        view:view
    });
    view.ui.add(compass,"top-left");

    const scaleBar = new ScaleBar({
        view: view,
        unit:"metric",
        style:"line"
    });
    view.ui.add(scaleBar, "bottom-left");

    // view.rotation = 90;

    // USING CIM SYMBOL TO DRAW OFFSET LINES
    const lineSymbol = new CIMSymbol({
        data: {
          type: "CIMSymbolReference",
          symbol: {
            type: "CIMLineSymbol",
            symbolLayers: [
                {
                    type: "CIMSolidStroke",
                    effects:[
                        {
                            type: "CIMGeometricEffectOffset",
                            offset: 3.0,
                            method: "Rounded",
                            option: "Fast"
                        }
                    ],
                    enable: true,
                    capStyle: "Butt",
                    joinStyle: "Round",
                    width: 1,
                    color: [0,0,0,255]
                },
                {
                    type: "CIMSolidStroke",
                    effects:[
                        {
                            type: "CIMGeometricEffectOffset",
                            offset: -3.0,
                            method: "Rounded",
                            option: "Fast"
                        }
                    ],
                    enable: true,
                    capStyle: "Butt",
                    joinStyle: "Round",
                    width: 1,
                    color: [0,0,0,255]
                }
            ]
        }
        }
      });

    const sketch = new Sketch({
        view: view,
        layer: graphicsLayer,
        creationMode: "update",
        layout:"vertical",
        viewModel: new SketchViewModel({
            view:view,
            layer: graphicsLayer,
            polygonSymbol: {
                type:"simple-fill",
                color: [227,139,79,0.8],
                outline: {
                    color: [255,255,255],
                    width: 1
                }
            },
            // polylineSymbol: {
            //     type: "simple-line",
            //     color: [226,119,40],
            //     width: 2
            // },
            polylineSymbol: lineSymbol,
            pointSymbol: {
                type: "simple-marker",
                color: [226,119,40],
                outline: {
                    color: [255,255,255],
                    width: 1
                }
            }
        }),
        visibleElements: {
            createTools: {
            },
            selectionTools: {
                "lasso-selection": false,
                "rectangle-selection": false
            },
            settingsMenu:false
        }
    });
    // view.ui.add(sketch,'top-right');

    // https://developers.arcgis.com/javascript/latest/sample-code/sandbox/?sample=sketch-viewmodel-styler
    const sketchVM = new SketchViewModel({
        view: view,
        layer: graphicsLayer,
        defaultCreateOptions: {
            hasZ: true,
            mode: "click",
            preserveAspectRatio: false
        }
    })

    // view.when(() => {
    //     sketchVM.defaultUpdateOptions.highlightOptions = {enabled: true};
    //     // sketchVM.
    //     console.log(sketchVM.defaultCreateOptions)
    //     // setDefaultPointSymbol();
    //     // setDefaultPolylineSymbol();
    //     // setDefaultPolygonSymbol();
    // })

    const selectBtn = document.getElementById('select-btn');
    const pinBtn = document.getElementById('pin-btn');
    const lineBtn = document.getElementById('line-btn');
    const polygonBtn = document.getElementById('polygon-btn');
    const rectangleBtn = document.getElementById('rectangle-btn');
    const circleBtn = document.getElementById('circle-btn');
    const trashBtn = document.getElementById('trash-btn');

    selectBtn.addEventListener('click',() => {sketchVM.cancel();});
    pinBtn.addEventListener('click',() => {sketchVM.create("point")});
    lineBtn.addEventListener('click',() => {sketchVM.create("polyline")});
    polygonBtn.addEventListener('click',() => {sketchVM.create("polygon")});
    rectangleBtn.addEventListener('click',() => {sketchVM.create("rectangle")});
    circleBtn.addEventListener('click',() => {sketchVM.create("circle")});
    trashBtn.addEventListener('click',() => {sketchVM.layer.removeAll();});


    sketchVM.on("update", (evt) => {console.log(evt)})

    // DRAG AND DROP FUNCTIONALITY

    function allowDrop(evt) {
        evt.preventDefault();
    }

    function dropPoint(evt) {
        const markerURL = evt.srcElement.dataset.src;
        const markerWidth = evt.srcElement.dataset.width;
        const markerHeight = evt.srcElement.dataset.height;
        const rect = document.getElementById('viewDiv').getBoundingClientRect();
        const mapPoint = view.toMap({x:evt.clientX-rect.left,y:evt.clientY-rect.top});
        const point = {
            type: "point",
            longitude: mapPoint.longitude,
            latitude: mapPoint.latitude
        };
        const pntSymbol = {
            type: "picture-marker",
            url: markerURL,
            width: markerWidth,
            height: markerHeight
        };
        const pointGraphic = new Graphic({
            geometry:point,
            symbol:pntSymbol
        });
        graphicsLayer.add(pointGraphic)
    };

    const mapdiv = document.getElementsByClassName('map-panel')[0]
    mapdiv.ondragover = allowDrop

    const markers = document.querySelectorAll('.symbol-list div img')
    for (let marker of markers) {
        marker.addEventListener('dragend', dropPoint)
    }

    // view.on("pointer-move", (event) => {
    //     var position = view.toMap(event)
    //     console.log(position.latitude, position.longitude)
    // })
});

 

2 Replies
JoelBennett
MVP Regular Contributor

I haven't tested this, but it seems likely to me that the problem you're experiencing is related to having two SketchViewModels in play at the same time.  In the JS code, one is found on line 108, and the other on line 147.  Since it doesn't appear that you're actually using the Sketch widget instantiated on line 103, you might try removing it altogether.

0 Kudos
JamesIng
Occasional Contributor

@RileyLum2  - Have just tested it and @JoelBennett  is correct if you remove the sketch widget instantiated on line 103, it'll fix the double box editor issue.

James from www.landkind.com