bijection/g9

Is it possible to check for which point is being dragged?

JobLeonard opened this issue · 4 comments

I'll take the example code from "using Max and Min to limit a point's range of motion" as a starting point:

 var initial = {
    x1: -100,
    x2: 0,
    x3: 100,
}

function render(data, ctx){
    var m = Math.max(Math.min(data.x2, data.x3 - 20), data.x1 + 20)
    ctx.point(m,0, {affects: ['x2']})
    ctx.point(data.x2,20, {affects: ['x2']})
    ctx.point(data.x1,0, {fill: 'red'})
    ctx.point(data.x3,0, {fill: 'red'})
}

When I drag point x1 or x3, there's nothing stopping me from dragging one point beyond the other.

That can be fixed by repeating the trick used for x2:

    var mMin = Math.min(data.x1, data.x3 - 40)
    var mMax = Math.max(data.x1 + 40, data.x3)
    var m = Math.max(Math.min(data.x2, mMax - 20), mMin + 20)
    ctx.point(m,0, {affects: ['x2']})
    ctx.point(data.x2,20, {affects: ['x2']})
    ctx.point(mMin,0, { affects: ['x1'], fill: 'red'})
    ctx.point(mMax,0, { affects: ['x3'], fill: 'red'})

Now x1 and x3 can't get closer than 40 pixels and stop when dragged into each other. Great! But then I thought: well, what would be really cool is if x1 and x3 would push each other when dragged into each other. Is there a way to do this?

The problem, as I see it, is that in order for this to work, the values of x1 and x3 would have to be mutually dependent on each other: if I drag x1 into x3, then the value x3 should depend on x1, but if I drag x3 into x1, the value of x1 should depend on x3. And for that to work I need to know which of the points is being dragged, but I don't see a way to check for that in the documentation. But maybe there's another trick and I just don't properly think in terms of constraint based programming yet?

Although there isn't a way to check which point is being dragged (at least for now), you can get the red points to push each other by giving them both the affects list ['x1', 'x3']:

function render(data, ctx){
    var mMin = Math.min(data.x1, data.x3 - 40)
    var mMax = Math.max(data.x1 + 40, data.x3)
    var m = Math.max(Math.min(data.x2, mMax - 20), mMin + 20)
    ctx.point(m,0, {affects: ['x2']})
    ctx.point(data.x2,20, {affects: ['x2']})
    ctx.point(mMin,0, { affects: ['x1', 'x3'], fill: 'red'})
    ctx.point(mMax,0, { affects: ['x1', 'x3'], fill: 'red'})
}

Does that work for you?

Oh, I didn't realize affects works that way! The docs don't really explain that either.

But yes, that is the intended effect :)

Awesome!

I've added a more prominent note in the readme.