2016-07-14 1 views
1

나는 많은 가득 반투명 각각의 (일반적으로 몇 백) Rectangle 층을 구성 한 후 전단지 하나의 타일 층지도와 LayerGroup (densityLayer)를 가지고 특정 연도의 인구 밀도에 따라 fillColor를 오버레이합니다.리플릿 : 인/아웃 레이어 그룹에 페이드 효율적으로

사용자 작업에 따라 densityLayer의 내용이 변경됩니다. 매우 간단한 것만으로도 densityLayer.clearLayers()을 실행하면 모든 새로운 Rectangle 레이어와 각각 densityLayer.addLayer(aRectangle) 레이어가 생성됩니다. 즉, 모든 새로운 Rectangle 레이어를 생성하고 새로운 LayerGroup (newDensityLayer)에 넣고, 동시에 페이드 아웃 : 내가 할 원하는 무엇

하지만, 새로운 데이터를 이전에서 페이드 애니메이션을하는 것입니다 원본 oldDensityLayernewDensityLayer으로 페이드되고 퇴색이 완료되면 oldDensityLayer을 제거하고 newDensityLayer으로 바꿉니다.

var oldDensityLayer = densityLayer 
var newDensityLayer = {...create new density layer here, add polygons, etc...} 

oldDensityLayer.eachLayer(function(l) { 
    $(l._path).fadeOut(1000) // 1000ms animation time 
}) 

setTimeout(function() { 
    oldDensityLayer.clearLayers() 
    myLeafletMap.removeLayer(oldDensityLayer) 
    oldDensityLayer = null 
}, 1000) 

myLeafletMap.addLayer(newDensityLayer) 

// now fade in all the new polygons 
newDensityLayer.eachLayer(function(l) { 
    $(l._path).hide() // so they start out invisible 
    $(l._path).fadeIn(1000) 
}) 

densityLayer = newDensityLayer 

이 기본적으로 작동하지만, 매우 빠른 컴퓨터 그러나 아무것도 꽤 고르지 느린 가져옵니다

나의 현재 솔루션은 무시 무시 비효율적이다.

전체를 페이드 인/아웃하는 방법이 있습니까? LayerGroup 또는 일부 옵션은 고려하지 않았습니다 ...?

이것은 중요한 기능이므로 다른 js 라이브러리를 추가하면 도움이 될 것입니다. 또한, SVG에 대한 답변도 괜찮습니다. Leaflet에서 드로잉 기능을 사용하고 있기 때문에 크로스 브라우저 호환성은이 애플리케이션에서 문제가되지 않습니다.

답변

3

전체를 페이드 인/아웃하는 방법이 있습니까? LayerGroup 또는 일부 옵션은 고려하지 않았습니다 ...?

실제로 고려하지 않은 옵션이 있습니다. L.Renderer을 조작하여 실제적으로 HTML 요소로 그립니다. 즉, 실제 <canvas> (L.Canvas) 또는 실제 <svg> (L.SVG)을 조작하는 것을 의미합니다.

L.Path (Polygons, Polylines 등)의 하위 클래스는 its own renderer이 될 수 있습니다. 일반적으로 전단지는 L.Renderer의 인스턴스를 하나만 만들고, L.Path에 다시 사용합니다. 달리 언급하지 않는 한, 이는 HTML 요소가 적고 (사용 사례의 99 %에서) 더 나은 성능을 의미합니다.

그래서 같은 것을 보일 것입니다 : 코드는 분명히 불완전

var rendererA = L.canvas(); 
var rendererB = L.canvas(); 

var groupA = L.layerGroup().addTo(map); 
var layerA1 = L.polygon(…, {renderer: rendererA}).addTo(groupA); 
var layerA2 = L.polygon(…, {renderer: rendererA}).addTo(groupA); 

var groupB = L.layerGroup().addTo(map); 
var layerB1 = L.polygon(…, {renderer: rendererB}).addTo(groupB); 
var layerB2 = L.polygon(…, {renderer: rendererB}).addTo(groupB); 

// Here comes the magic - using the *undocumented*, *private* _container 
// property of L.Canvas to access the <canvas> HTML element itself 
rendererA._container.style.opacity = 0.5; 

를하지만 제대로 아이디어를 설명해야한다.

이렇게하면 브라우저에 두 개의 다른 <canvas>이 생성되며 HTML 요소 자체의 불투명도를 변경하면 기능이 다시 렌더링되지 않습니다. 대신 L.SVG을 사용하는 유사한 솔루션이 있어야하지만 브라우저가 SVG 컨테이너의 불투명도를 합성하는 방법을 잘 모르겠습니다.

이 방법에는 명백한 단점이 있습니다. 두 그룹의 지오메트리가 서로 얽혀 있어야하는 경우 z 순서 (bringToFront 등)가 손실되는 것과 같은 단점이 있습니다.

