<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Getting GoTo Interrupted when using zoomTo in ArcGIS JavaScript Maps SDK Questions</title>
    <link>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/getting-goto-interrupted-when-using-zoomto/m-p/1321681#M82070</link>
    <description>&lt;P&gt;I have not worked in Vue, so I am going to use React terms. Most likely your issue is caused by altering the state during the goTo animation causing the component to reload. Does that make sense in a Vue context?&lt;/P&gt;</description>
    <pubDate>Wed, 23 Aug 2023 15:24:30 GMT</pubDate>
    <dc:creator>JeffreyThompson2</dc:creator>
    <dc:date>2023-08-23T15:24:30Z</dc:date>
    <item>
      <title>Getting GoTo Interrupted when using zoomTo</title>
      <link>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/getting-goto-interrupted-when-using-zoomto/m-p/1321651#M82068</link>
      <description>&lt;P&gt;Hello all.&amp;nbsp; I have a Vue project in which we are plotting markers shaped as pins.&amp;nbsp; Part of the requirement is that the markers must point to the location rather than be centered on top of it.&amp;nbsp; So we're using an offset to reposition the markers and then to reposition the popup so it's on the top center of the marker.&amp;nbsp; On initial click of the marker, everything works fine, but when I try to zoom to the marker, the map zooms, but then gets the following error:&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;aA {name: 'view:goto-interrupted', details: undefined, message: 'Goto was interrupted'}
details: undefined
message: "Goto was interrupted"
name: "view:goto-interrupted"
[[Prototype]]: oA&lt;/LI-CODE&gt;&lt;P&gt;I have tried to solve it in a few different ways, but this is the current method.&amp;nbsp; Can anyone help me figure out what's going wrong?&amp;nbsp; (Or if there's a better way to achieve my objective as a whole...) Here's the code:&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;&amp;lt;!-- eslint-disable no-console --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div
        id="map"
        style="width: 100%;"
    /&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import Map from '@arcgis/core/Map';
import MapView from '@arcgis/core/views/MapView';
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer';
import CustomContent from '@arcgis/core/popup/content/CustomContent';
import * as reactiveUtils from '@arcgis/core/core/reactiveUtils';
import Graphic from '@arcgis/core/Graphic';
import Point from '@arcgis/core/geometry/Point';
import { createVNode, render } from 'vue';

import MarkerSVG from '../../assets/marker.svg?url';

import PopupTemplateHeader from './PopupTemplateHeader.vue';
import PopupTemplateContent from './PopupTemplateContent.vue';

