Synchronizing 2 position inputs with draggable circle

I’m trying to make an example of a a draggable circle with D3 where users can directly drag on the svg circle, or they can use 2 Input sliders to set the x and y position of the circle.

Example code here:

I’m having trouble synchronizing the sliders values with the directly dragged position.
In the version published at the link above dragging the circle directly does update the sliders, but the values of viewof centX.value and centX don’t match the sliders even after manually refreshing them. It is easy to get ‘viewof centX.value’ and centX to produce different results after multiple drags.

Commenting in the Input Dispatches makes it so the y position of hte circle jumps when the drag is started.

Adding these two cells to monitor the values shows that when dragging the centX centY are not changing. So when you then go to drag a slide, the one not dragged uses it’s value before the drag.

{now; return [centX, viewof centX.value] }
{now; return [centY, viewof centY.value] }

Not sure how to fix that though.

Hi Maneesh! Here’s a suggestion:

https://observablehq.com/compare/a86a42c157f797fa...62fc53b2498f3deb

In summary: if you want two-way synchronization, it’s best to “opt-out” of Observable’s reactivity by using event listeners. In this case it means that your SVG cell can’t reference centX, centY, or rad, and should instead only reference viewof centX, viewof centY, and viewof rad. Then, you use an input event listener to update the SVG in response to those inputs’ values changing. You can also use the invalidation promise to remove those event listeners when the SVG cell is invalidated.

Hope this helps!

2 Likes