또한 기억하십시오 : 일을 실제로 정말로 알고 있고 API 변경 또는 희소 한 상황에서 코드가 깨지는 것을 기꺼이 보지 않으면 전단지 개체의 문서화되지 않은 사유 재산을 사용하지 않는 것이 좋습니다.

+0

이 매우 유망한 보인다. 오늘 그것을 테스트하려고합니다. – DanM

+0

아 - 이것은 리플릿 1.0 기능입니다. 그것이 내 문제를 해결할 수 있다는 것을 감안할 때, 나는 1.0RC1로 업그레이드를 시도 할 것이다. – DanM

+0

이것은 꽤 잘 작동했습니다. 나는 3 개의 렌더러 ("a", "b"및 "c")를 생성하고 순환 시켰으며, 하나가 퇴색하는 동안 페이드 아웃하고, 세 번째를 "낡은"레이어로 유지하여 어떤 경쟁 조건에도 빠지지 않았습니다 . – DanM

2

도형이 채워진 SVG 레이어를 포함 할 수 있습니다. 500 개 SVG 모양을 페이드 아웃의 예에서 아래 다음 SVG 모양의 새로운 무리를 구축하고 그들을 사라져요. (자신의 위치에서 모양을 확대 편집)

<!DOCTYPE html> 
 

 
<html xmlns="http://www.w3.org/1999/xhtml"> 
 

 
<head> 
 
    <title>Fade Out/In SVG Elements in Leaflet World Map</title> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> 
 
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.5/mapbox.js'></script> 
 
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.1.5/mapbox.css' rel='stylesheet' /> 
 

 
</head> 
 

 
<body style='font-family:arial'> 
 
<center><h4>Fade Out/In SVG Elements in Leaflet World Map</h4> 
 
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'> 
 
This adds 500 svg elements(circles, ellipses, rects, polygons) to the SVG layer in the world map. The map's mouse wheel zoom remains smooth in IE/CH/FF. Each element has a lat/lng value, converted to the needed x,y values to translate each symbol to the desired point. 
 
During map zoom level changes, the symbols are automatically scaled and translated, maintaining their original size and position. 
 

 
</div> 
 
<br /> 
 
<table border=1> 
 
<tr> 
 
<td> 
 
<b>Scenerio:</b><br /> 
 
1). The map is placed into its DIV (width:800px, height:400px).<br /> 
 
2). The map is centered at Lat/Lng (0,0) at zoom level 1.<br /> 
 
3.) The SVG element is added via <b>initPathRoot.</b><br /> 
 
4.) 500 SVG elements are added, randomly place about the world.<br /> 
 
5.) The svg <b>viewBox</b> is computed, used to create x,y values for the symbols.<br /> 
 
6.)Each element is translated/scaled when the map is zoomed, using the <b>viewreset</b> event.<br /> This calls the map method <b>latLngToLayerPoint(MyLatLng)</b> to accomplish this. 
 
<br>7.) Select <button>fade out/in</button> to fade out the current elements, build a new group, then fade In new group 
 
</td> 
 
</tr> 
 
</table> 
 

 
<div style='width:800px;height:400px' id='MyMap'></div> 
 
    <button onClick=fadeOutIn()>fade out/in</button> 
 

 
    <br />Javascript:<br /> 
 
<textarea spellcheck=false id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea> 
 
</center> 
 

 
<script id=myScript> 
 
L.mapbox.accessToken = 'pk.eyJ1IjoiZmhlbXNoZXIiLCJhIjoiODQ5MW9WayJ9.px2P6wVMFucfXHE1zmDA1A'; 
 
MyMap = L.mapbox.map('MyMap', 'mapbox.streets', { zoomControl:false,center: new L.latLng(0,0),zoom:1,minZoom:1}); 
 
//---zooming the map--- 
 
MyMap.on("viewreset", adjustSVGSymbols); 
 

 
var MySVG 
 
var SymbolG //---<g> element containing all symbols--- 
 
var VBw 
 
var VBh 
 
var NS="http://www.w3.org/2000/svg" 
 

 
//---body onload--- 
 
function initSVG() 
 
{ 
 
\t MyMap._initPathRoot() //---creates an svg layer--- 
 
\t MySVG=document.querySelector("svg") //---access svg element--- 
 
\t //---place symbols in here--- 
 
\t SymbolG=document.createElementNS(NS,"g") 
 
    SymbolG.setAttribute("id","symbolG") 
 
\t MySVG.appendChild(SymbolG) 
 
\t //---create random svg elements, place in SymbolG-- 
 
\t getViewBox()//---used to place svg random elements 
 
\t //---create 500 symbols at size 10 pixels-- 
 
\t svgGLOB(500,10) 
 
} 
 

 
//--- on map zoom - fired via map event: viewreset--- 
 
