webgis--arcgis2D与cesium3D

1.arcgis picture-marker-symbol 和 cesium entity-billboard。这2者常用于地图上进行图片标注。

arcgis_js_api (4.x,下同)中picture-mark-symbol 的图片支持gif动画。但cesium entity-billboard 却不支持,它加载的gif只能显示第一帧。问题就是为什么cesium不支持gif动画?能否让cesium的billboard支持gif动画呢?

原因:arcgis_js_api中,虽然有一部分是跟cesium一样用canvas 来渲染,但canvas并不是唯一用来展示的元素,他还把很多要显示 的要素放在了跟canvas同一层的div中.比如将同一个图层的很多picture-marker 放在某个div下的同一个svg里面,你是可以在html里面找到这个图片对应的svg节点的。也就是说,picure-marker 中的图片是放svg里面的,而svg是支持gif动画的。而cesium不同,cesium的所有渲染是基于canvas的,也就是说地图上的所有东西都是是canvas上绘制的,你并不能在canvas节点下面找到任何东西。而canvas是不支持gif动画的。之前在网上找资料说通过canvas的content2d,在定时器中不断的绘制引用gif图片 的img可以实现在canvas里面播放gif,经过测试,这个方法是行不通的。

解决办法:理论上可以通过解析gif的每帧然后绘制到一个canvas上,再把这个canvas设置成billboard的image。而cesium中的billoard这个类(注意不是billboardGraphic,后面经过测试,这个类中的image同样一旦设置成某个canvas后,通过更新canvas的内容是无效的。如果重新设置过一个新的canvas呢?2018.5.28更新。)恰恰也提供了setimage(id,image)这个方法.其中第二个参数image可以是image或者是canvas。经过测试,发现一个新问题,那就是一旦调用了setImage 这个方法传进去的image或者canvas就不能在外部被修改了,具体原因待查。所以通过setimage动态设置image就行不通了。

2.arcgis text-symbol 和cesium entity-label。这两者常用于地图上进行文字标注。

arcgis_js_api 中的text-symbol 里面 的text在mapview中不支持换行(4.7虽然说支持多行文本,但并没有看到对应的例子,而阅读了对应的源码后发现确实不行)mapview中不支持backgroundcolor,还有很多三维地图里面的功能在二维里面是不支持的。而cesium中的label却支持换行,支持backgroundColor。问题就是能否让text-symbol 支持换行呢?

解决办法:答案是肯定的,在arcgis_js_api 3.x里面有对应的方法,通过继承text-symbol 然后重载setShape函数,但在4.x中, 继承text-symbol 这种方法已经行不通了,4.x中的symbol只是一个简单的标注对象或者说一个简单变量--用来存储symbol的值,并不参与任何的渲染行为。text的颜色,字体大小都在mapview中进行解释渲染,所以要改的代码在mapview里面。打开esri->views->mapview.js。查找定位到“esri/views/2d/libs/gfx/Text”。然后在定位到下面的setShape函数,就可以看到textsymbol的解析渲染了。下面直接附上代码。这里使用的api为V4.7。

	d.prototype.setShape =
					function (a) {
						var bgc = a.backgroundColor;
						this.shape = e.makeParameters(this.shape, a);
						this.bbox = null;
						a = this.rawNode;
						var b = this.shape;
						a.setAttribute("x", b.x);
						a.setAttribute("y", b.y);
						a.setAttribute("text-anchor", b.align);
						a.setAttribute("text-decoration", b.decoration);
						a.setAttribute("rotate", b.rotated ? 90 : 0);
						a.setAttribute("kerning", b.kerning ? "auto" : 0);
						a.setAttribute("text-rendering", k);
					
						//a.firstChild ? a.firstChild.nodeValue = b.text : a.appendChild(c._createTextNode(b.text));
						//支持换行
						debugger
						while(a.firstChild)
							a.removeChild(a.firstChild);
						b.text+="";//
						var maxWidth= 0;
						if(b.text)
						{
							var tStr = b.text.replace(/<br\s*\/?>/ig, "/n");
							var texts= tStr.split("/n");
							var s = document.defaultView.getComputedStyle(a, "");
							var h = s.getPropertyValue("font-size");
							var lineHeight = 1.1 * parseInt(h, 10);
							if( isNaN(lineHeight) || !isFinite(lineHeight) )
								lineHeight = 15;

							for(var i = 0, n = texts.length; i < n; i++)
							{
								var tspan = (document.createElementNS ? document.createElementNS(c.xmlns.svg, "tspan") : document.createElement("tspan"));
								tspan.setAttribute("dy", i ? lineHeight : -(texts.length-1)*lineHeight/2);
								tspan.setAttribute("x", b.x);
								tspan.appendChild(c._createTextNode(texts[i]));
								a.appendChild(tspan);
								var width = texts[i].length*lineHeight;
								maxWidth = maxWidth>width?maxWidth:width;
							}
						}
						return this
}

3.textSymbol在mapview中不支持haloColor的解决办法:因为mapview中的text最终是以svg.text的形式存在的,所以只要在svg的text中设置相应的属性即可。在mapview 中定位到代码“if ("text" === w.type)”(这边的API为arcgis_js 4.8)在适当的位置加入设置haloColor属性即可,详细见代码

if ("text" === w.type) {
						if (m = w.font && w.font.clone())
							m.size = v ? A : k.pt2px(m.size);
						G = x(e, f, {
								type: "text",
								text: w.text,
								x: a,
								y: c,
								align: g.getSVGAlign(w),
								decoration: w.decoration || m && m.decoration,
								rotated: w.rotated,
								kerning: w.kerning
							});
						m && G.setFont(m);
						A = G.getNode();
                        //添加设置text 的haloColor
						if(w.haloColor){
							A.setAttribute("stroke-opacity","1");
							A.setAttribute("stroke-width",w.haloSize||0.5);
							A.setAttribute("stroke",w.haloColor);
						}
						e = g.getSVGBaseline(w);
						w = g.getSVGBaselineShift(w);
					
						A && (A.setAttribute("dominant-baseline", e), w && A.setAttribute("baseline-shift", w))
					}

 


版权声明:本文为lh1162810317原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。