Daily Archives: 06/04/2013

GeoExt1.1で印刷してみる。実践編[Chapter 12]

GeoExt1.1で印刷してみる。実践編[Chapter 12]

それでは、GeoExt1.1で印刷してみる。準備編[Chapter 11] に引き続き、印刷機能を追加していきます。

[Chapter 11] でGeoExtでprintを行うために、GeoServerをInstallして、print moduleを追加して、GeoServerがserviceを開始したところまでは確認できました。

今回はPDFへ出力、PrintPreview formの表示の2つを作成します。

JavaScriptの構成

私のAptana のフォルダー構成は、
blog.godo-tys.jp_wp-content_gallery_geoext_12_image04.jpg

な感じです。

ここで、lib folderは、SimplePrint/libを利用しました。また、resources folderはPrintPreview/resourcesを利用しました。

その他は、GeoExt Tutorialで利用するExtJS-3.4.1,GeoExt1.1,OpenLayers-2.12を利用します。

Simple Print

まずは、Browserに表示したmapをPDFへ出力してみましょう。
htmlとjsに分けて記述していきます。
まずは、htmlファイルです。
ファイ名は、SimplePrint.html

[html]
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>GeoExt Print Your Page</title>

<script type="text/javascript" src="ext-3.4.1/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-3.4.1/ext-all-debug.js"></script>
<link rel="stylesheet" type="text/css" href="ext-3.4.1/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="ext-3.4.1/examples/shared/examples.css" />
<script src="OpenLayers/OpenLayers.js"></script>
<script type="text/javascript" src="GeoExt/lib/GeoExt.js"></script>

<!– SimplePrint.js 追加 –>
<script type="text/javascript" src="SimplePrint.js"></script>

<!– The script below will load the capabilities of the print service
and save them into the global printCapabilities variable. Instead
of this, the PrintProvider can be configured with a url and take
care of fetching the capabilities. –>
<!–
<script type="text/javascript" src="http://demo.opengeo.org/geoserver/pdf/info.json?var=printCapabilities"></script>
–>
<script type="text/javascript" src="http://localhost:8080/geoserver/pdf/info.json?var=printCapabilities"></script>

</head>

<body>
</body>
</html>
[/html]

このHTMLの

<script type="text/javascript" src="http://localhost:8080/geoserver/pdf/info.json?var=printCapabilities"></script>

で、localhostにinstallしたGeoServerのpdfを使うようにします。

次に、SimplePrint.jsです。
表示するMap dataはMapServerのWMSを利用します。

[javascript]
Ext.onReady(function() {
Ext.QuickTips.init();

// The printProvider that connects us to the print service
var printProvider = new GeoExt.data.PrintProvider({
method : "GET", // "POST" recommended for production use
capabilities : printCapabilities, // from the info.json script
// in the html
customParams : {
mapTitle : "Printing Demo",
comment : "This is a simple map printed from GeoExt."
}
});

// Tells the PrintProvider about the scale and center of our page.
printPage = new GeoExt.data.PrintPage({
printProvider : printProvider
});

// mapの作成
var map = new OpenLayers.Map({});

// Base Layer
var prefLayer = new OpenLayers.Layer.WMS("神奈川県",
"http://localhost/cgi-bin/mapserv.exe", {
map : "c:/ms4w/Apache/htdocs/mapserver/example/kanagawa_wms.map",
layers : "kanagawa",
format : "image/png",
transparent : true
}, {
buffer : 0,
isBaseLayer : true,
// exclude this layer from layer container nodes
displayInLayerSwitcher : false
});

//
var regionLayer = new OpenLayers.Layer.WMS("市区町村界",
"http://localhost/cgi-bin/mapserv.exe", {
map : "c:/ms4w/Apache/htdocs/mapserver/example/kanagawa_wms.map",
layers : "region",
format : "image/png",
transparent : true
}, {
buffer : 0,
isBaseLayer : false
// true
});

var roadLayer = new OpenLayers.Layer.WMS("主要道路",
"http://localhost/cgi-bin/mapserv.exe", {
map : "c:/ms4w/Apache/htdocs/mapserver/example/kanagawa_wms.map",
layers : "road",
format : "image/png",
transparent : true
}, {
buffer : 0,
isBaseLayer : false
});

// layerの追加
map.addLayers([prefLayer, regionLayer, roadLayer]);

// map center
var lonlat = new OpenLayers.LonLat(139.35, 35.40);
map.setCenter(lonlat, 10);

// controlの追加
map.addControl(new OpenLayers.Control.ScaleLine());
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.addControl(new OpenLayers.Control.MousePosition());

// the map panel
// centerPanel
var mapPanel = new GeoExt.MapPanel({
title : ‘GeoExt Simple Print’,
border : true,
region : "center",
layers : [prefLayer, regionLayer, roadLayer],
zoom : 10,
map : map
});

// the viewport
new Ext.Viewport({
layout : "fit",
hideBorders : true,
items : {
layout : "border",
deferredRender : false,
items : [mapPanel],
bbar : ["->", {
text : "Print",
handler : function() {
// convenient way to fit the print page to the
// visible map area
printPage.fit(mapPanel, true);
// print the page
printProvider.print(mapPanel, printPage);
}
}]
}
});
});
[/javascript]

