3
$\begingroup$

I have a problem with Manipulate. I want to stop my animation depending on a condition on the value A, which is controlled by a manipulator. I tried to do this by giving the animator specified for variable x the option AnimationRunning -> If[Tan[A] <= 0.7, False, True]. That stopped the animation, but didn't stop the animation clock, which depends on the computer's real-clock time. So when the animation is restarted by increasing A above 0.7, the animation jumps to the place determined by the current clock time, which didn't stop while the graphics updating was paused.

I think I need to stop the animation clock when the graphics updating is paused. My idea is to get access to PlayPauseButton to click it in code. But i have no idea how to do it..

I will be grateful for any help.

Manipulate[
 Graphics[
  {
   {FaceForm[], EdgeForm[{Thick, Gray}], AASTriangle[Pi/2, A, 1]},
   Translate[{{FaceForm[], EdgeForm[{Thickness[0.004], Blue}],
      Rotate[{{Rectangle[{0, Sin[A] + 0.006}, {0.15, 
           Sin[A] + 0.08}]}}, -A, {0, Sin[A]}]}},
    {x*Cos[A], -x*Sin[A]}
    ]
   },
  PlotRange -> {{0, 1}, {0, 1}}, Axes -> False, ImageSize -> {400, 400}
  ],
 {{A, Pi/4, "A"}, 0.0001, Pi/2 - 0.0001},
 {{x, 0}, 0, 1 - 0.15, ControlType -> Animator, 
  AnimationRunning -> If[Tan[A] <= 0.7, False, True], 
  AnimationRunTime -> Dynamic[t], AnimationTimeIndex -> Dynamic[indx]},
 Dynamic[x],
 Dynamic[t],
 Dynamic[indx],
 ControlPlacement -> Left
 ]

enter image description here

$\endgroup$
1
  • $\begingroup$ I've implemented animations that required the level of control you are seeking, but I could never figure out how to do it with Manipulate or Animate. I had to fall back on the lower level construct DynamicModule and implement updating the graphics from the system clock by calling AbsoluteTime. It wasn't all that hard, but I had to implement my own Play, Pause, and Reset buttons. You might do the same for your code, unless someone smarter than me comes up with a way to do with Manipulate. $\endgroup$
    – m_goldberg
    Commented Jan 26, 2019 at 19:14

2 Answers 2

2
$\begingroup$

Ok. I think I found solution. Maybe someone someday will be need it. It is not exactly what i wanted but it works properly

Manipulate[
 {Animator[Dynamic[x], {0, 1 - 0.15}, 
   AnimationRunning -> If[A <= 0.7, False, True], 
   AnimationRunTime -> Dynamic[ti]],
  Graphics[{{FaceForm[], EdgeForm[{Thick, Gray}], 
     AASTriangle[Pi/2, A, 1]},
    Translate[{{FaceForm[], EdgeForm[{Thickness[0.004], Blue}],
       Rotate[{{Rectangle[{0, Sin[A] + 0.006}, {0.15, 
            Sin[A] + 0.08}]}}, -A, {0, Sin[A]}]}}, {Dynamic[x]*
       Cos[A], -Dynamic[x]*Sin[A]}]},
   PlotRange -> {{0, 1}, {0, 1}}, Axes -> False, 
   ImageSize -> {400, 400}]},
 {{A, Pi/4, "A"}, 0.0001, Pi/2 - 0.0001},
 Dynamic[ti], ControlPlacement -> Left]

enter image description here

$\endgroup$
1
  • $\begingroup$ The trouble with this solution is the one that forced me use DynamicModule: it destroys the functionality of the animator's Pause / Play button. You can get the rectangle moving below the critical angle with the Pause / Play button which shouldn't happen. $\endgroup$
    – m_goldberg
    Commented Jan 27, 2019 at 7:50
1
$\begingroup$

I think this does what is desired. The basic idea is to keep track of how long it is paused because the angle of inclination is too shallow.

With[{$defaultDuration = 5., x1 = 0., x2 = 1 - 0.15},
 Manipulate[
  With[{x = Mod[xx + dx, 1 - 0.15]},
   Graphics[{{FaceForm[], EdgeForm[{Thick, Gray}], AASTriangle[Pi/2, A, 1]}, 
     Translate[{{FaceForm[], EdgeForm[{Thickness[0.004], Blue}], 
        Rotate[{{Rectangle[{0, Sin[A] + 0.006}, {0.15, Sin[A] + 0.08}]}},
           -A, {0, Sin[A]}]}}, {x*Cos[A], -x*Sin[A]}]},
    PlotRange -> {{0, 1}, {0, 1}}, Axes -> False, ImageSize -> {400,400}]
   ],
  {{A, Pi/4, "A"}, 0.0001, Pi/2 - 0.0001},
  {{xx, 0, HoldForm[x]}, x1, x2, ControlType -> Animator,
   AnimationRate -> Dynamic[rate],
   AnimationRunning -> Dynamic[running && If[Tan[A] <= 0.7,
       If[state, iOld = indx]; state = False,
       True], (running = #) &],
   AnimationRunTime -> Dynamic[t],
   AnimationTimeIndex -> Dynamic[indx,
     (indx = #; If[! state, state = True; dx += (iOld - indx)*rate]) &],
   DefaultDuration -> $defaultDuration},
  {{state, True}, None}, {{running, True}, None},
  {{rate, (x2 - x1)/$defaultDuration}, None}, {{iOld, 0.}, None},
  {{dx, 0.}, None}, {{indx, 0.}, None},
  ControlPlacement -> Left]
 ]

The initial With was used to better show the dependencies on DefaultDuration and the length of the interval for the animation variable x (or in my code xx). It is not a necessary feature of the code.

$\endgroup$
3
  • $\begingroup$ The trouble with this solution is the one that forced me use DynamicModule: it destroys the functionality of the animator's Pause and Play buttons. Try to use those buttons in your Manipulate panel. You will see what I mean. $\endgroup$
    – m_goldberg
    Commented Jan 27, 2019 at 7:43
  • $\begingroup$ @m_goldberg That's a feature of the OP that was not mentioned as a problem. I considered just using Clock instead of Animator, which would seem to me to give a more natural user-interface. I've updated the code so that the pause/play and the animation rate buttons operate properly. $\endgroup$
    – Michael E2
    Commented Jan 27, 2019 at 12:08
  • $\begingroup$ The revised code is very nice and I have up-voted it. I think it satisfies all my objections. If I were the OP, this would be the answer I would accept. $\endgroup$
    – m_goldberg
    Commented Jan 27, 2019 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.