function adjustSVGSymbols() 
 
{ 
 

 
\t var symbols=SymbolG.childNodes 
 
\t for(var k=0;k<symbols.length;k++) 
 
\t { 
 
\t \t var symbol=symbols.item(k) 
 
\t \t //---initial lat/lng for symbol--- 
 
\t \t var lat=parseFloat(symbol.getAttribute("lat")) 
 
\t \t var lng=parseFloat(symbol.getAttribute("lng")) 
 
\t \t var latLng= new L.latLng(lat, lng) 
 
\t \t var transX=MyMap.latLngToLayerPoint(latLng).x 
 
\t \t var transY=MyMap.latLngToLayerPoint(latLng).y 
 
      //---scale--- 
 
       var initZoom=parseFloat(symbol.getAttribute("initZoom")) 
 
       var scale = (Math.pow(2, MyMap.getZoom())/2)/(Math.pow(2, initZoom)/2); 
 
    \t \t //---trash previous transform--- 
 
\t \t symbol.setAttribute("transform","") 
 
\t \t symbol.removeAttribute("transform") 
 

 
\t \t var transformRequestObj=MySVG.createSVGTransform() 
 
\t \t var animTransformList=symbol.transform 
 
\t \t //---get baseVal to access/place object transforms 
 
\t \t var transformList=animTransformList.baseVal 
 
\t \t //---translate---- 
 
\t \t transformRequestObj.setTranslate(transX,transY) 
 
\t \t transformList.appendItem(transformRequestObj) 
 
\t \t transformList.consolidate() 
 
\t \t //---scale--- 
 
\t \t transformRequestObj.setScale(scale,scale) 
 
\t \t transformList.appendItem(transformRequestObj) 
 
\t \t transformList.consolidate() 
 
\t } 
 

 

 
} 
 
//---needed for random symbol placement: create x,y values--- 
 
function getViewBox() 
 
{ 
 
\t vb=MySVG.viewBox.baseVal 
 
\t VBw=vb.width 
 
\t VBh=vb.height 
 
} 
 
//---compute svg elems: circles, rects, ellipses, polygons--- 
 
function svgGLOB(elems,elemSize) 
 
