我已经汇总了一个将mapboxgl地图放在three.js表面上的简单示例。这比基于栅格的地图提供了更好的响应。我们希望这样做是为了让地图位于移动设备视图的表面上,而这些视图始终是“向下”。当你将手机向下指时(这个例子在这里没有这样做)。
然而,仍有相当数量的内存被改组 - 如果将地图直接绘制到与three.js相同的webgl上下文中,则更合乎逻辑 - 所以问题在于围绕这些内容改进代码线。
下面的例子也展示了一种类似的技术,可以将视频放在三个表面上,但不幸的是在移动设备上不能很好地工作 - 所以同样,任何想法都会受到赞赏。
<!doctype html>
<html lang="en">
<head>
<title>Texture from Canvas (Three.js)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=0.3, maximum-scale=0.3">
</head>
<body>
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.20.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.20.1/mapbox-gl.css' rel='stylesheet' />
<script src="js/threejs/three.min.js"></script>
<script src="js/threejs/Detector.js"></script>
<!-- jQuery code to display an information button and box when clicked. -->
<script src="js/jquery/jquery.min.js"></script>
<script src="js/jquery/jquery-ui.js"></script>
<!-- ------------------------------------------------------------ -->
<div id="three" style="position: absolute; left:0px; top:0px"></div>
<div id="map" style="position: fixed; left:0px; top:0px; width:512px; height:512px;"></div>
<video id="video" style="position: fixed; left:0px; top:512px;" src="/videos/Big_Buck_Bunny_small.ogv" controls="false"></video>
<script>
/*
Three.js "tutorials by example"
Original Author: Lee Stemkoski
Modified by: Dr. Roy Davies to show mapboxgl
Date: July 2013 (three.js v59dev)
*/
// MAIN
// standard global variables
var container, scene, camera, renderer;
var mapcanvas;
var mapmaterial;
var videocanvas;
var videomaterial;
// custom global variables
init();
animate();
// FUNCTIONS
function init()
{
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'three' );
container.appendChild( renderer.domElement );
// LIGHT
var light = new THREE.PointLight(0xffffff);
light.position.set(0,250,0);
scene.add(light);
// SKYBOX/FOG
var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
// scene.add(skyBox);
scene.fog = new THREE.FogExp2( 0x9999ff, 0.00025 );
////////////
// CUSTOM //
////////////
DoMapTexture();
DoVideoTexture();
}
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
function update()
{
}
function render()
{
renderer.render( scene, camera );
}
function DoMapTexture()
{
// Using Mapbox GL
mapboxgl.accessToken = '<YOUR MAPBOX ACCESS TOKEN>';
map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/bright-v9',
zoom: 1,
center: [180,0],
pitch: 0
});
// When it has finished loading, set up the sources and layers
map.on("load", function ()
{
// Find the newly created WebGL map canvas
mapcanvas = document.getElementsByClassName('mapboxgl-canvas')[0];
// A loader for the image
var maploader = new THREE.TextureLoader();
// load a resource
maploader.load(
// Convert the webgl 'image' to a 'url'
mapcanvas.toDataURL(),
// Load the map image
function ( texture ) {
// Place the material on a mesh
mapmaterial = new THREE.MeshBasicMaterial( {map: texture, side:THREE.DoubleSide} );
mapmaterial.transparent = true;
var mapmesh = new THREE.Mesh( new THREE.PlaneGeometry(500, 500), mapmaterial );
mapmesh.rotation.x = -Math.PI / 2;
scene.add( mapmesh );
}
);
});
// Whenever it renders, redraw the texture
map.on('render', function(e) {
if (mapcanvas)
{
var maploader = new THREE.TextureLoader();
// Reload the material
maploader.load(
mapcanvas.toDataURL(),
function ( texture ) {
mapmaterial.map = texture;
mapmaterial.map.needsUpdate = true;
}
);
}
});
}
function DoVideoTexture()
{
// Create a temporary 2D canvas as an intermediary for the texture
var videocanvas = document.createElement('canvas');
var ctx = videocanvas.getContext('2d');
var video = document.getElementById('video');
// set canvas size = video size when known
video.addEventListener('loadedmetadata', function() {
videocanvas.width = video.videoWidth;
videocanvas.height = video.videoHeight;
});
video.addEventListener('play', function() {
var $this = this; //cache
(function loop() {
if (!$this.paused && !$this.ended) {
ctx.drawImage($this, 0, 0);
if (videocanvas)
{
var videoloader = new THREE.TextureLoader();
// Reload the material
videoloader.load(
videocanvas.toDataURL(),
function ( texture ) {
videomaterial.map = texture;
videomaterial.map.needsUpdate = true;
}
);
}
setTimeout(loop, 1000 / 30); // drawing at 30fps
}
})();
}, 0);
// A loader for the image
var videoloader = new THREE.TextureLoader();
// load a resource
videoloader.load(
// Convert the webgl 'image' to a 'url'
videocanvas.toDataURL(),
// Load the map image
function ( texture ) {
// Place the material on a mesh
videomaterial = new THREE.MeshBasicMaterial( {map: texture, side:THREE.DoubleSide} );
videomaterial.transparent = false;
var videomesh = new THREE.Mesh( new THREE.PlaneGeometry(200, 100), videomaterial );
videomesh.position.set(100,100,0);
scene.add( videomesh );
}
);
}
</script>
</body>
</html>