2050.earth 代碼分析-——第四部分(active hexagon)



/*
 █████╗  ██████╗████████╗██╗██╗   ██╗███████╗    ██╗  ██╗███████╗██╗  ██╗ █████╗  ██████╗  ██████╗ ███╗   ██╗
██╔══██╗██╔════╝╚══██╔══╝██║██║   ██║██╔════╝    ██║  ██║██╔════╝╚██╗██╔╝██╔══██╗██╔════╝ ██╔═══██╗████╗  ██║
███████║██║        ██║   ██║██║   ██║█████╗      ███████║█████╗   ╚███╔╝ ███████║██║  ███╗██║   ██║██╔██╗ ██║
██╔══██║██║        ██║   ██║╚██╗ ██╔╝██╔══╝      ██╔══██║██╔══╝   ██╔██╗ ██╔══██║██║   ██║██║   ██║██║╚██╗██║
██║  ██║╚██████╗   ██║   ██║ ╚████╔╝ ███████╗    ██║  ██║███████╗██╔╝ ██╗██║  ██║╚██████╔╝╚██████╔╝██║ ╚████║
╚═╝  ╚═╝ ╚═════╝   ╚═╝   ╚═╝  ╚═══╝  ╚══════╝    ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝  ╚═════╝ ╚═╝  ╚═══╝
*/
    
    // TODO: separate placing of additive prview hexagons
    var active_hex_dummy = new THREE.Object3D();
    active_hex_dummy.matrixAutoUpdate = false;
    this.container.add( active_hex_dummy );

    var active_hexagon = null;//
    var extActiveHexagonHide;// External method to hide DOM element of the active hexagon

    // ACTIVE HEXAGON
    function activateHexagon( _location, mobile){
        scope.deactivateHexagon();

        main.controls.autoRotate = false;
        scope.location_current = _location;

        // Define an array of nearby locations to view
        location_picked = _location;
        _location.briefs = PlanetData.hasLocationAnyBriefs( location_picked, true );
        _location.briefs_text = PlanetData.hasLocationAnyBriefTexts( location_picked, true );
        _location.works_list = PlanetData.getWorkList( location_picked, true );
        _location.more = PlanetData.getMoreText( location_picked, true );
        ;
        
        var _locations = [ _location ];

        // Hit an external method to show defined hexagons
        if( kaspersky.getHexaspherePopup ) {

            var o = kaspersky.getHexaspherePopup( _locations, moveToActiveHexagon, mobile);
            active_hexagon = o.element;
            extActiveHexagonHide = o.close;

            var $active_hexagon = $(active_hexagon);
            $active_hexagon.on( "mouseleave", onActiveHexagonMouseLeave );

            function onActiveHexagonMouseLeave(){
                scope.deactivateHexagon();
                $active_hexagon.off( "mouseleave", onActiveHexagonMouseLeave );
            }
        }

        active_hex_dummy.position.copy( _location.position );

        // Disable Earth constant rotation
        main.controls.autoRotate = false;
        _location.light.visible = false;

        // Hide current commentary
        scope.commentToggle( false );
    }


    this.deactivateHexagon = function() {

        if( !location_picked ) return;

        if (typeof extActiveHexagonHide === "function") extActiveHexagonHide();

        active_hexagon = null;

        scope.location_current = null;
        location_picked.light.visible = true;
        location_picked = null;

        main.controls.autoRotate = true;

        // show a commentary
        scope.commentToggle( true );
    }

    var camera_rotator = new THREE.Object3D();
    camera_rotator.up = new THREE.Vector3(0,1,0);
    main.scene.add(camera_rotator);
    camera_rotator.matrixAutoUpdate = false;

    function moveToActiveHexagon( location ) {
        var navigateUrl;
        var $info = location.years[PlanetData.YEAR_ID];

        if ($info.type === "brief") {
            navigateUrl  = langUrl + $info.brief_id;
        } else {
            navigateUrl = langUrl + "locations/" + PlanetData.YEAR_ID + "/" + location.location_id;
        }
        scope.state = scope.ANIMATED;

        main.controls.detach();
        DOMElement.style.cursor = "default";

        scope.deactivateHexagon();

        // hide current commentary
        scope.commentToggle( false );

        // target rotation
        camera_rotator.lookAt( location.position );
        var qend = camera_rotator.quaternion.clone();
        camera_rotator.lookAt( main.camera.position );
        var qstart = camera_rotator.quaternion.clone();
        camera_rotator.updateMatrix();

        var d = main.camera.position.length();
        camera_rotator.add( main.camera );
        main.camera.position.set( 0,0,d );
        main.camera.rotation.set( 0,0,0 );

        scene.updateMatrixWorld();

        // ANIMATE SPHERICAL ROTATION TO ACTIVE HEXAGON
        camera_rotator._anim_progress_ = 0;
        TweenLite.to( camera_rotator, 1.5, {
            _anim_progress_: 1,
            ease: Sine.easeInOut,
            onUpdate: function () {
                THREE.Quaternion.slerp( qstart, qend, camera_rotator.quaternion, camera_rotator._anim_progress_ );
                camera_rotator.updateMatrix();
            },
            onComplete: function() {

                TweenLite.to( main.camera.position, 1.2, {
                    z: radius*1.15,
                    ease: Sine.easeIn,
                  
                    onComplete: function() {
                  
                    }
                });

                // show Transition
                setTimeout( kaspersky.Transition.fadeIn, 400);
                setTimeout(function () {

                    kaspersky.navigateTo( navigateUrl );
                }, 400);

            }
        });

    }



    // UTILS

    this.isInFrontOfPlanet = function( position ) {
        var dist = camera.position.distanceToSquared( position );
        if( dist > camera_dist_to_center ) return false;
        return true;
    }

    this.googlePosToUV = function( _u, _v ){
        if( _u===undefined ) {
            var a = ('40.705565,-74.1180857').split(",");
            _u = a[0];
            _v = a[1];
        }
        var u = 1-(parseFloat( _u ) + 90 )/180;
        u += .014; if( u>1 ) u = u-1;
        var v = (parseFloat( _v ) + 180 )/360;
        v -= .031; if( v<0 ) v = 1+v;

        return {u:u,v:v};
    }


    // INIT THE PLANET
    var _first_year = window.currentYear || PlanetData.year_ids[0];

    onReady();
    main.animateOut( .05 , function(){
        scope.showYear( _first_year, undefined, 6 );
    });

}



