Arjen Markus (28 march 2011) The canvas is a very flexible widget with an incredible amount of functionality. Some of that functionality is not always easy to master. This page is concerned with scaling and scrolling the contents of a canvas widget. To understand how to do that you need to know a few things:
With these two features in mind I wrote the following program (the question came up in the Tcl chatroom):
# scalingcanvas.tcl --
# Example of scaling and scrolling a canvas
#
#
# Set up the canvas with scrollbars
#
canvas .c -bg white -xscrollcommand {.x set} -yscrollcommand {.y set}
scrollbar .x -orient horizontal -command {.c xview}
scrollbar .y -orient vertical -command {.c yview}
grid .c .y -sticky news
grid .x -sticky news
grid columnconfigure . 0 -weight 1
grid rowconfigure . 0 -weight 1
#
# Fill the canvas with a few items
#
.c create oval 100 100 200 200 -fill red -outline black -width 2
.c create rectangle 150 50 175 275 -outline green -width 4
.c create rectangle 0 0 2 2 -fill black ;# Origin
.c create rectangle 148 148 152 152 -fill black ;# Centre circle
#
# Set up a default scroll region
#
.c configure -scrollregion [list 0 0 [.c cget -width] [.c cget -height]]
#
# Now we will zoom in to the circle's centre (150,150) and make sure this
# is in the middle of the canvas
#
# 1. Scale all items by a factor of two
# 2. Adjust the scroll region accordingly
# 3. Scroll the canvas to the right position
#
# canvas - canvas in question
# xcentre, ycentre - coordinates for the centre of the scaling
# factor - factor by which to scroll
#
proc scaleAndScroll {canvas xcentre ycentre factor} {
$canvas scale all $xcentre $ycentre $factor $factor
set scrollRegion [$canvas cget -scrollregion]
set newRegion {}
lassign $scrollRegion xmin ymin xmax ymax
set xmin [expr {$xcentre + ($xmin - $xcentre) * $factor}]
set ymin [expr {$ycentre + ($ymin - $ycentre) * $factor}]
set xmax [expr {$xcentre + ($xmax - $xcentre) * $factor}]
set xmax [expr {$xcentre + ($ymax - $xcentre) * $factor}]
$canvas configure -scrollregion [list $xmin $ymin $xmax $ymax]
}
#
# canvas - canvas in question
# xcoord, ycoord - coordinates for the centre of the scaling
#
proc toCentre {canvas xcoord ycoord} {
lassign [$canvas cget -scrollregion] xmin ymin xmax ymax
#
# Compute the fraction:
# "$xcoord - 0.5 * $width" is the x-coordinate of the point
# that will appear at the top-left corner
#
set width [$canvas cget -width]
set height [$canvas cget -height]
set xfrac [expr {($xcoord - 0.5 * $width - $xmin) / ($xmax - $xmin)}]
set yfrac [expr {($ycoord - 0.5 * $height - $ymin) / ($ymax - $ymin)}]
$canvas xview moveto $xfrac
$canvas yview moveto $yfrac
}
scaleAndScroll .c 150 150 2.0
# Show new origin
.c create rectangle 0 0 2 2 -fill blue -outline blue
after 2000 {
toCentre .c 150 150
}