2017-06-04 27 views
0

mapbox-gl-jsを使用してマップ上のある座標から別の座標に多くの画像をアニメーションします。 15枚以上の画像を追加しようとするとフレームレートが遅くなります。 クロムのパフォーマンスプロファイルを実行すると、最も計算時間のかかるメソッドActor.receiveへのヒントが得られます。MapBox GLマーカー/アイコンアニメーションスローパフォーマンス

/** 
 
* Util.js 
 
*/ 
 
var linesDataSource = { 
 
    "type": "FeatureCollection", 
 
    "features": [{ 
 
    "type": "Feature", 
 
    "properties": {}, 
 
    "geometry": { 
 
     "type": "LineString", 
 
     "coordinates": [ 
 
     [ 
 
      151.15684390068054, -33.89568424317427 
 
     ], 
 
     [ 
 
      151.15808844566345, -33.89606717952166 
 
     ], 
 
     [ 
 
      151.15779876708984, -33.89680633086413 
 
     ], 
 
     [ 
 
      151.15740180015564, -33.897794824453406 
 
     ], 
 
     [ 
 
      151.1582601070404, -33.8980085512904 
 
     ], 
 
     [ 
 
      151.1609423160553, -33.89863191817193 
 
     ], 
 
     [ 
 
      151.16222977638245, -33.89621857248702 
 
     ], 
 
     [ 
 
      151.16639256477356, -33.89771467675142 
 
     ], 
 
     [ 
 
      151.1694610118866, -33.898916884371395 
 
     ], 
 
     [ 
 
      151.17089867591858, -33.896298721595166 
 
     ], 
 
     [ 
 
      151.17217540740964, -33.899014841282515 
 
     ], 
 
     [ 
 
      151.1714780330658, -33.899192944468965 
 
     ], 
 
     [ 
 
      151.17132782936093, -33.89878330658397 
 
     ], 
 
     [ 
 
      151.1719822883606, -33.8985784869035 
 
     ], 
 
     [ 
 
      151.17339849472046, -33.89839147720036 
 
     ], 
 
     [ 
 
      151.17376327514648, -33.89825789858986 
 
     ], 
 
     [ 
 
      151.17332339286804, -33.897269410368615 
 
     ], 
 
     [ 
 
      151.1732053756714, -33.89697553328233 
 
     ], 
 
     [ 
 
      151.17341995239258, -33.89662822269281 
 
     ], 
 
     [ 
 
      151.17295861244202, -33.896263099778615 
 
     ], 
 
     [ 
 
      151.17225050926208, -33.89589797530112 
 
     ], 
 
     [ 
 
      151.17136001586914, -33.89561299901295 
 
     ], 
 
     [ 
 
      151.17184281349182, -33.894758064434605 
 
     ], 
 
     [ 
 
      151.17200374603271, -33.89455323508587 
 
     ], 
 
     [ 
 
      151.17257237434387, -33.89148073582115 
 
     ], 
 
     [ 
 
      151.17042660713196, -33.89132042847356 
 
     ], 
 
     [ 
 
      151.17168188095093, -33.88838140703873 
 
     ], 
 
     [ 
 
      151.1716067790985, -33.887606557247125 
 
     ], 
 
     [ 
 
      151.16321682929993, -33.888274531623864 
 
     ], 
 
     [ 
 
      151.16029858589172, -33.88777577791726 
 
     ], 
 
     [ 
 
      151.1591076850891, -33.88790937294604 
 
     ], 
 
     [ 
 
      151.15857124328613, -33.8892809364742 
 
     ], 
 
     [ 
 
      151.1584746837616, -33.89006467716016 
 
     ], 
 
     [ 
 
      151.15894675254822, -33.89009139546571 
 
     ], 
 
     [ 
 
      151.15893602371216, -33.889806399775104 
 
     ] 
 
     ] 
 
    } 
 
    }] 
 
} 
 

 

 
var PI = Math.PI; 
 
