zoom-canvas

ABU 31-Oct-2021 - New major version 2.0

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.

Image ToyPlanetsDemo2.0

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

Image TimelineDemo2.0

Download

zoom-canvas 2.0 [L1 ] 31-oct-2021

  • New Major release - Full documentation and demos included

zoom-canvas 1.0.3 [L2 ] 2-jul-2018

  • OBSOLETE - Full documentation and demos

  Reference manual - zoom-canvas 2.0

zoom-canvas 2.0 zoom-canvas Canvas with Zoom

a canvas-widget extension

SYNOPSIS

package require Tk 8.6

package require zoom-canvas 2.0

  • zoom-canvas pathName ?options?
  • pathName create point x y ?option value...?
  • pathName zoom
  • pathName zoom zf ?Wx Wy?
  • pathName zoomfit ?mode? ?Wx0 Wy0 Wx1 Wy1?
  • pathName rzoom delta ?Wx Wy?
  • pathName overlap Wx Wy Vx Vy
  • pathName canvasxy Point
  • pathName W2V x y ?x y ...?
  • pathName W2V 'coordlist'

DESCRIPTION

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.

Coordinates and Transformations

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.

WIDGET OPTIONS

zoom-canvas supports all canvas options plus the following

zoom-canvas specific options

-zoommode mode
by default it is set to xy, meaning that x and y coords will be equally zoomed. When this option is set to x or y, then only the x (or the y) coordinate will be zoomed. This may be useful if you have a long horizontal (or vertical) axes you want to zoom keeping the other dimension unchanged.
-zmultiplier coeff
Specifies a coefficient used for relative zoom (see rzoom). It should be greater than 1.0. Default is 1.4142... (square root of two)
-yaxis orientation
Specifies the orientation of the y-axis. orientation can be up or down. Default value is down as for the standard canvas-widget. This option can be set only at creation-time, it cannot changed with the configure widget command.
-pointbmp xxx
Specifies the default bitmap used for the (new) point items. Note that argument should be the name of a predefined bitmap (e.g. a bitmap like "hourglass", "info", "quest_head" ... see Tk_GetBitmap), or the name of a file containing a bitmap, in standard X11 or X10 bitmap format. Filenames must be prefixed by @ (e.g. @/mybmps/start.xbm). The predefined bitmap is @/.../point.xbm, bundled within the package.
-userdata data
it can be used for storing any kind of data (for storing multiple values, a dictionary data is recommended)

WIDGET COMMANDS

zoom-canvas pathName ?options?
The zoom-canvas command creates a new widget (given by the pathName argument). Additional options, described above, may be specified on the command line or in the option database to configure default aspects of the zoom-canvas. At the time this command is invoked, there must not exist a window named pathName, but pathNames parent must exist. The zoom-canvas' command returns its pathName argument. Once created, pathName may be used to invoke all the standard canvas-widget subcommands plus the following

zoom-canvas specific commands

pathName create point x y ?option value...?
Create a point (actually a small bitmap) located at (x,y) Options are those of canvas-bitmap-item-type. If you omit the -bitmap option, the default-bitmap is used (see -pointbmp option).
  # 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
pathName zoom
Get the current zoom-factor
pathName zoom zf ?Wx Wy?
Set the current zoom-factor. zf can even be negative (axis directions will be inverted) but it cannot be 0 (or very close to 0).

(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.

pathName zoomfit ?mode? ?Wx0 Wy0 Wx1 Wy1?
Find and set the best zoom-factor so that all the canvas items (or those enclosed by Wx0 Wy0 Wx1 Wy1) will be visible. mode can be x (best-width) y (best-height) xy (best fit). Default is xy (best-fit.)

As for the zoom subcommand, this subcommand generates a <<Zoom>> virtual event.

pathName rzoom delta ?Wx Wy?
If delta is positive, the current zoom-factor is multiplied by the -zmultiplier option's value. If delta is negative, the current zoom-factor is divided by the -zmultiplier option's value. If delta is 0, no zoom is performed.

(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.

pathName overlap Wx Wy Vx Vy
Collimate World-Point (Wx,Wy) with Viewport-Point (Vx,Vy). (Viewport coordinates must be integers). Items don't change their intrinsic coordinates; it's only a viewport scrolling.
pathName canvasxy Point
Point is a list of two integers, i.e. a Viewport's point. Result is the corresponding point in World coords. (this is just a convenience subcommand based on canvasx and canvasy).
pathName W2V x y ?x y ...?
pathName W2V 'coordlist'
Convert a sequence of x y coords (or a list of x y coords), expressed as WorldCoords, returning a list with the corresponding Viewport coords. This may be useful for finding if a point (expressed in world-cordinate) is within the Viewport (i.e. the canvas visibile areaa). Just test if the returned x-coord is between 0 and [winfo width .zc] and the returned y.coord is between 0 and [winfo height .zc]

BINDINGS

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] }

EVENTS

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

Examples

 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.

  • demo/demo.tcl - a basic interactive demo showing the corrispondence between Viewport coordinates and World coordinates.
  • demo/toy_planet_demo.tcl - here the 'world model' is the solar system; planets and their orbits are expressed in kilometers (these are still huge measures..).
  • demo/timeline_demo.tcl - here a huge timeline from year 1900 to 2020 can be interactively zoomed, just in the horizontal dimension.

Limitations

  • Item-text, item-images and item-windows won't zoom ! (but this could be a benefical limitation, e.g. when drawing a map, text and small images (icons) won't zoom !)
  • Line's width (thickness) won't zoom. (.. same as above)
  • Coordinates and distances should be specified as simple numbers; no c,i,m,p suffix is allowed

BUGS, IDEAS, FEEDBACK

  • -
  • -

KEYWORDS

Snit, canvas, widget

CATEGORY

widgets

COPYRIGHT

 Copyright (c) 2021, by A.Buratti