このjs codeは簡単な説明を

  • printProviderの作成 info.jsonからcapabilities : printCapabilitiesを取得
  • printProviderからprintPageを作成
  • mapを作成して、Layerを定義(神奈川県の市町村界と道路)
  • mapPanelを作成
  • toolbar bottomにprintメニューを作成
  • print button click時のhandler : function(){…}を作成
  • Viewportを作成して、browserに表示

Ext.onReady(function(){….}はExtJSのお約束です。
このExtJSについては、各人でお勉強しといてくださいね。

FireFoxで実行しすると、
blog.godo-tys.jp_wp-content_gallery_geoext_12_image01.jpg

な感じで神奈川県全域が表示されます。

次に、toolbar bottomのprint buttonをclickすると、
blog.godo-tys.jp_wp-content_gallery_geoext_12_image02.jpg

な感じで、PDFに出力確認のDialogが表示されます。

PDFを保存後、PDF Viewで見ると
blog.godo-tys.jp_wp-content_gallery_geoext_12_image03.jpg

な感じで印刷ができています。

とりあえずは、PDF Fileへの出力は確認できました。

PrintPreview form

次に、印刷時のPreview windowを表示してみましょう。
htmlとjsに分けて記述していきます。
まずは、htmlファイルです。
ファイ名は、SimplePrint.html

[html]
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>Printing ux PrintPreview Example</title>

<script type="text/javascript" src="ext-3.4.1/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-3.4.1/ext-all.js"></script>
<link rel="stylesheet" type="text/css" href="ext-3.4.1/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="ext-3.4.1/examples/shared/examples.css" />
<script src="OpenLayers/OpenLayers.js"></script>
<script type="text/javascript" src="GeoExt/lib/GeoExt.js"></script>

<!– script and css resources for this ux –>
<script type="text/javascript" src="lib/GeoExt.ux/PrintPreview.js"></script>
<link rel="stylesheet" type="text/css" href="resources/css/printpreview.css" />
<!– –>

<script type="text/javascript" src="PrintPreviewForm.js"></script>

<script type="text/javascript" src="http://localhost:8080/geoserver/pdf/info.json?var=printCapabilities"></script>

</head>
<body>
<h1>PrintPreview using GeoExt.data.PrintProvider</h1>

<p>
This example shows how to use GeoExt.data.PrintProvider to talk
to the <a href="http://trac.mapfish.org/trac/mapfish/wiki/PrintModuleInstallation">Mapfish print module</a>,
which also runs inside the
<a href="http://docs.geoserver.org/stable/en/user/community/printing/">GeoServer printing module</a>.
</p>

<p>
Use the "Print" button from the bottom toolbar of the map to open
the print dialog.
</p>

<p>
Note that this example uses GET requests to communicate with the
print servlet (provided by the OpenGeo demo server). This saves us a
proxy, but has limitations (URL length in Internet Explorer, and
character encoding issues). For production use, the POST method is
recommended.
</p>

<p>
See <a href="PrintPreview.js">PrintPreview.js</a> for the source code.
</p>

<div id="content"></div>
</body>
</html>
[/html]

このHTMLの

<!-- script and css resources for this ux -->
<script type="text/javascript" src="lib/GeoExt.ux/PrintPreview.js"></script>
<link rel="stylesheet" type="text/css" href="resources/css/printpreview.css" />
<!-- -->

で、PrintPreview formを作成するためのJavaScriptとcssです。
PrintPreview.jsを見てみると、

[javascript]
/**
* Copyright (c) 2008-2009 The Open Source Geospatial Foundation
*
* Published under the BSD license.
* See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
* of the license.
*/
Ext.namespace("GeoExt.ux");

/** api: (define)
* module = GeoExt.ux
* class = PrintPreview
* base_link = `Ext.Container <http://dev.sencha.com/deploy/dev/docs/?class=Ext.Container>`_
*/

/** api: constructor
* .. class:: PrintPreview
*
* A print preview with an interactive map. Requires a server-side print
* module configuration with two custom fields (by default “mapTitle“ and
* “comment“).
*/
GeoExt.ux.PrintPreview = Ext.extend(Ext.Container, {

/* begin i18n */
/** api: config[paperSizeText] “String“ i18n */
paperSizeText: "Paper size:",
/** api: config[resolutionText] “String“ i18n */
resolutionText: "Resolution:",
/** api: config[printText] “String“ i18n */
printText: "Print",
/** api: config[emptyTitleText] “String“ i18n */
emptyTitleText: "Enter map title here.",
/** api: config[includeLegendText] “String“ i18n */
includeLegendText: "Include legend?",
/** api: config[emptyCommentText] “String“ i18n */
emptyCommentText: "Enter comments here.",
/** api: config[creatingPdfText] “String“ i18n */
creatingPdfText: "Creating PDF…",
/* end i18n */

/** api: config[printProvider]
* :class:`GeoExt.data.PrintProvider`|“Object“ Instance or
* configuration for the PrintProvider that this dialog will use. Not
* required if provided with the
* :ref:`GeoExt.ux.PrintPreview.printMapPanel`.
*/

/** private: property[printProvider]
* :class:`GeoExt.data.PrintProvider`
*/
printProvider: null,

/** api: config[sourceMap]
* :class:`GeoExt.MapPanel`|“OpenLayers.Map“ The map to copy layers and
* extent from for printing. Not required if provided with the
* :ref:`GeoExt.ux.PrintPreview.printMapPanel`.
*/

/** private: property[sourceMap]
* “OpenLayers.Map“ The map to copy layers and extent from for printing.
*/
sourceMap: null,

/** api: config[printMapPanel]
* :class:`GeoExt.PrintMapPanel`:“Object“ Optional. Useful e.g.
* for adding a ZoomSlider (via “items“) or setting map options (like
* configuring custom controls or filtering out unsupported layers with
* a preaddlayer listener via “map“).
*
* .. note:: If provided as :class:`GeoExt.PrintMapPanel`, this has to be
* configured with “printProvider“ and “sourceMap“.
*/

/** api: property[printMapPanel]
* class:`GeoExt.PrintMapPanel` The print preview map. Read-only.
*/
printMapPanel: null,

/** api: config[mapTitleField]
* “String“ The custom field of the print service for the map title
*/
mapTitleField: "mapTitle",

/** api: config[commentField]
* “String“ The custom field of the print service for the comment
*/
commentField: "comment",

/** api: config[legend]
* ref:`GeoExt.LegendPanel` The legend to include. If not provided, the
* dialog won’t have an option to include the legend.
*/
legend: null,

/** api: config[includeLegend]
* “Boolean“ Initial status of the "Include legend?" checkbox. Will be
* ignored if :ref:`GeoExt.ux.PrintPreview.legend` is not provided.
*/
includeLegend: false,

/** api: config[mapTitle]
* “String“ An optional title to set for the mapTitle field when
* creating the dialog.
*/
mapTitle: null,

/** api: config[comment]
* “String“ An optional comment to set for the comment field when
* creating the dialog.
*/
comment: null,

/** api: config[addMapOverlay]
* “Boolean“ Set to false if no map overlay with scale, scale selector
* and north arrow should be added. Default is true.
*/
addMapOverlay: true,

/** api: config[busyMask]
* “Ext.LoadMask“ A LoadMask to use while the print document is
* prepared. Optional, will be auto-created with “creatingPdfText` if
* not provided.
*/

/** private: property[busyMask]
* “Ext.LoadMask“
*/
busyMask: null,

/** private: property[form]
* “Ext.form.FormPanel“ The form for this dialog.
*/
form: null,

/** private: property[autoEl]
* override
*/
autoEl: "center",

/** private: property[cls]
* override
*/
cls: "x-panel-body x-panel-body-noheader",

/** private: method[initComponent]
*/
initComponent: function() {
var printMapPanelOptions = {
sourceMap: this.sourceMap,
printProvider: this.printProvider
};
if(this.printMapPanel) {
if(!(this.printMapPanel instanceof GeoExt.PrintMapPanel)) {
printMapPanelOptions.xtype = "gx_printmappanel";
this.printMapPanel = new GeoExt.PrintMapPanel(
Ext.applyIf(this.printMapPanel, printMapPanelOptions));
}
} else {
this.printMapPanel = new GeoExt.PrintMapPanel(
printMapPanelOptions);
}
this.sourceMap = this.printMapPanel.sourceMap;
this.printProvider = this.printMapPanel.printProvider;

this.form = this.createForm();

if (!this.items) {
this.items = [];
}
this.items.push(this.createToolbar(), {
xtype: "container",
cls: "gx-printpreview",
autoHeight: this.autoHeight,
autoWidth: this.autoWidth,
items: [
this.form,
this.printMapPanel
]
});

GeoExt.ux.PrintPreview.superclass.initComponent.call(this);

this.addMapOverlay && this.printMapPanel.add(this.createMapOverlay());

this.printMapPanel.on({
"resize": this.updateSize,
scope: this
});
this.on({
"render": function() {
if (!this.busyMask) {
this.busyMask = new Ext.LoadMask(this.getEl(), {
msg: this.creatingPdfText
});
}
this.printProvider.on({
"beforeprint": this.busyMask.show,
"print": this.busyMask.hide,
"printexception": this.busyMask.hide,
scope: this.busyMask
});
},
scope: this
});
},

/** private: method[createToolbar]
* :return: “Ext.Toolbar“
*/
createToolbar: function() {
var items = [];
this.printProvider.layouts.getCount() > 1 && items.push(this.paperSizeText, {
xtype: "combo",
width: 98,
plugins: new GeoExt.plugins.PrintProviderField({
printProvider: this.printProvider
}),
store: this.printProvider.layouts,
displayField: "name",
typeAhead: true,
mode: "local",
forceSelection: true,
triggerAction: "all",
selectOnFocus: true
}, "&nbsp;");
this.printProvider.dpis.getCount() > 1 && items.push(this.resolutionText, {
xtype: "combo",
width: 62,
plugins: new GeoExt.plugins.PrintProviderField({
printProvider: this.printProvider
}),
store: this.printProvider.dpis,
displayField: "name",
tpl: ‘<tpl for="."><div class="x-combo-list-item">{name} dpi</div></tpl>’,
typeAhead: true,
mode: "local",
forceSelection: true,
triggerAction: "all",
selectOnFocus: true,
setValue: function(v){
v = parseInt(v) + " dpi";
Ext.form.ComboBox.prototype.setValue.apply(this, arguments);
}
}, "&nbsp;");
items.push("->", {
text: this.printText,
iconCls: "icon-print",
handler: function(){
this.printMapPanel.print(this.includeLegend &&
{legend: this.legend});
},
scope: this
});
return {
xtype: "toolbar",
items: items
};
},

/** private: method[createForm]
* :return: “Ext.form.FormPanel“
*/
createForm: function() {
var titleCfg = {
xtype: "textfield",
name: this.mapTitleField,
value: this.mapTitle,
emptyText: this.emptyTitleText,
margins: "0 5 0 0",
flex: 1,
anchor: "100%",
hideLabel: true,
plugins: new GeoExt.plugins.PrintProviderField({
printProvider: this.printProvider
})
};

if(this.legend) {
var legendCheckbox = new Ext.form.Checkbox({
name: "legend",
checked: this.includeLegend,
boxLabel: this.includeLegendText,
hideLabel: true,
ctCls: "gx-item-nowrap",
handler: function(cb, checked) {
this.includeLegend = checked;
},
scope: this
});
}

return new Ext.form.FormPanel({
autoHeight: true,
border: false,
defaults: {
anchor: "100%"
},
items: [
this.legend ? {
xtype: "container",
layout: "hbox",
cls: "x-form-item",
items: [
titleCfg,
legendCheckbox
]
} : titleCfg, {
xtype: "textarea",
name: this.commentField,
value: this.comment,
emptyText: this.emptyCommentText,
hideLabel: true,
plugins: new GeoExt.plugins.PrintProviderField({
printProvider: this.printProvider
})
}
]
});
},

/** private: method[createMapOverlay]
* :return: “Ext.Panel“
*/
createMapOverlay: function() {
var map = this.printMapPanel.map;
var scaleLine = new OpenLayers.Control.ScaleLine({
geodesic: !(map.getProjectionObject() || new OpenLayers.Projection(map.projection || "EPSG:4326")).equals("EPSG:4326")
});
map.addControl(scaleLine);
scaleLine.activate();
return new Ext.Panel({
cls: "gx-map-overlay",
layout: "column",
width: 235,
bodyStyle: "padding:5px",
items: [{
xtype: "box",
el: scaleLine.div,
width: scaleLine.maxWidth
}, {
xtype: "container",
layout: "form",
style: "padding: .2em 5px 0 0;",
columnWidth: 1,
cls: "x-small-editor x-form-item",
items: {
xtype: "combo",
name: "scale",
anchor: "100%",
hideLabel: true,
store: this.printMapPanel.previewScales,
displayField: "name",
typeAhead: true,
mode: "local",
forceSelection: true,
triggerAction: "all",
selectOnFocus: true,
getListParent: function() {
return this.el.up(".x-window") || document.body;
},
plugins: new GeoExt.plugins.PrintPageField({
printPage: this.printMapPanel.printPage
})
}
}, {
xtype: "box",
autoEl: {
tag: "div",
cls: "gx-northarrow"
}
}],
listeners: {
"render": function() {
function stop(evt){evt.stopPropagation();}
this.getEl().on({
"click": stop,
"dblclick": stop,
"mousedown": stop
});
}
}
});
},

/** private: method[updateSize]
* sync the form’s width with the map with, and make sure that the window
* shadow is updated if this dialog is added to an “Ext.Window“
*/
updateSize: function() {
this.suspendEvents();
var mapWidth = this.printMapPanel.getWidth();
// sync form and toolbar width with map width
this.form.setWidth(mapWidth);
// the line with title and legend needs an extra invitation
this.form.items.get(0).setWidth(mapWidth);
var minWidth = this.initialConfig.minWidth || 0;
this.items.get(0).setWidth(
this.form.ownerCt.el.getPadding("lr") + Math.max(mapWidth, minWidth)
);
// shadow does not sync, so do it manually
var parent = this.ownerCt;
if (parent && parent instanceof Ext.Window) {
this.ownerCt.syncShadow();
}
this.resumeEvents();
},

/** private: method[beforeDestroy]
*/
beforeDestroy: function() {
if (this.busyMask) {
this.printProvider.un("beforeprint", this.busyMask.show, this.busyMask);
this.printProvider.un("print", this.busyMask.hide, this.busyMask);
}
this.printMapPanel.un("resize", this.updateSize, this);
GeoExt.ux.PrintPreview.superclass.beforeDestroy.apply(this, arguments);
}

});

/** api: xtype = gxux_printpreview */
Ext.reg("gxux_printpreview", GeoExt.ux.PrintPreview);
[/javascript]

となり、Ext.namespace(“GeoExt.ux”);でGeoExt.uxとして定義し、Ext.reg(“gxux_printpreview”, GeoExt.ux.PrintPreview);で利用できるようになっています。

次に、PrintPreviewForm.jsは

[javascript]
var mapPanel, printMapPanel, legendPanel;
var PrefLayer, regionLayer, roadLayer;

Ext.onReady(function() {

var bounds = new OpenLayers.Bounds(
138.85, 35.03,
139.81, 35.76
);

// Base Layer
prefLayer = new OpenLayers.Layer.WMS("神奈川県",
"http://localhost/cgi-bin/mapserv.exe", {
map : "c:/ms4w/Apache/htdocs/mapserver/example/kanagawa_wms.map",
layers : "kanagawa",
format : "image/png",
transparent : true
}, {
buffer : 0,
isBaseLayer : true,
// exclude this layer from layer container nodes
displayInLayerSwitcher : false
});

//
regionLayer = new OpenLayers.Layer.WMS("市区町村界",
"http://localhost/cgi-bin/mapserv.exe", {
map : "c:/ms4w/Apache/htdocs/mapserver/example/kanagawa_wms.map",
layers : "region",
format : "image/png",
transparent : true
}, {
buffer : 0,
isBaseLayer : false
// true
});

roadLayer = new OpenLayers.Layer.WMS("主要道路",
"http://localhost/cgi-bin/mapserv.exe", {
map : "c:/ms4w/Apache/htdocs/mapserver/example/kanagawa_wms.map",
layers : "road",
format : "image/png",
transparent : true
}, {
buffer : 0,
isBaseLayer : false
});

mapPanel = new GeoExt.MapPanel({
region : "center",
map : {
maxExtent : bounds,
maxResolution : 0.018140625,
projection : "EPSG:4326",
units : ‘degrees’
},
layers : [prefLayer, regionLayer, roadLayer],
extent : bounds,
bbar : [{
text : "Print...",
handler : showPrintWindow
}]
});

legendPanel = new GeoExt.LegendPanel({
width : 150,
region : "west",
defaults : {
style : "padding:5px",
baseParams : {
FORMAT : "image/png"
}
}
});
new Ext.Panel({
layout : "border",
renderTo : "content",
width : 600,
height : 350,
items : [mapPanel, legendPanel]
});
});

function showPrintWindow() {
var printWindow = new Ext.Window({
title : "Print",
modal : true,
border : false,
resizable : false,
width : 360,
autoHeight : true,
items : new GeoExt.ux.PrintPreview({
autoHeight : true,
printMapPanel : {
// limit scales to those that can be previewed
limitScales : true,
// no zooming on the map
map : {
controls : [
new OpenLayers.Control.Navigation({
zoomBoxEnabled : false,
zoomWheelEnabled : false
}),
new OpenLayers.Control.PanPanel()]
}
},
printProvider : {
// using get for remote service access without
// same origin
// restriction. For async requests, we would set
// method to "POST".
method : "GET",
// method: "POST",

// capabilities from script tag in
// Printing.html.
capabilities : printCapabilities,
listeners : {
"print" : function() {
printWindow.close();
}
}
},
includeLegend : true,
mapTitle : "PrintMapPanel Demo",
sourceMap : mapPanel,
legend : legendPanel
})
}).show().center();
}
[/javascript]

このjs codeは簡単な説明を

  • mapを作成して、Layerを定義(神奈川県の市町村界と道路)
  • mapPanelを作成
  • legendPanelを作成
  • toolbar bottomにprintメニューを作成
  • print button click時のhandler : function(){…}を作成
  • showPrintWindow
  • div = 'content'にmapPanelをrender

function showPrintWindow() {…}でprint buttonがclickされた時にpopup windowを表示します。

FireFoxで実行しすると、
blog.godo-tys.jp_wp-content_gallery_geoext_12_image05.jpg

な感じで神奈川県全域と凡例が表示されます。

次に、toolbar bottomのprint buttonをclickすると、
blog.godo-tys.jp_wp-content_gallery_geoext_12_image06.jpg

な感じで、popup windowにmap previewが表示されます。そして、print iconをclickするとPDF Fileに出力されます。

今回のまとめ

GeoExtのprint機能の基本を利用しました。
次回は、Print機能を拡充したり、OpenStreetMapと電子国土の印刷を行ってみます。

GeoExt1.1 Tutorialの目次に戻る。

1 / 11

Social Widgets powered by AB-WebLog.com.