Changes between Initial Version and Version 1 of PerlMapScriptExamples35ex18


Ignore:
Timestamp:
Jan 29, 2009, 7:12:37 AM (15 years ago)
Author:
jmckenna
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PerlMapScriptExamples35ex18

    v1 v1  
     1Using HTML::Template allows (almost) complete separation of programming from display. Not only is this useful if separating responsibility for programming from html and web design, it is also a cleaner code which allows for easy changes later on as new functionality is added to the application.
     2
     3There are many templating solutions in the Perl world. I like HTML::Template for its utter simplicity and effectiveness at doing what it claims to do.
     4
     5The following Perl script/template combo shows a simple example of making a map and displaying it.
     6----
     7{{{
     8#!perl
     9        #!/usr/bin/perl -w
     10
     11        # Import the modules
     12        use strict;
     13        use CGI::Pretty qw(:standard);
     14        use HTML::Template;
     15        use mapscript;
     16
     17        # Create new template
     18        my $template = HTML::Template->new( filename => 'index.tmpl' );
     19
     20        $ENV{MS_ERRORFILE} = "path/to/mapserver.log";                     # Mapserver error log
     21
     22        # create a new map object
     23        my $mapObj = new mapscript::mapObj("mymapfile.map") or die("$mapscript::ms_error->{message}");
     24
     25        my @draw_layers = param('draw_layer');                            # layers to be drawn submitted by the user
     26                                                                          # submitted as form variables, usually via
     27                                                                          # checkboxes checked or unchecked for the
     28                                                                          # layers to be drawn.
     29
     30        my @layers;                                                       # layers to be sent back to the browser to
     31                                                                          # construct the set of checkboxes so the
     32                                                                          # user may choose what to draw
     33
     34        my $tool = param("tool") eq "" ? "zoomin" : param("tool");        # currently selected tool
     35
     36        my $x = param("map.x");                                           # coordinates of the mouseclick on the map
     37        my $y = $mapObj->{height} - param("map.y");                       # invert the y coordinate because image
     38                                                                          # origin is top-left while map origin is
     39                                                                          # bottom-left
     40
     41        my $zf = 2;                                                       # zoom in/out by this much
     42        my $jitter = 20;                                                  # Catch jerky mouse movement
     43
     44        my $mapname_suf = time() . ".png";                                # Tmp map and legend image names
     45        my $mapimgname = $mapObj->{name} . "_map_" . $mapname_suf;        #
     46
     47        # Store max extent
     48        my $mminx = $mapObj->{extent}->{minx};
     49        my $mminy = $mapObj->{extent}->{miny};
     50        my $mmaxx = $mapObj->{extent}->{maxx};
     51        my $mmaxy = $mapObj->{extent}->{maxy};
     52
     53        # variables to hold new extent
     54        my ($minx, $miny, $maxx, $maxy);
     55
     56        # $currect are the current geo rect coords used to calc the new geo rect coords.
     57        # $currect arrives at the server as a hidden form field submitted by the user.
     58        # split the form field value into component bounding coordinates.
     59        my ($f_minx, $f_miny, $f_maxx, $f_maxy) = split(" ", param("currect"));
     60
     61        # Check if this is the first visit or a return visit. If $f_minx variable
     62        # (or any of the form variables calculated above) is empty then this is the
     63        # first visit
     64        if (($f_minx eq "") || ($tool eq "zoomall")) {
     65
     66          # make new extent equal to max extent
     67          ($minx, $miny, $maxx, $maxy) = ($mminx, $mminy, $mmaxx, $mmaxy);
     68
     69                for (0..$mapObj->{numlayers} - 1) {
     70                        my $layerObj = $mapObj->getLayer($_);
     71                        my %layer = (   
     72                                                                        'layername' => $layerObj->{name},
     73                                                                        'layerindx' => $layerObj->{index},
     74                                                                        'layerchek' => $layerObj->{status} ? "checked" : ""
     75                                                                );
     76                        push(@layers, \%layer);
     77                }
     78
     79        } else {
     80
     81                # Calc the amount of $zf based on the kind of redraw tool.
     82                # Pan will have a $zf of 1, while zoomout will inverse the $zf.
     83                # Leave $zf alone in case of zoomin.
     84                if ($tool eq "pan") { $zf = 1; } elsif ($tool eq "zoomput") { $zf = 1 / $zf; }
     85
     86          # Calculate cellsize in x and y directions. cellsize is the geographic
     87          # size of each pixel on the screen.
     88                my $old_ground_width = $f_maxx - $f_minx;
     89                my $old_ground_height = $f_maxy - $f_miny;
     90
     91          my $cx = $old_ground_width / $mapObj->{width};
     92          my $cy = $old_ground_height / $mapObj->{height};
     93
     94                my $new_ground_width = $old_ground_width / $zf;
     95                my $new_ground_height = $old_ground_height / $zf;
     96
     97          # use the cellsize and the zoom to calc the new extent
     98          $minx = ($f_minx + ($x * $cx)) - ($new_ground_width / 2);
     99                $miny = ($f_miny + ($y * $cy)) - ($new_ground_height / 2);
     100                $maxx = ($f_minx + ($x * $cx)) + ($new_ground_width / 2);
     101                $maxy = ($f_miny + ($y * $cx)) + ($new_ground_height / 2);
     102
     103                # now figure out what layers to draw.
     104                # loop over all the layers...
     105                for (0..$mapObj->{numlayers} - 1) {
     106
     107                        # get the layer
     108                        my $layerObj = $mapObj->getLayer($_);
     109
     110                        # toggle layer on if requested by user, otherwise toggle off
     111                        $layerObj->{status} = grep($layerObj->{index} == $_, @draw_layers) ? 1 : 0;
     112                        my %layer = (   
     113                                                                        'layername' => $layerObj->{name},
     114                                                                        'layerindx' => $layerObj->{index},
     115                                                                        'layerchek' => $layerObj->{status} ? "checked" : ""
     116                                                                );
     117                        push(@layers, \%layer);
     118
     119                }
     120
     121        }
     122
     123        # set the new map extent
     124        $mapObj->{extent}->{minx} = $minx; $mapObj->{extent}->{miny} = $miny;
     125        $mapObj->{extent}->{maxx} = $maxx; $mapObj->{extent}->{maxy} = $maxy;
     126
     127        # create the map
     128        my $imgObj = $mapObj->draw() or die('Unable to draw map');
     129        $imgObj->saveImage(
     130                                                                                $mapimgname,
     131                                                                                $mapscript::MS_PNG,
     132                                                                                $mapObj->{interlace},
     133                                                                                $mapObj->{transparent},
     134                                                                                $mapObj->{imagequality}
     135                                                                        );
     136
     137        # ref to array of layers info to be sent back to the browser
     138        $template->param(layers => \@layers);
     139
     140        # create vars to be sent back to the browser
     141        $template->param(map_img => "path/to/$mapimgname");
     142
     143        $template->param(currect => "$minx $miny $maxx $maxy");
     144
     145        #reset the tool to zoomin, if necessary
     146        $template->param(tool => ($tool eq "zoomall") ? "zoomin" : "$tool");
     147
     148        # Send the obligatory Content-Type and output the template
     149        print "Content-Type: text/html\n\n";
     150        print $template->output;
     151        exit(0);
     152}}}
     153Meanwhile, in the template...
     154{{{
     155        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
     156
     157        <html>
     158        <head>
     159                <title>My Mapping Application</title>
     160        </head>
     161
     162        <body>
     163
     164        <form name="mapform" action="index.cgi" method="post">
     165
     166                <table>
     167                        <!-- start map toolbar -->
     168                        <tr>
     169                                <td colspan="2">
     170                                        <input type="radio" name="tool" value="zoomin" checked>
     171                                        <input type="radio" name="tool" value="zoomout">
     172                                        <input type="radio" name="tool" value="zoomall" onClick="document.mapform.submit();">
     173                                        <input type="radio" name="tool" value="pan">
     174                                </td>
     175                        </tr>
     176                        <!-- end map toolbar -->
     177
     178                        <tr>
     179                                <!-- start checkboxes for layers -->
     180                                <td>
     181                                <!-- start layers loop -->
     182                                <tmpl_loop layers>
     183                                        <input type="checkbox" name="draw_layer" value="<tmpl_var layerindx>" <tmpl_var layerchek>>
     184                                        <tmpl_var layername>
     185                                </tmpl_loop>
     186                                <!-- end layers loop -->
     187                                </td>
     188                                <!-- end checkboxes for layers -->
     189
     190                                <!-- start map image -->
     191                                <td>
     192                                        <input type="image" name="map" src="<tmpl_var map_img>" border="1">
     193                                        <input type="hidden" name="currect" value="<tmpl_var currect>">
     194                                        <input type="hidden" name="tool" value="<tmpl_var tool>">
     195                                </td>
     196                                <!-- end map image -->
     197                        </tr>
     198                </table>
     199
     200        </form>
     201
     202        </body>
     203        </html>
     204}}}
     205I encourage reading documentation for HTML::Template, and using it or some other templating solution to create web applications. Email me if further help is needed, or ask on the list.
     206
     207-- Puneet Kishor (pkishor at geoanalytics dot com)
     208----
     209back to PerlMapScript