Planet.prototype.getClosestLocation = function( intersection ) {
    
    var _location_current;
    var min = isMobile.any ? .15 : .04;
    var _locations = this.planetLocations.current_locations;
   
    for (var i = 0; i < _locations.length; i++) {
        
        var l = _locations[i];

        // if the location object has no briefs
        if( !l.position ) continue;
        if( !PlanetData.hasLocationAnyBriefs( l, true ) ) continue;

        var d = intersection.distanceToSquared( l.position );
        if( d<min ){
            min = d;
            _location_current = l;
            break;
        }
    };
    
    return _location_current;
}


Planet.prototype.getAnyClosestLocation = function( intersection, except_locations ) {
    
    var _location_current;
    var min = 10000;
    var _locations = this.planetLocations.current_locations;

    for (var i = 0; i < _locations.length; i++) {
        
        var l = _locations[i];
        
        if( except_locations && checkExceptions( l ) ) continue;

        var d = intersection.distanceToSquared( l.position );
        if( d<min ){
            min = d;
            _location_current = l;
        }
    };
    
    function checkExceptions ( l ) {
        for (var j = 0; j < except_locations.length; j++) {
            if( except_locations[j] == l) return true;
        };
        return false;
    }

    return _location_current;
}

function Hexagon ( scene ) {
    
    var active_color = new THREE.Color( 0xffffff );
    var inactive_color = new THREE.Color( 0x507e50 );
    
    var mesh = Utils.createHexagon( .5 );
    // mesh.up = new THREE.Vector3(0,1,0);
    var material = mesh.material;
    material.transparent = true;
    material.opacity = .4;
    material.blending = THREE.AdditiveBlending;
    material.depthWrite = false;

    mesh._anim_progress = .001;
    mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
    
    mesh.setToLocation = function ( l ) {
        // console.log("setToTile: ", l);
        mesh.location = l;

        mesh.position.copy( l.position );
        mesh.lookAt( new THREE.Vector3() );

        material.color = active_color;
        scene.add( mesh );
        mesh.matrixAutoUpdate = true;
        TweenLite.killTweensOf( mesh );
        TweenLite.to( mesh, .2, {
            _anim_progress: .8,// * .8,
            // ease: Sine.easeOut,
            onUpdate: function () {
                mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
            },
            onComplete:function() {
                mesh.matrixAutoUpdate = false;
            }
        });
    }

    mesh.hide = function( _assets ) {
        mesh.matrixAutoUpdate = true;
        TweenLite.killTweensOf( mesh );
        TweenLite.to( mesh, 1, {
            _anim_progress: .001,
            // ease: Sine.easeIn,
            onUpdate: function () {
                mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
            },
            onComplete: function () {
                scene.remove( mesh );
                _assets.push( mesh );
                mesh.matrixAutoUpdate = false;
            }
        });
    }
/*
    //
    mesh.setActive = function() {
    	// console.log("setActive", mesh.tile);
    	if( !mesh.tile ) return;
    	mesh.is_active = true;

    	TweenLite.killTweensOf( mesh );
    	mesh._anim_progress = 0;
        TweenLite.to( mesh, .2, {
            _anim_progress: 1,
            // ease: Sine.easeOut,
            onUpdate: function () {
            	var scl = mesh._anim_progress*1+1;
                mesh.scale.set( scl, scl, scl );
                mesh.position.copy( mesh.tile.centerPoint ).multiplyScalar( 1 + scl*.05 );
            }
        });
    }

    mesh.setInactive = function( _assets ) {
    	// _assets.push( mesh );
    	mesh.is_active = false;

    	TweenLite.killTweensOf( mesh );
    	// mesh._anim_progress = 0;
        TweenLite.to( mesh, .5, {
            _anim_progress: .01,
            // ease: Sine.easeOut,
            onUpdate: function () {
                mesh.scale.set( mesh._anim_progress, mesh._anim_progress, mesh._anim_progress );
            },
            onComplete: function () {
                scene.remove( mesh );
                _assets.push( mesh );
            }
        });
    }
*/
    return mesh;
}
function PlanetLocations ( planet ) {
    
	var data = planet.data;
	var data_locations = data.locations;
	var current_container;

	this.current_locations;// a list of locations corresponding to the current year

	var max_opacity = .8;
    var material_yellow = new THREE.MeshBasicMaterial({
    	transparent : true,
	    opacity : 0,
	    color : new THREE.Color( 0xffde00 ),
	    blending : THREE.AdditiveBlending,
	    side : THREE.DoubleSide,
	    depthWrite : false	
    });

    var material_white = new THREE.MeshBasicMaterial({
    	transparent : true,
	    opacity : 0,
	    color : new THREE.Color( 0xffffff ),
	    blending : THREE.AdditiveBlending,
	    side : THREE.DoubleSide,
	    depthWrite : false,
    });


    // !!! fake locations

    // get image links
    var f_images = [];
    for (var i = 0; i < data_locations.length; i++) {
        f_images.push( data_locations[i].preview );
    }

    

    // make base location shape
    var hex = Utils.createHexagon( .15, false, undefined );
    // additional shape - the ring
    var hex_ring = Utils.createHexagon( .2, false, undefined, .02 );
    hex.add( hex_ring );


    var r = planet.radius*1.005;
    var zero = new THREE.Vector3();

    
    // METHODS

    this.init = function ( _year ){

    	var container = new THREE.Object3D();
	    container.matrixAutoUpdate = false;

	    var _locations = container._locations = [];
	    for (var i = 0; i < data_locations.length; i++) {
	    	var l = data_locations[i];
	    	_locations.push( l );/// All Locations are available in all Years
	    }
	    var geo;
	    var geo_yellow = new THREE.Geometry();//hex.geometry.clone();
	    var geo_white = new THREE.Geometry();//hex.geometry.clone();
	    
    	for (var i = 0; i < _locations.length; i++) {
	        
			var l = _locations[i];
			if(!!l.years[_year] === false) continue;
	        var l_year_data = l.years[_year];
	        
	        // skip a point creation if the location doesn't have any briefs
	        if( !l_year_data.briefs ) continue;

	        // get shorthand to a country object of the location
	        l.country = data.countries_by_id[ l.country_id ];
	        
	        var uv = planet.googlePosToUV( l.planet_u, l.planet_v );
	        Utils.setFromSpherical( r, uv.v, uv.u, hex.position );
	        hex.lookAt( zero );
	        hex.updateMatrix();
	        hex.updateMatrixWorld();

	        geo = l_year_data.works ? geo_yellow : geo_white;
	        geo.merge( hex.geometry, hex.matrixWorld );
	        geo.merge( hex_ring.geometry, hex_ring.matrixWorld );

	        l.position = hex.position.clone();

	        // and finaly the ray
	        l.light = addLightRay( hex.position, l_year_data.works );
	        container.add( l.light );

		};
		
	    var hexs_yellow = new THREE.Mesh( geo_yellow, material_yellow );
	    container.add( hexs_yellow );

	    var hexs_white = new THREE.Mesh( geo_white, material_white );
	    container.add( hexs_white );

	    return container;
    }



    this.show = function( _year, t ){
		var year_data = PlanetData.years[_year];

		if( !year_data.locations_container ) year_data.locations_container = this.init( _year );
		current_container = year_data.locations_container;
		this.current_locations = current_container._locations;

		planet.container.add( current_container );

		_showMaterial( material_yellow, t );
		_showMaterial( material_white, t );
		showRays( t/2, t/2 );
	}

	function _showMaterial( mat, t ){

		var _anim = 0;
		var t1 = .3;

		mat.opacity = 0;
		
		TweenLite.killTweensOf( mat );
		TweenLite.to( mat, t1, {
			delay: t-t1,
			ease: Sine.easeOut
			,onUpdate:function(){
				_anim += 1;
				mat.opacity = Math.round( _anim%2 ) * max_opacity;
			}
			,onComplete: function(){
				mat.opacity = max_opacity;
			}
		});

	}
	
	this.hide = function ( t ) {
		
		_hideMaterial( material_yellow, t );
		_hideMaterial( material_white, t );
		hideRays( t/2 );
	}

	function _hideMaterial( mat, t ){
		
		var _anim = 0;

		TweenLite.killTweensOf( mat );
		TweenLite.to( mat, .3, {
			ease: Sine.easeInOut
			,onUpdate:function(){
				_anim += 1;
				mat.opacity = Math.round( _anim%2 ) * max_opacity;
			}
			,onComplete: function(){
				planet.container.remove( current_container );	
			}
		});
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章