forked from MapServer/MapServer
-
Notifications
You must be signed in to change notification settings - Fork 2
PerlMapScriptExamples35ex18
Thomas Bonfort edited this page Apr 6, 2012
·
2 revisions
Using 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.
There 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.
#!perl
#!/usr/bin/perl -w
# Import the modules
use strict;
use CGI::Pretty qw(:standard);
use HTML::Template;
use mapscript;
# Create new template
my $template = HTML::Template->new( filename => 'index.tmpl' );
$ENV{MS_ERRORFILE} = "path/to/mapserver.log"; # Mapserver error log
# create a new map object
my $mapObj = new mapscript::mapObj("mymapfile.map") or die("$mapscript::ms_error->{message}");
my @draw_layers = param('draw_layer'); # layers to be drawn submitted by the user
# submitted as form variables, usually via
# checkboxes checked or unchecked for the
# layers to be drawn.
my @layers; # layers to be sent back to the browser to
# construct the set of checkboxes so the
# user may choose what to draw
my $tool = param("tool") eq "" ? "zoomin" : param("tool"); # currently selected tool
my $x = param("map.x"); # coordinates of the mouseclick on the map
my $y = $mapObj->{height} - param("map.y"); # invert the y coordinate because image
# origin is top-left while map origin is
# bottom-left
my $zf = 2; # zoom in/out by this much
my $jitter = 20; # Catch jerky mouse movement
my $mapname_suf = time() . ".png"; # Tmp map and legend image names
my $mapimgname = $mapObj->{name} . "_map_" . $mapname_suf; #
# Store max extent
my $mminx = $mapObj->{extent}->{minx};
my $mminy = $mapObj->{extent}->{miny};
my $mmaxx = $mapObj->{extent}->{maxx};
my $mmaxy = $mapObj->{extent}->{maxy};
# variables to hold new extent
my ($minx, $miny, $maxx, $maxy);
# $currect are the current geo rect coords used to calc the new geo rect coords.
# $currect arrives at the server as a hidden form field submitted by the user.
# split the form field value into component bounding coordinates.
my ($f_minx, $f_miny, $f_maxx, $f_maxy) = split(" ", param("currect"));
# Check if this is the first visit or a return visit. If $f_minx variable
# (or any of the form variables calculated above) is empty then this is the
# first visit
if (($f_minx eq "") || ($tool eq "zoomall")) {
# make new extent equal to max extent
($minx, $miny, $maxx, $maxy) = ($mminx, $mminy, $mmaxx, $mmaxy);
for (0..$mapObj->{numlayers} - 1) {
my $layerObj = $mapObj->getLayer($_);
my %layer = (
'layername' => $layerObj->{name},
'layerindx' => $layerObj->{index},
'layerchek' => $layerObj->{status} ? "checked" : ""
);
push(@layers, \%layer);
}
} else {
# Calc the amount of $zf based on the kind of redraw tool.
# Pan will have a $zf of 1, while zoomout will inverse the $zf.
# Leave $zf alone in case of zoomin.
if ($tool eq "pan") { $zf = 1; } elsif ($tool eq "zoomput") { $zf = 1 / $zf; }
# Calculate cellsize in x and y directions. cellsize is the geographic
# size of each pixel on the screen.
my $old_ground_width = $f_maxx - $f_minx;
my $old_ground_height = $f_maxy - $f_miny;
my $cx = $old_ground_width / $mapObj->{width};
my $cy = $old_ground_height / $mapObj->{height};
my $new_ground_width = $old_ground_width / $zf;
my $new_ground_height = $old_ground_height / $zf;
# use the cellsize and the zoom to calc the new extent
$minx = ($f_minx + ($x * $cx)) - ($new_ground_width / 2);
$miny = ($f_miny + ($y * $cy)) - ($new_ground_height / 2);
$maxx = ($f_minx + ($x * $cx)) + ($new_ground_width / 2);
$maxy = ($f_miny + ($y * $cx)) + ($new_ground_height / 2);
# now figure out what layers to draw.
# loop over all the layers...
for (0..$mapObj->{numlayers} - 1) {
# get the layer
my $layerObj = $mapObj->getLayer($_);
# toggle layer on if requested by user, otherwise toggle off
$layerObj->{status} = grep($layerObj->{index} == $_, @draw_layers) ? 1 : 0;
my %layer = (
'layername' => $layerObj->{name},
'layerindx' => $layerObj->{index},
'layerchek' => $layerObj->{status} ? "checked" : ""
);
push(@layers, \%layer);
}
}
# set the new map extent
$mapObj->{extent}->{minx} = $minx; $mapObj->{extent}->{miny} = $miny;
$mapObj->{extent}->{maxx} = $maxx; $mapObj->{extent}->{maxy} = $maxy;
# create the map
my $imgObj = $mapObj->draw() or die('Unable to draw map');
$imgObj->saveImage(
$mapimgname,
$mapscript::MS_PNG,
$mapObj->{interlace},
$mapObj->{transparent},
$mapObj->{imagequality}
);
# ref to array of layers info to be sent back to the browser
$template->param(layers => \@layers);
# create vars to be sent back to the browser
$template->param(map_img => "path/to/$mapimgname");
$template->param(currect => "$minx $miny $maxx $maxy");
#reset the tool to zoomin, if necessary
$template->param(tool => ($tool eq "zoomall") ? "zoomin" : "$tool");
# Send the obligatory Content-Type and output the template
print "Content-Type: text/html\n\n";
print $template->output;
exit(0);
Meanwhile, in the template...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>My Mapping Application</title>
</head>
<body>
<form name="mapform" action="index.cgi" method="post">
<table>
<!-- start map toolbar -->
<tr>
<td colspan="2">
<input type="radio" name="tool" value="zoomin" checked>
<input type="radio" name="tool" value="zoomout">
<input type="radio" name="tool" value="zoomall" onClick="document.mapform.submit();">
<input type="radio" name="tool" value="pan">
</td>
</tr>
<!-- end map toolbar -->
<tr>
<!-- start checkboxes for layers -->
<td>
<!-- start layers loop -->
<tmpl_loop layers>
<input type="checkbox" name="draw_layer" value="<tmpl_var layerindx>" <tmpl_var layerchek>>
<tmpl_var layername>
</tmpl_loop>
<!-- end layers loop -->
</td>
<!-- end checkboxes for layers -->
<!-- start map image -->
<td>
<input type="image" name="map" src="<tmpl_var map_img>" border="1">
<input type="hidden" name="currect" value="<tmpl_var currect>">
<input type="hidden" name="tool" value="<tmpl_var tool>">
</td>
<!-- end map image -->
</tr>
</table>
</form>
</body>
</html>
I 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.
back to PerlMapScrip