如何在不需要两个画布的情况下将mapboxgl地图放在three.js中?

时间:2016-07-12 22:38:12

标签: video three.js mapbox-gl-js

我已经汇总了一个将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>

0 个答案:

没有答案