2050.earth 代碼分析-——第三部分(planet base、comment tip、update、interactive、hovers )


var kaspersky;
/*
██████╗ ██╗      █████╗ ███╗   ██╗███████╗████████╗    ██████╗  █████╗ ███████╗███████╗
██╔══██╗██║     ██╔══██╗████╗  ██║██╔════╝╚══██╔══╝    ██╔══██╗██╔══██╗██╔════╝██╔════╝
██████╔╝██║     ███████║██╔██╗ ██║█████╗     ██║       ██████╔╝███████║███████╗█████╗  
██╔═══╝ ██║     ██╔══██║██║╚██╗██║██╔══╝     ██║       ██╔══██╗██╔══██║╚════██║██╔══╝  
██║     ███████╗██║  ██║██║ ╚████║███████╗   ██║       ██████╔╝██║  ██║███████║███████╗
╚═╝     ╚══════╝╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝   ╚═╝       ╚═════╝ ╚═╝  ╚═╝╚══════╝╚══════╝
*/

function Planet( main, data, onReady, locationAPI ){
    
    var $debug = $(".debug");

    var scope = window.PLANET = this;
    
    scope.main = main;
    var DOMElement = main.renderer.domElement;
    var scene = scope.scene = main.scene;
    var camera = main.camera;

    var radius = scope.radius = 10;        // Radius used to calculate position of tiles
    var ratio = scope.ratio = window.devicePixelRatio || 1;

    // PLANET 3D CONTAINER
    var container = this.container = new THREE.Object3D();
    scene.add(container);

    // 3D CONTAINER FOR OBJECTS LOOKING TO THE CAMERA
	var static_container = this.static_container = new THREE.Object3D();
    scene.add(static_container);
    static_container.matrixAutoUpdate = false;

    var textureLoader = this.textureLoader = new THREE.TextureLoader();

    this.planet_color = 0xa6f5a3;
    this.water_color = 0x81915b;
    
    // STATES
    scope.LOADING = "loading";
    scope.IDLE = "idle";
    scope.ANIMATED = "animated";
    scope.state = scope.LOADING;

    scope.data = data;

    // sort countries by id
    data.countries_by_id = {};
    for (var i = 0; i < data.countries.length; i++) {
        var l = data.countries[i];
        data.countries_by_id[ l.country_id ] = l;
    };

    // sort locations by id
    data.locations_by_id = {};
    for (var i = 0; i < data.locations.length; i++) {
        var l = data.locations[i];
        data.locations_by_id[ l.location_id ] = l;
    }
    //--------------------------------------------



/*
 ██████╗ ██████╗ ███╗   ███╗███╗   ███╗███████╗███╗   ██╗████████╗    ████████╗██╗██████╗ 
██╔════╝██╔═══██╗████╗ ████║████╗ ████║██╔════╝████╗  ██║╚══██╔══╝    ╚══██╔══╝██║██╔══██╗
██║     ██║   ██║██╔████╔██║██╔████╔██║█████╗  ██╔██╗ ██║   ██║          ██║   ██║██████╔╝
██║     ██║   ██║██║╚██╔╝██║██║╚██╔╝██║██╔══╝  ██║╚██╗██║   ██║          ██║   ██║██╔═══╝ 
╚██████╗╚██████╔╝██║ ╚═╝ ██║██║ ╚═╝ ██║███████╗██║ ╚████║   ██║          ██║   ██║██║     
 ╚═════╝ ╚═════╝ ╚═╝     ╚═╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═══╝   ╚═╝          ╚═╝   ╚═╝╚═╝     
*/

    // COMMENTARY TIP
    this._PlanetCommentPopup = PlanetCommentPopup( this.main.$container );

    scope.commentToggle = function( _show ){
        if( !scope._PlanetCommentPopup ) return;
        if( _show ) scope._PlanetCommentPopup.showRandom();
        else scope._PlanetCommentPopup.hide();
    }

    this.getLocationBriefs = function( location_id, onComplete ){
        
        var loc = scope.data.locations_by_id[ location_id ];
        var brief_list = loc.brief_list;

        if( brief_list ){
            if(!!brief_list[ PlanetData.YEAR_ID ] !== false)
                onComplete( brief_list[ PlanetData.YEAR_ID ].briefs );
            return;

        }else{

            locationAPI( { location_id: location_id } )
                .done( function( locationData ){
                    brief_list = loc.brief_list = locationData;
                    if(!!brief_list[ PlanetData.YEAR_ID ] !== false)
                        onComplete( brief_list[ PlanetData.YEAR_ID ].briefs );
                } );

        }
        
    }

    // ELEMENTS
    this.drawPoints( radius * 1.1 );
    this.drawParticles( radius );
    this.drawBG();
    this.drawSputniks();
    this.drawOrbitas();



    this.planetLocations = new PlanetLocations( this );
    this.planetPointed = new PlanetPointed( this );
    this.planetContour = new PlanetContour( this );



/*
██╗   ██╗██████╗ ██████╗  █████╗ ████████╗███████╗
██║   ██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝
██║   ██║██████╔╝██║  ██║███████║   ██║   █████╗  
██║   ██║██╔═══╝ ██║  ██║██╔══██║   ██║   ██╔══╝  
╚██████╔╝██║     ██████╔╝██║  ██║   ██║   ███████╗
 ╚═════╝ ╚═╝     ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚══════╝
*/
    
    var camera_dist_to_center;

    this.update = function() {
        
        camera_dist_to_center = camera.position.distanceToSquared( THREE.Vector3.ZERO ) - 100;

        static_container.lookAt( camera.getWorldPosition() );
        scope.static_container.updateMatrix();

        // Rotation of the grid sphere
        this.grid_shpere.rotation.y += .0005;

        // MOVEMENT OF DECOR ORBITS
        if( this.orbits ){
            for (var i = 0; i < this.orbits.length; i++) {
                var orbit = this.orbits[i];
                orbit.rotation.x += orbit._increment.x;
                orbit.rotation.y += orbit._increment.y;
                orbit.rotation.z += orbit._increment.z;
            };
        }

        // Movement of space stations
        if( this.sputniks ){
            for (var i = 0; i < this.sputniks.length; i++) {
                var sputnik = this.sputniks[i];
                sputnik.rotation.y += .0020;
            }
        }
        
        // SPACE JUNK FLOATING AROUND THE PLANET
        if( this.particles ){
            this.particles.rotation.y += .001;
        }

        // PLANET LANDSCAPE MADE OF POINTS
        this.planetPointed.update();
        if( this.updateBg ) this.updateBg();
        
        // Active hexagon update state
        if( active_hexagon ) {
            active_hex_dummy.updateMatrix();
            var pos = active_hex_dummy.getWorldPosition();
            var v1 = pos.clone().project( camera );
            v1.x = (v1.x + 1) / 2 * window.canvasWidth;
            v1.y = -(v1.y - 1) / 2 * window.innerHeight;
            active_hexagon.style.transform = "translate("+ v1.x +"px, "+v1.y+"px)";

            // Deactivate picked hexagons when it moves to the negative side of the planet
            if( !this.isInFrontOfPlanet( active_hex_dummy.position ) ){
                scope.deactivateHexagon();
            }
        }

        if( this._PlanetCommentPopup ) this._PlanetCommentPopup.update();

        if( this.state == this.IDLE && !isMobile.any ) {
            chekHover()
        }

    }



/*
██╗███╗   ██╗████████╗███████╗██████╗  █████╗  ██████╗████████╗██╗██╗   ██╗███████╗
██║████╗  ██║╚══██╔══╝██╔════╝██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██║██║   ██║██╔════╝
██║██╔██╗ ██║   ██║   █████╗  ██████╔╝███████║██║        ██║   ██║██║   ██║█████╗  
██║██║╚██╗██║   ██║   ██╔══╝  ██╔══██╗██╔══██║██║        ██║   ██║╚██╗ ██╔╝██╔══╝  
██║██║ ╚████║   ██║   ███████╗██║  ██║██║  ██║╚██████╗   ██║   ██║ ╚████╔╝ ███████╗
╚═╝╚═╝  ╚═══╝   ╚═╝   ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝   ╚═╝   ╚═╝  ╚═══╝  ╚══════╝
*/
    // INTERACTIVE
    scope.tile_current = null;
    var mouse = new THREE.Vector2(-2,-2);
    var mouse_dir = mouse.clone();PlanetPointed
    
    var mouse_moving_distance = 0;

    var intersect_sphere = new THREE.Sphere( scope.container.position.clone(), radius );
    var raycaster = new THREE.Raycaster();

    DOMElement.addEventListener( 'touchstart', onMouseDown, false );
    DOMElement.addEventListener( 'touchmove', onMouseMove, false );
    DOMElement.addEventListener( 'touchend', onMouseUp, false );

    DOMElement.addEventListener( 'mousedown', onMouseDown, false );
    DOMElement.addEventListener( 'mousemove', onMouseMove, false );
    DOMElement.addEventListener( 'mouseup', onMouseUp, false );

    var mx, my, dx, dy;

    function onMouseDown (e) {

        e.preventDefault();

        if( e.touches ){
            var touch = e.touches[0];
            mx = touch.clientX;
            my = touch.clientY;
        }else{
            mx = e.clientX * ratio;
            my = e.clientY * ratio;
        }

        updateMouse( mx, my );
        mouse_moving_distance = 0;
        mouse_is_down = true;

    }


    function onMouseUp (e) {
        
        mouse_is_down = false;


        if( scope.state != scope.IDLE ) return;

        // is it was a click?
        if( mouse_moving_distance>6 ) return;

        if( isMobile.any ){
            
            checkTapOnObject();

        }
    }

    function onMouseMove (e) {

        e.preventDefault();

        if( e.touches ){
            var touch = e.touches[0];
            mx = touch.clientX;
            my = touch.clientY;
        }else{
            mx = e.clientX * ratio;
            my = e.clientY * ratio;
        }

        updateMouse(mx, my);

    }



    function updateMouse ( mx, my ) {

        dx = Math.abs(mouse.x - mx);
        dy = Math.abs(mouse.y - my);
        mouse_moving_distance += dx*dx + dy*dy; 
        mouse.x = mx;
        mouse.y = my;

        if( isMobile.any){
            mouse_dir.x = (mouse.x / DOMElement.originalSize.width - .5) * 2;
            mouse_dir.y = -(mouse.y / DOMElement.originalSize.height - .5) * 2;
        }else{
            mouse_dir.x = (mouse.x / DOMElement.width - .5) * 2;
            mouse_dir.y = -(mouse.y / DOMElement.height - .5) * 2;
        }
    }



    function chekHover () {
        
        if( scope.state != scope.IDLE) return;

        var intersection, _location_current;

        raycaster.setFromCamera( mouse_dir, camera );     
                
        // intersection with sphere
        intersection = raycaster.ray.intersectSphere( intersect_sphere );
        if( intersection ){
            _location_current = scope.getClosestLocation( intersection );
        }

        if( _location_current ){

            if( _location_current != scope.location_current ){
                activateHexagon( _location_current );
                
                return true;
            }

        }

        return false;
    }



    function checkTapOnObject () {
        var intersection, _location_current;

        raycaster.setFromCamera( mouse_dir, camera );        

        // intersection with sphere
        intersection = raycaster.ray.intersectSphere( intersect_sphere );
        if( intersection ){
            _location_current = scope.getClosestLocation( intersection );
        }

        
        if( _location_current ) {
            activateHexagon( _location_current , true);
        }else{
            scope.deactivateHexagon();
        }
        
    }


/*
██╗  ██╗ ██████╗ ██╗   ██╗███████╗██████╗ ███████╗
██║  ██║██╔═══██╗██║   ██║██╔════╝██╔══██╗██╔════╝
███████║██║   ██║██║   ██║█████╗  ██████╔╝███████╗
██╔══██║██║   ██║╚██╗ ██╔╝██╔══╝  ██╔══██╗╚════██║
██║  ██║╚██████╔╝ ╚████╔╝ ███████╗██║  ██║███████║
╚═╝  ╚═╝ ╚═════╝   ╚═══╝  ╚══════╝╚═╝  ╚═╝╚══════╝
*/
    var location_picked = null;// hexagon_hovered and picked hexagon

 

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