var TWO_PI = Math.PI * 2; 
 

 
function rotation(start, end) { 
 
    var dx = end[0] - start[0]; 
 
    var dy = end[1] - start[1]; 
 
    return -Math.atan2(dy, dx) * (180/PI); 
 
}; 
 

 
function lerp(v0, v1, t) { 
 
    return v0 * (1 - t) + v1 * t 
 
} 
 

 
function interpolateAngle(fromAngle, toAngle, t) { 
 
    fromAngle = fromAngle * (PI/180); 
 
    toAngle = toAngle * (PI/180); 
 

 
    fromAngle = (fromAngle + TWO_PI) % TWO_PI; 
 
    toAngle = (toAngle + TWO_PI) % TWO_PI; 
 

 
    var diff = Math.abs(fromAngle - toAngle); 
 
    if (diff < PI) { 
 
    return lerp(fromAngle, toAngle, t) * (180/PI); 
 
    } else { 
 
    if (fromAngle > toAngle) { 
 
     fromAngle = fromAngle - TWO_PI; 
 
     return lerp(fromAngle, toAngle, t) * (180/PI); 
 
    } else if (toAngle > fromAngle) { 
 
     toAngle = toAngle - TWO_PI; 
 
     return lerp(fromAngle, toAngle, t) * (180/PI); 
 
    } 
 
    } 
 
} 
 

 

 

 

 

 
/** 
 
* Car.js 
 
*/ 
 
function Car(name, map, path) { 
 
    this.name = name; 
 
    this.map = map; 
 
    this.path = path; 
 
    this.speed = 90; // 30 km/h 
 
    this.accumulatedDistance = 0; 
 
    this.previousPos = this.path.features[0].geometry.coordinates[0]; 
 
    this.previousAngle = 0; 
 

 
    this.animate = function(frameInfo) { 
 

 
    this.accumulatedDistance += ((frameInfo.deltaTime/3600) * this.speed); 
 
    var point = turf.along(this.path.features[0], this.accumulatedDistance, 'kilometers'); 
 

 
    this.map.getSource(this.name).setData(point); 
 

 
    var newAngle = rotation(this.previousPos, point.geometry.coordinates); 
 
    var rotate = interpolateAngle(this.previousAngle, newAngle, 0.1); 
 

 
    this.map.setLayoutProperty(this.name, 'icon-rotate', rotate); 
 

 
    this.previousAngle = rotate; 
 
    this.previousPos = point.geometry.coordinates; 
 
    }; 
 

 
    this.init = function() { 
 
    this.map.addSource(this.name, { 
 
     "type": "geojson", 
 
     "data": { 
 
     "type": "FeatureCollection", 
 
     "features": [{ 
 
      "type": "Feature", 
 
      "geometry": { 
 
      "type": "Point", 
 
      "coordinates": this.previousPos 
 
      } 
 
     }] 
 
     } 
 
    }); 
 

 
    this.map.addLayer({ 
 
     "id": this.name, 
 
     "type": "symbol", 
 
     "source": this.name, 
 
     "layout": { 
 
     "icon-image": "car", 
 
     "icon-size": 1, 
 
     "icon-rotate": 0, 
 
     "icon-rotation-alignment": "map" 
 
     } 
 
    }); 
 
    }; 
 
} 
 

 

 

 

 

 
/** 
 
* MapBoxTest.js 
 
*/ 
 
var destination = {}; 
 
var cars = []; 
 
var style = 'mapbox://styles/mapbox/streets-v9'; //'/TestEmptyProject/mapbox-gl-styles-master/styles/basic-v8.json'; 
 
//'http://localhost:8080/styles/osm-bright.json'; // 'http://localhost:8080/styles/fiord-color-gl.json' 
 

 

 
mapboxgl.accessToken = 'pk.eyJ1IjoiZW1wZXJvcjE0MTIiLCJhIjoiY2ozYTYxdXFlMDM3dzJyczRsa2M5ZjE3aCJ9.9zQGtkSsjOw6npohN6ba3w'; 
 
var map = new mapboxgl.Map({ 
 
    container: 'map', 
 
    style: style, 
 
    center: [132.133333, -23.116667], 
 
    zoom: 3 
 
}); 
 

 
// Used to increment the value of the point measurement against the linesData. 
 
var counter = 0; 
 
var linesData = {}; 
 

 
function addCar() { 
 
    var car = new Car("Car_" + counter, map, linesData); 
 
    car.init(); 
 
    cars.push(car); 
 
    ++counter; 
 
} 
 

 
var previousTimeStamp = 0; 
 
// Add a source and layer displaying a point which will be animated in a circle. 
 
