ABU 31-Oct-2021 - New major version 2.0
ABU 10-Aug-2024 - 2.0.1 now compatible with Tcl9
ABU 15-Aug-2024 - 2.0.2 now compatible with Tcl9 - Bug Fix for <TouchpadScroll> event
zoom-canvas is an extension of the standard tk canvas widget. Users can create,change,move all the graphical primitives (lines, polygons, ovals, ....) by simply specifying coordinates and distances based on their world coordinate-system, and then, they can control how zoom-canvas scales and translates the whole scene.
This is a screenshot of a demo included with the package.
For those who knew zoom-canvas 1.x, we must warn that zoom-canvas 2.0 is no longer backward compatible, but this lack of backward compatibility is compensated for by new advantages as the user no longer needs to explicitely convert coordinates from its own world coordinate-system to canvas coordinates and viceversa; now all the scale transformations are performed internally.
Here's another screenshot from a demo included with the package. Here we have a very long timeline that can be zoomed in the horizontal dimension only
zoom-canvas 2.0 zoom-canvas Canvas with Zoom
a canvas-widget extension
package require Tk 8.6
package require zoom-canvas 2.0
zoom-canvas is an extension of the standard canvas-widget.
zoom-canvas is fully compatible with canvas and adds new subcommands to change the zoom-factor of the whole scene. In this way, users are no more forced to scale in advance the coordinates of their world-model so that it fits in the visible part of the canvas.
Users can create,change,move all the graphical primitives (lines, polygons, ovals, ....) by simply specifying coordinates and distances based on their world coordinate-system, and then they can control how zoom-canvas scales and translates the whole scene.
It is important to remark that, independently of this apparent scaling, all the zoom-canvas items maintain their original size and position.
Example
package require zoom-canvas 2.0 zoom-canvas .zc pack .zc -expand true -fill both # create two huge discs .zc create oval -1e6 -1e6 1e6 1e6 -tag DISC_1 -outline red .zc create oval -1e7 -1e7 1e7 1e7 -tag DISC_2 -outline green .... # let zoom-canvas scale/translate the whole scene within the window .zc zoomfit ... # get the coords of DISC_1 set disc1_coords [.zc coords DISC_1] # disc1_coords is {-1e6 -1e6 1e6 1e6}
That's all about zoom-canvas. Users create and change all the graphical primitives using their world-coordinates and then control how zoom-canvas scales and translates the whole scene.
Normally the origin of the zoom-canvas coordinate-system is at the upper-left corner of the window containing the canvas (i.e. the Viewport). By default the y-axis of zoom-canvas is downwards oriented (as for the standard canvas), but it can set upwards oriented (as in mathematics) by setting the -yaxis option. to up.
As for the standard canvas-widget, it is possible to adjust the origin of the zoom-canvas coordinate-system relative to the Viewport coordinate-system using the xview/yview subcommands or the scan mark/moveto subcommands; this is typically used for scrolling.
zoom-canvas also support scaling of the whole scene using the zoom/rzoom/zoomfit subcommands.
The canvasx/canvasx subcommands map the x/y coordinates of the Viewport to the x/y coordinates of zoom-canvas (i.e. from the Viewport coordinate-system to the World coordinate-System).
The W2V subcommand does the inverse map, from World coordinates to Viewport coordinates.
zoom-canvas supports all canvas options plus the following
# create a point at WorldCoord (11,22) .zc create point 11 22 # create a point with a new bitmap .zc create point 100 200 -bitmap @/mybmps/special.xbm # create a RED point (with default bmp) and then change it to yellow set id [.zc create point 200 200 -foreground red] .zc itemconfigure $id -foreground yellow
(Wx,Wy) is the fixed-point of the zoom transformation, i.e. its apparent position does not change. If (Wx,Wy) is not specified, the fixed-point is the point related to the center of the window.
When this subcommand complets, it generates a virtual event <<Zoom>> for the purpose of notification, carrying the actual zoom factor as user_data. Binding scripts can access this user_data as the value of the %d substitution.
As for the zoom subcommand, this subcommand generates a <<Zoom>> virtual event.
(Wx,Wy) is the fixed-point of the zoom transformation, i.e. its apparent position does not change. If (Wx,Wy) is not specified, the fixed-point is the point related to the center of the window. As for the zoom subcommand, this subcommand generates a <<Zoom>> virtual event.
zoom-canvas does not provide built-in bindings, but it's easy to add mouse bindings for zooming and panning.
bind ZoomCanvas <Button-1> { %W scan mark %x %y } bind ZoomCanvas <B1-Motion> { %W scan dragto %x %y 1 }
If your app is alreading using <Button-1> and <B1-Motion> on canvas, consider using alternatives mouse-bindings like <Control-Button-1> <Control-B1-Motion> or ... use the scrollbars ! (scrollbars are old-fashioned)
IMPORTANT NOTE on scrolling the viewport (panning):
If no scrollregion is set, then you could move the viewport with no limits. If you want to limit the scrolling, you should set the scrollregion AND be sure the -confine option is set to 1 (this is the default), like in the following example:
.zc configure -scrollregion [.zc bbox all]
The following command binds the <MouseWheel> event with the rzoom subcommand. Note that zoom is centered on the cursor position and that the zoom coefficient may by adjusted with the -zmultiplier configuration option.
bind ZoomCanvas <MouseWheel> { %W rzoom %D [%W canvasx %x] [%W canvasy %y] }
Event <<Zoom>> is generated when zoom changes. This virtual-event carries some data that may be caught in binding script by the %d substitution keyword. Parameter %d holds the new zoom factor
zoom-canvas .zc -background orange pack .zc -fill both -expand true # set the zoom-factor to 0.1x .zc zoom 0.1 # Draw a circle and a rectangle .zc create oval 0 0 3000 3000 .zc create rectangle 0 0 3000 3000 # Move all items by (500,200) (in world coords) .zc move all 500 200 # note that the 'apparent translation' is only 0.1*(500,200) # add a binding on mouse movement and print the position (in world-coords) bind .zc <Button-1> { puts "You picked [%W canvasxy [list %x %y]]" }
You can find many other examples within the "demo" directory of the zoom-canvas package.
Snit, canvas, widget
widgets
Copyright (c) 2021-2024, by A.Buratti