Version 0 of Move an item on a Canvas Widget in a Straight Line (animated)

Updated 2004-07-15 16:14:18 by MG

if 0 {July 15th 2004 - MG After a quick search of the Wiki, I couldn't find a page explaining how to do this, so thought I'd knock something up myself. On a canvas widget, if you have an item which you want to move, it's simple enough to do; $widget move $item $xAmount $yAmount. But, if you want the movement to be animated - so that the item moves a bit at a time - it's a little more difficult. This is something I wanted for my Spider Solitaire game, so that the cards could be dealt in a slightly more noticable fashion; once I finish this page and get around to adding it to the game, you can see it for a working implimentation. (Hence the example :)

The proc below works so that the item on the canvas moves an even amount (by both X and Y) every time. The variables passed to it are $c (the path to the canvas widget), $item (the ID of the item on the canvas, returned by canvas create), $tox and $toy (the x and y coords to move to, respectively), $time (how long to wait between each move), and $steps, which can be moved to speed it up more (see below).

$steps works like this: if you're moving from coords 0 0 to coords 100 50, by default it'll move one x coordinate and half a y coordinate at a time: to 1 .5, 2 1, 3 1.5, etc. $steps will be multiplied by the default amount; so, with $steps set to 4, it'll move to 4 2, 8 4, 12 6, and so on. (No, explaining things I code isn't my strong point;)

Anyway, here's the code. :)

}

 # Mike Griffiths, July 15th 2004.
 # Move an item on a canvas from one coordinate set to another, animated.
 proc cMove {c item tox toy {time 25} {steps 1}} {

 scan [$c coords $item] "%s %s" origx origy
 set diffx [expr {abs($origx-$tox)}]
 set diffy [expr {abs($origy-$toy)}]

 if { $diffx > $diffy } {
      set stepy [expr {$steps*1}] ; set stepx [expr {$steps*(double($diffx) / $diffy)}]
    } else {
      set stepx [expr {$steps*1}] ; set stepy [expr {$steps*(double($diffy) / $diffx)}]
    }
 set dirx ">" ; set diry ">"
 if { $origx > $tox } {
      set stepx [expr {$stepx*-1}] ; set dirx "<"
    }
 if { $origy > $toy } {
      set stepy [expr {$stepy*-1}] ; set diry "<"
    }
 while {1} {
   scan [$c coords $item] "%s %s" nowx nowy
   if { [expr {round(($nowx-$tox)+($nowy-$toy))}] == 0 } {return;}
   if { [expr {round($nowx-$tox)}] == 0 } {
        set stepx 0
      } elseif " [expr {$nowx+$stepx}] $dirx $tox " {
        set stepx [expr {$tox-$nowx}]
      }
   if { [expr {round($nowy-$toy)}] == 0 } {
        set stepy 0
      } elseif " [expr {$nowy+$stepy}] $diry $toy " {
        set stepy [expr {$toy-$nowy}]
      }
   $c move $item $stepx $stepy
   update idletasks
   after $time
  }

 };# move

if 0 {

 And a small demo...

}

  pack [canvas .c -height 500 -width 500 -bg "dark green"]

  image create photo myimg -format gif -data {
       R0lGODlhRwBgAKEAAH//1AAAAP////8AACH5BAEAAAAALAAAAABHAGAAAAL/BIKpy+0PYzBH2I
       uz3rz7L0wBSJamiZzquqbawMZyOL7zfbrYwOP+p7vwYL+iJijo9YxMWkZJbBaDy2RUiqMOh9if
       bgvuZmvW51XMcm2FXHRM3bZW3SokfUq+G+36MRsW15dTs7YmOGgBZnhYAqd4xujhqBjZSPZYab
       mzmAmUJ9ep+RQqStryaVqaioK66umKCKsqK9lKe2R7i8Gnu5vb6wTMwStMLLPI6WdESen1u4KJ
       6WMM/Sit/GN9fUOtot2M7fMdNv1cPY7HND7HbX5uvef+Tp4ute3cRR8vFrjP39XtVkBaA2UVhH
       XQVcJVC1M1NPWQVMRQEztVzHTxDqSMYm76ceTH6SOWayKbaLNQUh28YLROspRVqE1KlYCqzLxz
       k05ONztnIJMp79DPJT19nrEZVOjKl7C2FTXKxlcvKBmeQmVn1ejGpJH6MW25IavPsFwZlnVYQV
       hVChLaun3b1kABADs=}

   set item [.c create image 100 100 -image myimg -anchor center]
   move .c $item 250 375 10

if 0 {


[Category Animation] (kind of:) | [Canvas]]