perpetuallyconfused
Posts: 8
Joined: Fri Nov 03, 2023 12:42 am

Dragging annotations not in new position on export

I am using highcharts maps to place points on the map using long and lat coordinates and adding annotations to them with the text as svg tags.
I am also adding a legend using annotations that is not associated to any point. All annotations are using the setting draggable: 'xy'.

Everything looks and works perfectly in the UI. But I am trying to do a export of the map via chart.getSVG(). All the annotations are in their proper spots. However, whenever I drag any annotation and export, the exported image shows the map point annotations in their original positions.
For my legend, I used shapes to create boxes around the text and it shows the shapes moved, but the text inside remains in the initial position. What is the proper way to export the map with the annotations in their newly placed positions?

Here is the code I use to add the legend at the least:

Code: Select all

function generateLegend(region) {
    window[`${region}Map`].addAnnotation({
        id: `${region}legend`,
        draggable: 'xy',
        labelOptions: {
            allowOverlap: true,
            backgroundColor: null,
            borderWidth: 0,
            padding: 10,
        },
        labels: [
            {
                point: {
                    x: window.regionValStore[region]['legendParams']['x'],
                    y: window.regionValStore[region]['legendParams']['y'],
                },
                text: `
                    <svg width="300" height="200">
                        <text x="8%" y="30" fill="black" style="text-align:center; text-decoration:underline;">
                            Legend
                        </text>
                        <text x="10%" y="40" fill="black" text-anchor="middle">
                            <tspan x="10%" dy="1.5em" style="font-weight:bold; margin:2px;">
                                TOTAL COUNT
                            </tspan>
                            <tspan x="10%" dy="1.5em" style="font-weight:bold; margin:2px;">
                                ITEM CODE
                            </tspan>
                            <tspan x="10%" dy="1.5em" style="font-weight:bold; margin:2px;">
                                ITEM UNIT
                            </tspan>
                        </text>
                        <text x="10" y="100" fill="black" style="border:solid black 1px; background-color:#8895bd;">
                            <tspan x="10" dy="1.5em" style="font-weight:bold; color:#ce0000; margin:2px;">
                                Red font = changes
                            </tspan>
                            <tspan x="10" dy="1.5em" style="font-weight:bold; color:#ce0000; margin:2px;">
                                previous year
                            </tspan>
                        </text>
                        <text x="10" y="140" fill="black" style="border:solid black 1px; background-color:#8895bd;">
                            <tspan x="10" dy="1.5em" style="font-weight:bold; background-color:yellow; margin:2px;">
                                Yellow Highlight = Pre-decisional
                            </tspan>
                            <tspan x="10" dy="1.5em" style="font-weight:bold; background-color:yellow; margin:2px;">
                                Inventory Changes
                            </tspan>
                        </text>
                    </svg>
                `,
                style: {
                    color: '#000000',
                    fontSize: '12px',
                },
            },
        ],
        shapes: [
            {
                type: 'rect',
                points: [{
                    x: window.regionValStore[region]['legendParams']['x'] - 102,
                    y: window.regionValStore[region]['legendParams']['y'] - 155,
                }],
                stroke: 'black',
                strokeWidth: 1,
                fill: 'none',
                width: 200,
                height: 60,
            }, {
                type: 'rect',
                points: [{
                    x: window.regionValStore[region]['legendParams']['x'] - 102,
                    y: window.regionValStore[region]['legendParams']['y'] - 95,
                }],
                stroke: 'black',
                strokeWidth: 1,
                fill: 'none',
                width: 200,
                height: 43,
            }, {
                type: 'rect',
                points: [{
                    x: window.regionValStore[region]['legendParams']['x'] - 102,
                    y: window.regionValStore[region]['legendParams']['y'] - 52,
                }],
                stroke: 'black',
                strokeWidth: 1,
                fill: 'yellow',
                width: 200,
                height: 45,
            },
        ],
        events: {
            drag: function(event) {
                console.log('dragged');
                annotation.update({
                    x: event.chartX,
                    y: event.chartY
                });
            }
        }
    });
}
andrzej.b
Site Moderator
Posts: 538
Joined: Mon Jul 15, 2024 12:34 pm

Re: Dragging annotations not in new position on export

Hi,

Thanks for reaching out with your question.

