Drag + drop questions

I’m trying to get the hang of dynamic objects in a graph. Here’s an example I put together with circles that can be dragged only horizontally, not vertically:

  • I want to have a hollow circle (fill="none") that I can drag around, but that seems to mean that I can only drag it if I click right on the circle outline. Is there a way to still use fill="none" but be able to drag the circle by clicking in the interior?
  • I want to have other views of the state variables in handles2. I tried a markdown cell right below the graph, but it doesn’t update. I must be missing something important… what?

The answer to your first point is pointer-events="all".

1 Like

For the second point, I would read these two tutorials representing the two main approaches (views and mutables):

Thanks! What’s the recommended way of putting short css snippets into a notebook?

(the equivalent of <style type='text/css'> ... rules go here ... </style>)

It looks like mutable is the way to go in my case, since the handles are just one aspect of my graph, not the primary output of it.

Does it work with properties?

e.g.

// in one cell
mutable x = {a: 0, b:1}

// in another cell
mutable x.a = 3;

Hmm. It looks like the mutable name has to be a global variable, you can’t do something like this?

something.on('click', function(d) { mutable ++d.count; })

Try

mutable a = ({foo: 42})

(The need for parens is explained in the Introduction to Code notebook.)

You can modify a property of a mutable value, but it won’t trigger reactive evaluation until you reassign to the mutable itself. So you might see code like this:

{
  ++mutable a.foo;
  mutable a = mutable a;
}
1 Like
html`<style>…</style>`
1 Like

oh, I see, yeah, that makes sense.

I’m still stymied by the need for mutable to act on a name rather than a value (I think).

I plan on having the same drag handler operating on several different data fields, so something like

// allow changing x only
  function dragged(d) {
    d.x = x.invert(d3.event.x);  
    // now we want this value `d.x` to propagate to cause other notebook values 
    // to change. But we don't want to go through global variables.
    d3.select(this).attr("cx", d3.event.x)
                   .attr("cy", y(d.y))
  }

If you don’t mind triggering re-evaluation for all the handles simultaneously, you can have a mutable handles which is an array, and reassign to that whenever you move any handle:

If you want to keep your mutables separate, it’s a bit trickier because there’s currently no way to write code that sets the value of a generic mutable (a reference to a mutable) and triggers re-evaluation. You have to write separate get & set functions for each mutable, as here:

You can, however, treat views generically:

(Related issue.)