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))
}