export default {
    data() {
        return ({
            selectedMarkers: [],
            animationState: ''
        });
    },
    watch: {
        '$store.list.data.records': {
            handler() {
                this.$nextTick(this.plotRecords);
            },
            immediate: true
        }
    },
    created() {
        this.$mitt.on('open-popup', (id) =&amp;gt; {
            const graphic = this.layer.graphics.items.find((i) =&amp;gt; i.attributes.record.id === id);
            this.openPopup([graphic]);
        });
        this.$mitt.on('close-popup', this.clearPopup);
    },
    mounted() {
        window.MapComponent = this;

        this.map = new Map({
            basemap: 'streets-navigation-vector',
            customParameters: { type: 'map' }
        });

        this.view = new MapView({
            map: this.map,
            popup: {
                collapseEnabled: false,
                dockOptions: {
                    buttonEnabled: false
                },
                highlightEnabled: false,
                alignment: 'top-center',
                viewModel: {
                    autoCloseEnabled: false,
                    includeDefaultActions: true
                }
            },
            center: [-98.805, 38.027], // lng, lat
            zoom: 4,
            container: 'map',
            constraints: {
                minZoom: 2,
                maxZoom: 15,
                rotationEnabled: false
            }
        });

        // Move zoom toggles to bottom right
        this.view.ui.move(['zoom'], 'bottom-right');

        this.view.on('click', (event) =&amp;gt; {
            // do not let Esri handle the click event
            event.stopPropagation();

            this.view.hitTest(event).then(({ results }) =&amp;gt; {
                const markers = results.filter((r) =&amp;gt; r.graphic.symbol?.type === 'picture-marker').map((f) =&amp;gt; f.graphic);
                if (markers.length) {
                    this.openPopup(markers);
                } else {
                    this.clearPopup();
                }
            });
        });

        reactiveUtils.on(
            () =&amp;gt; this.view.popup,
            "trigger-action",
            (event) =&amp;gt; {
                if (event.action.id === 'zoom-to-feature') {
                    this.openPopup([this.view.popup.selectedFeature], true);
                }
                else {
                    console.log('EVENT ID: ', event.action.id);
                    console.log('EVENT: ', event);
                    console.log('GEOMETRY: ', this.view.popup.selectedFeature.geometry);
                }
            });

        // whenever the popup title changes, render the custom header content and inject it
        reactiveUtils.when(() =&amp;gt; this.view.popup?.title, () =&amp;gt; {
            const interval = setInterval(() =&amp;gt; {
                const container = this.$el.querySelector(`div[id="${this.view.popup.titleId}"] .maps-popup-header`);

                if (container) {
                    const recordId = container.classList[1];
                    const record = this.$store.list.data.records.find((r) =&amp;gt; r.id === recordId);

                    if (record) {
                        const header = createVNode(PopupTemplateHeader, { columns: this.$store.list.info.displayColumns, record, addressFieldsArray: this.$store.addressFieldsArray });
                        render(header, document.createElement('div'));
                        container.innerHTML = header.el.innerHTML;
                    }

                    clearInterval(interval);
                }
            }, 10);
        });

        reactiveUtils.when(() =&amp;gt; this.view.animation, (animation) =&amp;gt; {
                this.animationState = animation.state; // Should be 'running'
                animation.when((animation) =&amp;gt; {
                    this.animationState = animation.state; // Should be 'finished'
                })
                .catch((animation) =&amp;gt; {
                    this.animationState = animation.state; // should be 'stopped'
                });
        });
    },
    methods: {
        async openPopup(markers, zoomIn = false) {
            // clear any existing popup
            if (this.view.popup.visible) {
                this.clearPopup();
            }
            
            // pan the map center to the first marker
            this.panTo(markers[0].geometry, zoomIn);

            markers.forEach((marker) =&amp;gt; {
                const { record } = marker.attributes;
                const recordTitle = record.fields?.Name?.displayValue ?? record.fields?.Name?.value ?? '';
                marker.popupTemplate = {
                    title: `&amp;lt;div class="maps-popup-header ${record.id}"&amp;gt;${recordTitle}&amp;lt;/div&amp;gt;`,
                    content: [new CustomContent({
                        creator: () =&amp;gt; {
                            // build content
                            const content = createVNode(PopupTemplateContent, { columns: this.$store.list.info.displayColumns, record });
                            render(content, document.createElement('div'));
                            return content.el;
                        }
                    })],
                    overwriteActions: true,
                    actions: [
                        {
                            id: 'zoom-to-feature',
                            className: 'esri-icon-zoom-in-magnifying-glass',
                            icon: 'magnifying-glass-plus',
                            type: 'button',
                            visible: true,
                            title: "{messages.zoom}"                   
                        }
                    ]
                };
            });
            this.selectedMarkers = [ ...markers ];
            const location = this.createOffsetPoint(markers[0].geometry);
            if (this.animationState === 'finished') {
                this.view.openPopup({
                    features: markers,
                    location
                });
            }
            
        },
        clearPopup() {
            this.view?.closePopup();

            if (this.view.popup.clear) {
                this.view.popup.features.forEach((feature) =&amp;gt; {
                    delete feature.popupTemplate;
                });

                this.view.popup.clear();
            }
        },
        async panTo(target, zoomIn) {
            const offset = this.createOffsetPoint(target, 'zoom');
            const zoom = zoomIn ? this.view.zoom + 4 : this.view.zoom;

            // use modified extent center as target
            return await this.view.goTo(
                { geometry: offset, zoom },
                { duration: 750 }
            )
        },
        plotRecords() {
            // clear any existing popups before plotting
            this.clearPopup();

            if (this.layer) {
                this.map.layers.remove(this.layer);
            }
            const latField = this.$store.latLongFields.lat;
            const longField = this.$store.latLongFields.long;
            const graphics = this.$store.list.data.records?.reduce((arr, record) =&amp;gt; {
                if (this.$store.hasGeo(record)) {
                    arr.push(
                        new Graphic({
                            attributes: { record },
                            geometry: {
                                type: 'point', // autocasts as new Point()
                                longitude: record.fields[longField].value,
                                latitude: record.fields[latField].value
                            },
                            symbol: {
                                type: 'picture-marker', // autocasts as new SimpleMarkerSymbol()
                                url: import.meta.env.MODE === 'development' ? `https://localhost:5173${MarkerSVG}` : MarkerSVG,
                                height: 26,
                                width: 20,
                                yoffset: 13
                            }
                        })
                    );
                }

                return arr;
            }, []);

            if (graphics?.length) {
                this.layer = new GraphicsLayer({ graphics });
                this.map.layers.add(this.layer);
                this.view.goTo(graphics);
            }
        },
        createOffsetPoint(recordPoint, type = 'popup') {
            // Convert to screen point to get location of x and y in pixels
            const screenPoint = this.view.toScreen(recordPoint);
            // Subtract 26 to offset the marker and its offset
            screenPoint.y =  type === 'popup' ? screenPoint.y - 26 : screenPoint.y - 100;
            // Convert offset screenpoint to regular point to use in Graphic.
            return this.view.toMap({ ...screenPoint });
        }
    }
};
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
    .esri-popup__main-container {
        border-radius: 5px;
    }

    .esri-popup__header {
        border-bottom: 1px solid #dddd;
        margin-bottom: 10px;
        padding-top: 3px;
    }

    .esri-popup__button:hover {
        background-color: unset;
    }

    .esri-popup__content {
        margin-bottom: 0;
    }

    .esri-feature__content-element {
        margin-bottom: 0 !important;
    }

    .esri-popup--aligned-top-center .esri-popup__pointer-direction, .esri-popup--aligned-bottom-center .esri-popup__pointer-direction {
        transform: scale(1, 1.1) rotate(45deg) !important;
    }
&amp;lt;/style&amp;gt;&lt;/LI-CODE&gt;</description>
      <pubDate>Wed, 23 Aug 2023 14:55:06 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/getting-goto-interrupted-when-using-zoomto/m-p/1321651#M82068</guid>
      <dc:creator>kprenesti</dc:creator>
      <dc:date>2023-08-23T14:55:06Z</dc:date>
    </item>
    <item>
      <title>Re: Getting GoTo Interrupted when using zoomTo</title>
      <link>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/getting-goto-interrupted-when-using-zoomto/m-p/1321681#M82070</link>
      <description>&lt;P&gt;I have not worked in Vue, so I am going to use React terms. Most likely your issue is caused by altering the state during the goTo animation causing the component to reload. Does that make sense in a Vue context?&lt;/P&gt;</description>
      <pubDate>Wed, 23 Aug 2023 15:24:30 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/getting-goto-interrupted-when-using-zoomto/m-p/1321681#M82070</guid>
      <dc:creator>JeffreyThompson2</dc:creator>
      <dc:date>2023-08-23T15:24:30Z</dc:date>
    </item>
  </channel>
</rss>

