There are several ways you might accomplish this. Here's one that I like to use, if the cylinders are to retract at the same time:
For my example, I'll only use 2 cylinder movement bones. You should have no trouble adding a third.
Create your deformation armature of 3 bones, assigning one bone to each cylinder:
Make sure that each bone is parented to the bone below it, but is disconnected from the bone.
Add your controller bone adjacent to the top bone. Parent it to the bottom bone but keep it disconnected. Set it to not be a deforming bone.
- Make sure its bone roll is zero, because we're going to move it on the Z axis.
- Enter Pose mode.
- hover over the Z location value of the controller bone, right click and select Copy as new driver.
- hover over the Y location value of the top bone, right click and select Paste driver.
- edit the driver and change the type to Scripted Expression
- hover over the Y location value of the middle bone, right click and select Paste driver.
- edit the driver and change the type to Scripted Expression
- Lock everything but the Z location of the controller bone
- Lock everything but the Y location of the top and middle bone
You can add constraints to the Y locations of the top and middle bone and the Z location of the controller bone, or leave it to the animator to not overdo it.
Why it works
The controller bone is oriented so that it's Z axis is aligned along the axis of the cylinders. By locking it so it only moves along the Z axis, we limit its motion along that line.
The loose bones, on the other hand have their Y axis aligned along the cylinders, so we want the Z axis position of the controller to drive the Y axis position of the other bones.
The driver will cause this to happen in local space, so that the two cylinders will collapse at equal rates. Here's what the driver looks like in the driver editor:
Variations
You can adjust the scripted expressions to handle variations. For example, if the cylinders aren't the same length, you'll have to multiply the Z location by a value to compensate.
Another adjustment might be to change the way the cylinders collapse. Perhaps you want the lower cylinder to close first and then the upper, or the other way around. You do this by modifying the scripted expression, or, if you want more complex motion, by editing the driver curve.
EDIT: It is very straightforward (if you're comfortable with drivers) to modify the drivers so that the controller will collapse the cylinders from either end.
- Add a root bone.
- Unparent all of the other bones and parent them to the root.
- Add a driver to the bottom bone in the same way as the top, middle, and bottom bones were given drivers above.
- Each driver should have a scripted expression
- top
location if location <=0 else 0
- middle
location if location >= -1 and location <= 1 else -1 if location < 0 else 1
- bottom
location if location >=0 else 0
Now if you move the controller up, the cylinders will collapse from the bottom and if you move it down, they will collapse from the top.
I've left it as an exercise for the interested reader to modify the top and bottom expressions so that the cylinders stop moving when they've fully collapsed. The middle expression is a sort of hint.
Here's my blend file: