(Well, the guidelines asked if the title of my post was interesting, so…)
I am creating an animation that takes in some ‘path’ data and simulates people (red circles) walking on a path (gray line). Like this:
One feature is that the red lines projecting from the circles should point to their next destination on the path. The gray paths are visible for diagnostic purposes.
This, as you can see in the above image, does not happen.
While I expect something like this (although it’s also not perfect):
I get this:
This is strange behavior because the red circles (while moving) and the red lines (for pointing) use the same data. While the red lines stay on the gray path correctly, the red lines do not align with the gray path.
The problematic code is:
...
moveAgents = {
replay;
d3.selectAll('.agent')
.remove()
drawAgents()
const agents = d3.selectAll('.agent')
const timeStep = 1000
_.zip( agents.nodes(), Object.entries(paths) ).forEach( ([agentNode, pathObject]) => { // converstion to nodes is necessary for zip to work. (D3 selections are not iterable directly).
const agent = d3.select(agentNode)
const directionIndicator = agent.select('.agent-direction-indicator')
const path = pathObject[1] // pathObject[0] is a key, which is 1, 2, 3, etc...
let currentStep = -1
path.forEach( (position , i) => {
const currentX = agent.select('circle').attr('cx')
const currentY = agent.select('circle').attr('cy')
const destinationX = x(position.x)
const destinationY = y(position.y)
const differenceX = destinationX - currentX
const differenceY = destinationY - currentY
const timeToInitializeMovement = position.time
// Move agents along the path
agent
.transition()
.duration( timeStep )
.ease( d3.easeLinear )
.delay( timeToInitializeMovement )
.attr( 'transform', `translate(${differenceX}, ${differenceY})`)
// Point the direction indicator towards the next destination on the path
directionIndicator
.transition()
.duration( 0 )
.ease( d3.easeLinear )
.delay( timeToInitializeMovement )
.attr('x2', destinationX )
.attr('y2', destinationY )
} ) // forEach
}) // zip-forEach
return agents
}```
It is probably much easier to see it working in context, so I made a notebook here. More details are in it.
Anyone can perhaps recognize this issue and point me in the right direction?
This has been quite a pain, and I would greatly appreciate any help you might be able to offer.
Many thanks in advance!