function animate(timeStamp) { 
 
    if (timeStamp <= previousTimeStamp) { 
 
    console.log("Wrong timeStamp, now: " + timeStamp + "\t previous: " + previousTimeStamp); 
 
    return; 
 
    } 
 

 
    var i; 
 
    var frameInfo = { 
 
    "timeStamp": timeStamp, 
 
    "previousTimeStamp": previousTimeStamp, 
 
    "deltaTime": (timeStamp - previousTimeStamp)/1000 
 
    }; 
 
    previousTimeStamp = timeStamp; 
 

 
    for (i = 0; i < cars.length; ++i) { 
 
    var car = cars[i]; 
 
    car.animate(frameInfo); 
 
    } 
 
    requestAnimationFrame(animate); 
 
} 
 

 
map.on('load', function() { 
 

 
    console.log("map load"); 
 

 
    map.loadImage('https://maxcdn.icons8.com/office/PNG/40/Transport/railroad_car-40.png', function(error, image) { 
 
    if (error) throw error; 
 
    map.addImage('car', image); 
 
    }); 
 

 
    //fetch('./lines.geojson', { 
 
    //method: 'get' 
 
//}).then(function(response) { 
 
// return response.json(); 
 
//}).then(function(data) { 
 

 
    linesData = linesDataSource; 
 
    var coordinates = linesData.features[0].geometry.coordinates; 
 

 
    var bounds = coordinates.reduce(function(bounds, coord) { 
 
    return bounds.extend(coord); 
 
    }, new mapboxgl.LngLatBounds(coordinates[0], coordinates[0])); 
 

 
    map.fitBounds(bounds, { 
 
    padding: 20, 
 
    duration: 2000 
 
    }); 
 

 
    map.addSource('lines', { 
 
    "type": "geojson", 
 
    "data": linesData 
 
    }); 
 

 
    map.addLayer({ 
 
    "id": "route", 
 
    "source": "lines", 
 
    "type": "line", 
 
    "paint": { 
 
     "line-width": 2, 
 
     "line-color": "#007cbf" 
 
    } 
 
    }); 
 
    // }).catch(function(err) { 
 
    //console.log("error: " + err); 
 
//}); 
 

 
document.getElementById('addCar').addEventListener('click', function() { 
 
addCar(); 
 
}); 
 

 

 
}); 
 

 

 
requestAnimationFrame(animate);
body { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 
    
 
#map { 
 
    position: absolute; 
 
    top: 0; 
 
    bottom: 0; 
 
    width: 100%; 
 
} 
 
    
 
.overlay { 
 
    position: absolute; 
 
    top: 10px; 
 
    left: 10px; 
 
} 
 
    
 
.overlay button { 
 
    font: 600 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; 
 
    background-color: #3386c0; 
 
    color: #fff; 
 
    display: inline-block; 
 
    margin: 0; 
 
    padding: 10px 20px; 
 
    border: none; 
 
    cursor: pointer; 
 
    border-radius: 3px; 
 
} 
 
    
 
.overlay button:hover { 
 
    background-color: #4ea0da; 
 
}
<script src="https://master.fieldtec.com/vendor/custom-component-modules/car_tracking_animation/scripts/turf.min.js"></script> 
 
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css" rel="stylesheet"/> 
 
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js"></script> 
 

 
<body> 
 
    <div id='map'></div> 
 
    <div class='overlay'> 
 
    <button id='addCar'>Add Car</button> 
 
    </div> 
 
</body>

答えて

1

つのソースを使用して、アニメーションのすべてを行います。各フレームをsetData()で更新します。データ駆動型を使用して、ソースから1つのレイヤーをレンダリングします。これはあなたのGPUを使ってアニメーションをレンダリングします。 これにより、レイヤー数とsetData()呼び出しを減らすことで、パフォーマンスが大幅に向上します。一つの層と、一方のソースとGL JSにアニメーションの

例コード:アイコンの数百をアニメーション化するhttps://bl.ocks.org/ryanbaumann/9b9b52e09ff86d1ce8346fb76b681427

1

、シェーダではなく、JavaScriptでアニメーションを実行する方が効率的です。これにより、GPUのパワーを活用することができます。ここにデモがあります:http://misterfresh.github.io/mapbox-animation/

関連する問題