arcgis server jsapi 地图打印:多图层打印(tiled+dynamic地图服务)
来源:互联网 发布:java第二学期考试 编辑:程序博客网 时间:2024/05/06 03:15
最近做个地图print,坐了好久,现在终于解决了。
概要:本地图中包含tiled和dynamic的图层,同时输出打印;
首先:要有esri的代理proxy。这个不多说:直接去arcgis server帮助中心http://help.arcgis.com/zh-CN/webapps/sharepoint/help/index.html#//01590000004w000000查看;
注意的是:proxyconfig文件的配置!!!!
其次:代码结构:
TestPage.htm作为主页面,点击主页中的打印会弹出Layout的打印页面。
printing.js用来获取地图服务的url信息;
MergerAndOutput.ashx是一个用于tiled地图服务的切片融合的类文件,
在printableLayer.js中使用MergerAndOutput.ashx,PrintableLayer.js文件是一个创建Dynamic图层的类,将切片的图层融合后,然后加载到这个新的Dynamic图层中;
代码:
----------------------------------------------
PrintTableLayer.js
dojo.require("esri.utils");
dojo.declare("geoweb2book.PrintableLayer", esri.layers.DynamicMapServiceLayer,
{
constructor: function(url, options)
{
this.layers = options.layers;
this.initialExtent = this.fullExtent = options.extent;
this.spatialReference = this.initialExtent.spatialReference;
this.loaded = true;
this.onLoad(this);
},
//call mergeAndOutput.*, pass request JSON.
//process response JSON and return image url
getImageUrl: function(extent, width, height, callback)
{
try
{
var layersJson = [], layerJson;
dojo.forEach(this.layers, function(layer)
{
if (layer.visible)
{
layerJson = { url: layer.url, format: (layersJson.length == 0 ? "jpg" : "png"), opacity: layer.opacity};
if (layer.layers)
{
layerJson.layers = "show:" + layer.layers.join(",");
}
if (layer.layerDefs)
{
var defs = [];
dojo.forEach(layer.layerDefs, function(def, index)
{
if (def)
{
defs.push(index + ":" + def);
}
});
layerJson.layerDefs = defs.join(";");
}
layersJson.push(dojo.toJson(layerJson));
}
});
// JSON格式的请求
var json =
{
"width": width,
"height": height,
"extent": dojo.toJson(extent.toJson()),
"layers": layersJson
};
// 将请求发送到MergeAndOutput.ashx
var request=esri.request
({
url: this.url,
content: json,
handleAs: "json",
load: function(response, io)
{
// 当得到服务器的响应后,调用callback,并传递图像URL
callback(response.href);
},
error: this.onError
});
}
catch (err)
{
this.onError(err);
}
}
});
----------------------------------------------
printing.js
dojo.require("esri.map");
dojo.require("dojo.parser");
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");
//serialize the map's state and call layout.* through iframe
function printMap(m) {
var state = {
map: getMapState(m)
};
var printUrl="Layout.aspx?param="+dojo.toJson(state);;
window.open(printUrl);
}
function getMapState(m) {
var layerStates = [], graphicsState = [], graphics = m.graphics.graphics;
//serialize each layer's state
dojo.forEach(m.layerIds, function(layerId) {
layerStates.push(getLayerState(m.getLayer(layerId)));
});
//serialize graphics from last to first to retain graphics drawing order
for (var i = graphics.length - 1; i >= 0; i--) {
graphicsState.push(graphics[i].toJson());
};
return {
extent: m.extent.toJson(),
layers: layerStates,
graphics: graphicsState
};
}
function getLayerState(layer) {
return {
id: layer.id,
type: layer.declaredClass,
url: layer.url,
visible: layer.visible,
opacity: layer.opacity,
layerDefs: layer.layerDefinitions,
layers: layer.visibleLayers
};
}
----------------------------------------------
MergeAndOutput.ashx
<%@ WebHandler Language="C#" Class="MergeAndOutput" %>
using System;
using System.Web;
using System.Text;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web.Extensions;
public class MergeAndOutput : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
context.Response.ContentEncoding = Encoding.UTF8;
// 得到输入JSON字符串
//byte[] bytes = new byte[context.Request.InputStream.Length];
//context.Request.InputStream.Read(bytes, 0, (int)context.Request.InputStream.Length);
//string inputJson = ASCIIEncoding.ASCII.GetString(bytes);
string inputJson = HttpUtility.UrlDecode(context.Request.Url.Query);
inputJson = inputJson.Substring(1, inputJson.Length - 1);
//inputJson = inputJson.Replace("&", ",");
//inputJson = inputJson.Replace("=", ":");
//inputJson = "{" + inputJson + "}";
// 将输入JSON转换为泛型词典对象
//Dictionary<string, object> dict = new Dictionary<string, object>();
//dict = ReadJsonInput(inputJson);
// 调用Blend方法融合图像
string filename = Blend(inputJson);
// 调用ConstructOutputJson构造输出JSON字符串
string result = ConstructOutputJson(inputJson, filename);
context.Response.Output.Write(result);
}
public bool IsReusable
{
get
{
return false;
}
}
/// <summary>
/// Read JSON input to get map information.
/// </summary>
/// <param name="inputJson"></param>
/// <returns></returns>
//private Dictionary<string, object> ReadJsonInput(string inputJson)
//{
// Dictionary<string, object> dict = new Dictionary<string, object>();
// JavaScriptSerializer jss = new JavaScriptSerializer();
// object obj = jss.DeserializeObject(inputJson);
// dict = (Dictionary<string, object>)obj;
// return dict;
//}
/// <summary>
/// Contruct output JSON.
/// </summary>
/// <param name="dict"></param>
/// <param name="filename"></param>
/// <returns></returns>
private string ConstructOutputJson(string inputJson, string filename)
{
//Get values persisted from the input JSON.
char[] sep = { '&', '=' };
string[] inputArr = inputJson.Split(sep);
string width = inputArr[1];
string height = inputArr[3];
string extent = inputArr[5];
StringBuilder sb = new StringBuilder();
sb.Append("{");
sb.Append("'width':" + width + ",");
sb.Append("'height':" + height + ",");
sb.Append("'extent':" + extent + ",");
sb.Append("'href':'" + System.Configuration.ConfigurationManager.AppSettings["OutputUrl"] + filename + ".jpg'}");
return sb.ToString();
}
/// <summary>
/// Construct image URl to be passed to the Blend method.
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="extent"></param>
/// <param name="objLayers"></param>
/// <param name="transparency"></param>
/// <returns></returns>
private string ConstructImageURL(string width, string height, string extent, object objLayers)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
StringBuilder sb = new StringBuilder();
string opacity = string.Empty;
//Store extent values in dictionary object.
Dictionary<string, object> dictExtent = new Dictionary<string, object>();
object objExtent = jss.DeserializeObject(extent);
dictExtent = (Dictionary<string, object>)objExtent;
//Store layer information in dictionary object;
Dictionary<string, object> dictLayer = new Dictionary<string, object>();
dictLayer = (Dictionary<string, object>)objLayers;
//Construct the image URL.
sb.Append(dictLayer["url"].ToString());
sb.Append("/export?f=image&bbox=");
//sb.Append(dictExtent["xmin"].ToString() + "," + dictExtent["ymin"].ToString() + "," + dictExtent["xmax"].ToString() + "," + dictExtent["ymax"].ToString());
sb.Append(ConvertToString(dictExtent["xmin"]) + "," + ConvertToString(dictExtent["ymin"]) + "," + ConvertToString(dictExtent["xmax"]) + "," + ConvertToString(dictExtent["ymax"]));
sb.Append("&size=" + width + "," + height);
sb.Append("&transparent=true");
sb.Append("&format=" + dictLayer["format"].ToString());
sb.Append("&layers=" + dictLayer["layers"].ToString());
sb.Append("&layerDefs=" + ((!dictLayer.ContainsKey("layerDefs")) ? "" : HttpUtility.UrlEncode(dictLayer["layerDefs"].ToString())));
return sb.ToString();
}
private string ConvertToString(object strObj)
{
string strStr = strObj.ToString();
if (strStr.Contains(","))
{
return strStr.Replace(',', '.');
}
return strStr;
}
/// <summary>
/// Create list of layer transparencies.
/// </summary>
/// <param name="objLayers"></param>
/// <returns></returns>
private List<double> GetTransparency(List<object> objLayers)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
List<double> lt = new List<double>();
string opacity = string.Empty;
//object objLayer = null;
//Create list of layer transparencies.
Dictionary<string, object> dictLayer = new Dictionary<string, object>();
for (int i = 0; i < objLayers.Count; i++)
{
//objLayer = jss.DeserializeObject(objLayers[i].ToString());
dictLayer = (Dictionary<string, object>)objLayers[i];
opacity = dictLayer["opacity"].ToString();
lt.Add(1 - (Convert.ToDouble(opacity)));
}
return lt;
}
#region Blend Methods
/// <summary>
/// Method to blend images.Dictionary<string, object> dict
/// </summary>
/// <param name="dict"></param>
/// <returns></returns>
private string Blend(string inputJson)
{
List<double> listTransparency = new List<double>();
int count = 0;
int layerIndex = -1;
Bitmap tempimg = null;
Bitmap baseimg = null;
Bitmap topimg = null;
string filename = string.Empty;
string output = string.Empty;
// 从JSON字符串中得到各种参数的值
char[] sep={'&','='};
string[] inputArr = inputJson.Split(sep);
string width =inputArr[1];
string height=inputArr[3];
string extent = inputArr[5];
List<object> objLayers =new List<object>();
for(int i=7;i<inputArr.Length;i=i+2)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
object obj = jss.DeserializeObject(inputArr[i]);
objLayers.Add(obj);
}
count = objLayers.Count;
// 得到地图中各图层对应的地图图像URL
List<string> urlList = new List<string>();
for (int i = 0; i < count; i++)
{
urlList.Add(ConstructImageURL(width, height, extent, objLayers[i]));
}
// 得到图层的透明度
listTransparency = GetTransparency(objLayers);
// 创建一白色背景的图像
Bitmap whiteImage = new Bitmap(Convert.ToInt32(width), Convert.ToInt32(height));
Graphics objGraphics = Graphics.FromImage(whiteImage);
objGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, Convert.ToInt32(width), Convert.ToInt32(height));
baseimg = whiteImage;
count = count + 1;
while (count > 1)
{
topimg = Converter.ToImage(urlList[layerIndex + 1].ToString());
// 设置输出文件名
if (count == 2)
{
output = System.Configuration.ConfigurationManager.AppSettings["OutputPath"];
filename = "export_" + Guid.NewGuid().ToString("N");
output = output + filename + ".jpg";
}
// 融合图像
tempimg = Blend(baseimg, topimg, listTransparency[layerIndex + 1], output, Convert.ToInt32(width), Convert.ToInt32(height));
baseimg = tempimg;
count--;
layerIndex++;
}
// 释放资源
baseimg.Dispose();
baseimg = null;
topimg.Dispose();
topimg = null;
tempimg.Dispose();
tempimg = null;
return filename;
}
/// <summary>
/// Blend images using transparency.
/// </summary>
/// <param name="baseimg"></param>
/// <param name="topimg"></param>
/// <param name="transparency"></param>
/// <param name="output"></param>
/// <param name="width"></param>
/// <param name="height"></param>
private Bitmap Blend(Bitmap baseimg, Bitmap topimg, double transparency, string output, int width, int height)
{
//output image
Bitmap newimg = new Bitmap(width, height);
//get graphics of output image, and set size of image
System.Drawing.Graphics imgGraphics = System.Drawing.Graphics.FromImage(newimg);
//draw base image
imgGraphics.DrawImage(baseimg, 0, 0,
baseimg.Width, baseimg.Height);
BlendNoSave(imgGraphics, topimg, transparency);
//release resources
// this will enable writing new image to the location of one of the component images
baseimg.Dispose();
baseimg = null;
topimg.Dispose();
topimg = null;
//save out image and release resources
if (!string.IsNullOrEmpty(output))
{
newimg.Save(output, System.Drawing.Imaging.ImageFormat.Jpeg);
}
return newimg;
}
/// <summary>
/// Blends an image into a graphics object.
/// </summary>
/// <param name="baseGraphics">Graphics reference.</param>
/// <param name="topimg">Image to blend on top.</param>
/// <param name="transparency">Transparency from 0 (transparent) to 1 (opaque).</param>
public static void BlendNoSave(System.Drawing.Graphics baseGraphics, Bitmap topimg, double transparency)
{
if (transparency > 1 || transparency < 0)
{
string error = "Invalid transparency value.";
throw new ArgumentOutOfRangeException(error);
}
else if (transparency > 0)
{
ImageAttributes imgAttributes = new ImageAttributes();
//matrix to use for alpha-blending (to achieve transparency)
float[][] ptsArray ={
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 1-(float)transparency, 0},
new float[] {0, 0, 0, 0, 1}};
ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
//Draw top image using matrix to apply transparency
imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
baseGraphics.DrawImage(topimg, new Rectangle(0, 0, topimg.Width, topimg.Height), 0, 0, topimg.Width, topimg.Height, GraphicsUnit.Pixel, imgAttributes);
}
else
{
baseGraphics.DrawImage(topimg, new Rectangle(0, 0, topimg.Width, topimg.Height), 0, 0, topimg.Width, topimg.Height, GraphicsUnit.Pixel);
}
return;
}
#endregion
}
----------------------------------
TestPage中的代码:
<head>
<title>地图打印</title>
<style type="text/css">
@import "http://serverapi.arcgisonline.com/jsapi/arcgis/2.6/js/dojo/dijit/themes/tundra/tundra.css";
@import "css/RestLegends.css";
html, body, #main{
width: 100%;
height: 100%;
}
</style>
<script type="text/javascript">
djConfig = { parseOnLoad: true ,url:"服务器IP"};
</script>
<script type="text/javascript" src="http://服务器IP/jsapi/library/2.6/jsapi"></script>
<script type="text/javascript" src="js/printing.js">
</script>
<script type="text/javascript">
//variable to store hidden frame
var printingHiddenFrame;
var map1;
function init() {
map1 = new esri.Map("map", {
extent: new esri.geometry.Extent({"xmin":496369
,"ymin":299413
,"xmax":504735
,"ymax":312319
,"spatialReference":{"wkid":32601} } )
});
var tiled = new esri.layers.ArcGISTiledMapServiceLayer("http://服务器IP/ArcGIS/rest/services/baseMap/MapServer");
map1.addLayer(tiled);
var dyna=new esri.layers.ArcGISDynamicMapServiceLayer("http://服务器IP/ArcGIS/rest/services/YXX/MapServer");
map1.addLayer(dyna);
var dyna1=new esri.layers.ArcGISDynamicMapServiceLayer("http://服务器IP/ArcGIS/rest/services/PB/MapServer");
map1.addLayer(dyna1);
}
dojo.addOnLoad(init);
function print()
{
var _divWidth = document.getElementById("map").style.width;
var _divHeight =document.getElementById("map").style.height;
var divWidth = _divWidth.substring(0,_divWidth.length-2);
var divHeight = _divHeight.substring(0,_divHeight.length-2);
//alert(divWidth);
var realWidth = parseInt(divWidth);
var realHeight = parseInt(divHeight);
// document.getElementById("map").style.position.s
}
</script>
</head>
<body class="tundra">
<div id="main">
<div style="height: 60px;">
<h3>功能:地图打印</h3>
</div>
<div id="map" ></div>
<div
style="height: 50px;" splitter="true">
<button onclick="printMap(map1);"><img src="images/print.gif" />打印</button>
</div>
</div>
</body>
</html>
=----------------------------------------------------------
Layout文件代码:
<title>地图打印</title>
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.6/js/dojo/dijit/themes/tundra/tundra.css" />
<script type="text/javascript">
djConfig = { parseOnLoad: true ,url:"服务器IP"};
</script>
<script type="text/javascript" src="http://服务器IP/jsapi/library/2.6/jsapi"></script>
<script type="text/javascript" src="js/PrintableLayer.js"></script>
<script type="text/javascript" charset="utf-8">
var mapParam=getParam();
mapParam=dojo.fromJson(mapParam);
var resizeTimer;
function getParam()
{
var obj_ArrParam = new Array();
var str_CurrentUrl = document.URL;
var obj_RequestUrl = str_CurrentUrl.split('?');
var obl_Param = obj_RequestUrl[1].split('=');
return obl_Param[1];
}
dojo.require("esri.map");
// var jsonStr = <%=Request.Params.Get("appState")%>;
var appState = mapParam;
var map;
function init()
{
map = new esri.Map("mapDiv", {
extent: new esri.geometry.Extent(appState.map.extent),
showInfoWindowOnClick: false,
slider: false
});
//on load, add graphics to map
dojo.connect(map, "onLoad", addGraphicsToMap);
esri.config.defaults.io.proxyUrl = "proxy.ashx";
esriConfig.defaults.io.alwaysUseProxy = false;
var layer = new geoweb2book.PrintableLayer("http://服务器IP/Sample3-9/MergeAndOutput.ashx",
{
layers:appState.map.layers,
extent: new esri.geometry.Extent(appState.map.extent)
});
dojo.connect(layer, "onError", errorHandler);
map.addLayer(layer);
map.disableDoubleClickZoom();
map.disableKeyboardNavigation();
map.disableMapNavigation();
map.disablePan();
map.disableScrollWheelZoom();
dojo.connect(window, 'onresize', function() {
//当浏览器变化的时候div也会变化,这样把地图控件重绘
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
map.resize();
map.reposition();
}, 500);
});
}
function errorHandler(err)
{
alert(err);
}
//deserialize graphics and add to map
function addGraphicsToMap()
{
dojo.forEach(appState.map.graphics, function(graphic)
{
map.graphics.add(new esri.Graphic(graphic));
});
}
function printPage()
{
try
{
//ie中打印默认打印页眉页脚,这里做一下处理,只打印地图部分。
var hkey_root,hkey_path,hkey_key;
hkey_root="HKEY_CURRENT_USER";
hkey_path="\\Software\\Microsoft\\Internet Explorer\\PageSetup\\";
RegWsh = new ActiveXObject("WScript.Shell");
hkey_key="header";
RegWsh.RegWrite(hkey_root+hkey_path+hkey_key,"");
hkey_key="footer";
RegWsh.RegWrite(hkey_root+hkey_path+hkey_key,"");
}
catch(e)
{alert ("页面设置失败,请手动设置!");}
var bdhtml=window.document.body.innerHTML;
var sprnstr = "<!--startprint-->";
var eprnstr = "<!--endprint-->";
var frontprnhtml=bdhtml.substring(bdhtml.indexOf(sprnstr)+17);
var laterprnhtml=frontprnhtml.substring(0,frontprnhtml.indexOf(eprnstr));
window.document.body.innerHTML=laterprnhtml;
window.print();
}
dojo.addOnLoad(init);
</script>
<style type="text/css">
#btn
{
width: 65px;
}
</style>
</head>
<body style="text-align:center; margin-left:auto; margin-right:auto;position:relative">
<!--startprint-->
<div id="div_print" >
<h2>地图打印</h2>
<div id="mapDiv" style="width: 1000px; height: 1000px; border: 1px solid #000; text-align:center; margin-left:auto; margin-right:auto;position:relative;">
</div>
</div>
<!--endprint-->
<input name="button" type="button" id="btn" onclick = "printPage();" value="打印地图" />
</body>
</html>
----------------------------------------------------------
另外在website的webconfig中ps两句话:
<add key="OutputPath" value="C:\Inetpub\wwwroot\Sample3-9\output\"/>
<add key="OutputUrl" value="http://服务器IP/Sample3-9/output/"/>
整个Demo的结构就是这样的。希望对大家有用;
参考文献:ArcGIS Server JavaScript API开发GeoWeb 2.0应用/刘光
arcgis server javascript api (arcgis resource center)
js+c#相关教程
ArcGIS Server JavaScript API开发GeoWeb 2.0应用/刘光
ArcGIS Server JavaScript API开发GeoWeb 2.0应用/刘光
ArcGIS Server JavaScript API开发GeoWeb 2.0应用/刘光
ArcGIS Server JavaScript API开发GeoWeb 2.0应用/刘光
- arcgis server jsapi 地图打印:多图层打印(tiled+dynamic地图服务)
- Tiled ArcGIS MapServer——ArcGIS瓦片地图服务
- arcgis api for js入门开发系列十二地图打印(GP服务)
- ArcGIS API For Javascript GP工具 Printing Tools导出地图或者打印地图(一):GP 服务Printing Tools
- ArcGIS API For Javascript GP工具 Printing Tools导出地图或者打印地图(二):GP 服务Printing Tools
- ArcGIS Server 地图服务叠加
- ArcGIS Server 发布地图服务
- ArcGIS Server发布地图服务
- arcgis server 9.3 jsapi 不能显示地图解决方案
- web端输出打印地图(ArcGIS api for Javascript)一、地图打印模板的制作
- 发布地图打印服务注意事项
- ArcGIS Server 10.2 打印服务
- 地图打印
- ArcGIS教程:打印和导出时态地图
- ArcGIS Server 地图服务无法预览(转)
- (一)ArcGIS Server之发布动态地图服务
- (二)ArcGIS Server之发布切片地图服务
- (七)ArcGIS Server之发布结果地图服务
- 你点燃了我的思念,你残留了我的温柔
- 亚马逊与苹果模式无法复制
- App Store开人民币付款先河 苹果中国本土化路上问题多
- 第一次安装android sdk后进行开发包的更新,你应该了解到需要的时间会很长,那么是否有办法提升安装的进度呢?办法自然是有的,这里提供一个取巧的方法,不会太麻烦,又能加快android开发环境的部
- 子衿的事(66)
- arcgis server jsapi 地图打印:多图层打印(tiled+dynamic地图服务)
- 小米手机的世界梦想
- 软件架构的5种视图
- 追赶者——微软
- STL-set用法
- 我为什么离开Facebook
- UVa 11000 简单递推
- 这个世界有病,我们都有病
- STL--map用法