{ 
 
\t //---note: each browser creates a different sized svg layer--- 
 
\t var svgWidth=VBw 
 
\t var svgHeight=VBh 
 
\t //---obtain a random whole number from a thru b--- 
 
\t function rdm(a,b) 
 
\t { 
 
\t \t return a + Math.floor(Math.random()*(b-a+1)); 
 
\t } 
 

 
\t function randomPoints(elems,svgWidth,svgHeight,elemSize) 
 
\t { 
 
\t \t //--return format:[ [x,y],[x,y],,, ] 
 
\t \t //---Generate random points--- 
 
\t \t function times(n, fn) 
 
\t \t { 
 
\t \t \t var a = [], i; 
 
\t \t \t for (i = 0; i < n; i++) 
 
\t \t \t { 
 
\t \t \t \t a.push(fn(i)); 
 
\t \t \t } 
 
\t \t \t return a; 
 
\t \t } 
 
\t \t var width=svgWidth-2*elemSize //---offset from edge--- 
 
\t \t var height=svgHeight-2*elemSize //---offset from edge--- 
 

 
\t \t return \t RandomPnts = times(elems, function() { return [Math.floor(width * Math.random()) + elemSize, Math.floor(height * Math.random()) + elemSize] }); 
 
\t } 
 
\t //---random color--- 
 
\t function rcolor() 
 
\t { 
 
\t \t var letters = 'ABCDEF'.split(''); 
 
\t \t var color = '#'; 
 
\t \t for (var i = 0; i < 6; i++) 
 
\t \t { 
 
\t \t \t color += letters[Math.round(Math.random() * 15)]; 
 
\t \t } 
 
\t \t return color; 
 
\t } 
 
\t function polygon(vCnt,radius,centerX,centerY) 
 
\t { 
 
\t \t var myPoints=[] 
 
\t \t var polyXPts  = Array(vCnt); 
 
\t \t var polyYPts  = Array(vCnt); 
 
\t \t var vertexAngle = 360/vCnt; 
 
\t \t //---init polygon points processor--- 
 
\t \t for(var v=0; v<vCnt; v++) 
 
\t \t { 
 
\t \t \t theAngle = (v*vertexAngle)*Math.PI/180; 
 
\t \t \t polyXPts[v] = radius*Math.cos(theAngle); 
 
\t \t \t polyYPts[v] = -radius*Math.sin(theAngle); 
 
\t \t } 
 
\t \t //--note points are CCW--- 
 
\t \t for(var v=0;v<vCnt; v++) 
 
\t \t { 
 
\t \t \t var point=[centerX+polyXPts[v],centerY+polyYPts[v]] 
 
\t \t \t myPoints.push(point) 
 
\t \t } 
 
\t \t return myPoints 
 
\t } 
 

 
\t var Points=randomPoints(elems,svgWidth,svgHeight,elemSize) 
 

 
\t var n=Points.length 
 
\t var circleCnt=0 
 
\t var ellipseCnt=0 
 
\t var rectCnt=0 
 
\t var polygonCnt=0 
 

 
\t var RandomElems=[] 
 
\t RandomElems[0]="circle" 
 
\t RandomElems[1]="rect" 
 
\t RandomElems[2]="ellipse" 
 
\t RandomElems[3]="polygon_3" 
 
\t RandomElems[4]="polygon_4" 
 
\t RandomElems[5]="polygon_5" 
 
\t RandomElems[6]="polygon_6" 
 
\t RandomElems[7]="polygon_7" 
 
\t RandomElems[8]="polygon_8" 
 
\t RandomElems[9]="polygon_9" 
 
\t RandomElems[10]="polygon_10" 
 
\t RandomElems[11]="polygon_11" 
 
\t RandomElems[12]="polygon_12" 
 

 
\t //---create all at center(0,0), then translate--- 
 

 
\t for(var k=0;k<n;k++) 
 
\t { 
 
\t \t var rand=rdm(0,12) 
 
\t \t var elemStr=RandomElems[rand] 
 

 
\t \t if(!elemStr.indexOf("_")) 
 
\t \t var elemSt=elemStr 
 
\t \t else 
 
\t \t var elemSt=elemStr.split("_")[0] 
 

 
\t \t //var elem=document.createElementNS(NS,elemSt) 
 
\t \t var x=Points[k][0] 
 
\t \t var y=Points[k][1] 
 

 
\t \t var lng=((x * 360/VBw) - 180) 
 
\t \t var lat= (90 - (y * 180/VBh)) 
 

 
\t \t var id="symbol"+k 
 

 
\t \t var fill=rcolor() 
 
\t \t var elem=document.createElementNS(NS,elemSt) 
 
\t \t elem.setAttribute("id",id) 
 
\t \t elem.setAttribute("cursor","default") 
 
\t \t elem.setAttribute("fill",fill) 
 
\t \t elem.setAttribute("lat",lat) 
 
\t \t elem.setAttribute("lng",lng) 
 

 
\t \t if(elemSt=="circle") 
 
\t \t { 
 
\t \t \t var r=elemSize 
 
\t \t \t elem.setAttribute("r",r) 
 
\t \t } 
 
\t \t else if(elemSt=="ellipse") 
 
\t \t { 
 
\t \t \t var rx=elemSize 
 
\t \t \t var ry=elemSize/2 
 
\t \t \t elem.setAttribute("rx",rx) 
 
\t \t \t elem.setAttribute("ry",ry) 
 
\t \t } 
 
\t \t else if(elemSt=="rect") 
 
\t \t { 
 
\t \t \t var width=elemSize 
 
\t \t \t var height=elemSize 
 
\t \t \t //---center at 0,0--- 
 
\t \t \t var x=-elemSize/2 
 
\t \t \t var y=-elemSize/2 
 

 
\t \t \t elem.setAttribute("width",width) 
 
\t \t \t elem.setAttribute("height",height) 
 
\t \t \t elem.setAttribute("x",x) 
 
\t \t \t elem.setAttribute("y",y) 
 
\t \t } 
 
\t \t else if(elemSt=="polygon") 
 
\t \t { 
 
\t \t \t var pgonSides=parseInt(elemStr.split("_")[1]) 
 
\t \t \t var pgonPnts=polygon(pgonSides,elemSize,0,0) 
 

 
\t \t \t var points=pgonPnts.join() 
 
\t \t \t elem.setAttribute("points",points) 
 
\t \t } 
 

 
     elem.setAttribute("initZoom",1) 
 

 
\t \t SymbolG.appendChild(elem) 
 
\t } 
 
\t //---initialize locations--- 
 
\t adjustSVGSymbols() 
 
} 
 
//---fade out/In button---- 
 
function fadeOutIn() 
 
{ 
 
    $("#symbolG").fadeOut(1000, function(){ 
 
      createAnotherGlob() 
 
     }); 
 
} 
 
function createAnotherGlob() 
 
{ 
 
    var symbols=SymbolG.childNodes 
 
    for(var k=symbols.length-1;k>=0;k--) 
 
    SymbolG.removeChild(symbols.item(k)) 
 

 
    svgGLOB(500,10,true) 
 

 
    $("#symbolG").fadeIn(1500) 
 

 
} 
 

 
</script> 
 
<script> 
 
document.addEventListener("onload",init(),false) 
 
function init() 
 
{ 
 
\t jsValue.value=myScript.text 
 
\t initSVG() 
 
} 
 
</script> 
 

 
</body> 
 

 
</html>

관련 문제