It sounds like you're encountering an issue where the annotations don't maintain their new positions after being dragged when exporting the map. The key here is to ensure that the annotations' positions are updated in the chart's configuration before you call the getSVG() method. Here's a potential solution:
1. ​Update Annotation Positions on Drag​: Ensure that the new positions of the annotations are stored in a way that they can be accessed when exporting. You can do this by updating the window.regionValStore[region]['legendParams'] with the new coordinates after dragging.
2. ​Export with Updated Positions​: When you call getSVG(), make sure that the chart configuration reflects the latest positions of the annotations.
Here's a modified version of your drag event handler that updates the stored positions:

Code: Select all

events: {
    drag: function(event) {
        const annotation = this;
        const newX = event.chartX;
        const newY = event.chartY;

        // Update the annotation's position in the store
        window.regionValStore[region]['legendParams']['x'] = newX;
        window.regionValStore[region]['legendParams']['y'] = newY;

        // Update the annotation position
        annotation.update({
            labels: [{
                point: {
                    x: newX,
                    y: newY
                }
            }],
            shapes: annotation.options.shapes.map(shape => ({
                ...shape,
                points: shape.points.map(point => ({
                    x: point.x + (newX - annotation.options.labels[0].point.x),
                    y: point.y + (newY - annotation.options.labels[0].point.y)
                }))
            }))
        });
    }
}
When you call getSVG(), it will now use the updated positions from window.regionValStore[region]['legendParams'].
This approach ensures that whenever you drag an annotation, its new position is saved and reflected in the exported SVG.

Let me know if this resolves the issue!
Andrzej
Highcharts Developer
perpetuallyconfused
Posts: 8
Joined: Fri Nov 03, 2023 12:42 am

Re: Dragging annotations not in new position on export

Hi Andrzej!

Thank you so much for your response! I tried out your suggested code and it mostly worked, but running the update on the annotation while dragging was overloading / breaking the drag functionality. But it was a great starting point and I've made some changes. This is what I have that works perfectly.

Code: Select all

events: {
            drag: function(event) {
                const annotation = this;
                const newX = event.clientX;
                const newY = event.clientY;
        
                window.regionValStore[region]['legendParams']['x'] = newX;
                window.regionValStore[region]['legendParams']['y'] = newY;
                
                const annotationContainer = annotation.chart.container;
                annotationContainer.addEventListener('mouseup', dragLegend);
                annotationContainer.removeEventListener('mouseup', dragLegend);
        }
    }
    
With legend being the code to update the legend annotation.

Thanks again!
perpetuallyconfused
Posts: 8
Joined: Fri Nov 03, 2023 12:42 am

Re: Dragging annotations not in new position on export

Just as an FYI, I have a function that will remove the legend annotation and re-generate it when the mouse is released. I'm still working on trying the update method to do the same, but it is not quite working as expected.
perpetuallyconfused
Posts: 8
Joined: Fri Nov 03, 2023 12:42 am

Re: Dragging annotations not in new position on export

Hi Andrzej,

I do have another problem now though. Here is my code for my annotations that are tied to points placed on the map via lat/long coordinates.

Code: Select all

events: {
                    drag: function(event) {
                        const annotation = this;
                        const newX = event.clientX;
                        const newY = event.clientY;
                        
                        const annotationContainer = annotation.chart.container;
                        
                        const handleAnnotationMouseUp = function() {
                            annotation.update({
                                labels: [{
                                    point: {
                                        x: newX,
                                        y: newY,
                                    },
                                }],
                            });
                            
                            annotationContainer.removeEventListener('mouseup', handleAnnotationMouseUp);
                        };
                        
                        annotationContainer.addEventListener('mouseup', handleAnnotationMouseUp);
                    }
                }
This will allow the annotations to persist on exporting after moving. However, it seems to dissociate from the plotted points that it was originally associated with. It also leaves a duplicate annotation at the initial position instead of treating it as a moved object. Any suggestions on this?
Thanks again for your help!
perpetuallyconfused
Posts: 8
Joined: Fri Nov 03, 2023 12:42 am

Re: Dragging annotations not in new position on export

Actually, I figured out my issue. I had added some redundant code that was causing a redraw and thus causing a bunch of issues. Thanks for the help Andrzej!
andrzej.b
Site Moderator
Posts: 538
Joined: Mon Jul 15, 2024 12:34 pm

Re: Dragging annotations not in new position on export

Hi,

So glad to have been able to help – if you have any follow up questions, please let us know.

Kind regards,
Andrzej
Highcharts Developer

Return to “Highcharts Maps”