zoom-canvas

Difference between version 7 and 13 - Previous - Next
*** EDITING IN PROGRESS ***

[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 model 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''' [https://sourceforge.net/projects/irrational-numbers/files/zoom-canvas/zoom-canvas-2.0.zip/download]  31-oct-2021****
        * New Major release - Full documentation and demos included
****'''zoom-canvas 1.0.3''' [https://sourceforge.net/projects/irrational-numbers/files/zoom-canvas/zoom-canvas-1.0.3.zip/download]  2-jul-2018****
        * OBSOLETE - Full documentation and demos


<<discussion>> 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 ''pathName'''s 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


<<discussion>>
<<categories>> Extension | canvas | Widget