ThreeJS

简单的全景

LEWPano = function(domElement){
    // init renderer
    this.domElement = domElement;
    this.canvasWidth = domElement.clientWidth;
    this.canvasHeight = domElement.clientHeight;

    this.renderer = new THREE.WebGLRenderer();
    this.renderer.setPixelRatio( window.devicePixelRatio );
    this.renderer.setSize(this.canvasWidth, this.canvasHeight);
    this.renderer.setClearColor( new THREE.Color( 0xffffff ) );
    this.domElement.appendChild( this.renderer.domElement );

    // scene
    this.scene = new THREE.Scene();
    this.scene.fog = new THREE.FogExp2( 0xffffff, 0.0005 );

    // camera
    var sphereRadius = 1000;
    this.camera = new THREE.PerspectiveCamera(60, this.canvasWidth / this.canvasHeight, 1, sphereRadius*2 );
    this.camera.position.set(0, 0, 0);
    this.scene.add(this.camera);

    // 球模型
    var mesh = this.createSphereScene("./image.png");
    this.scene.add(mesh);

    // 漫反射光线
    var light = new THREE.AmbientLight( 0x666666 );
    this.scene.add( light );

    // 开始渲染
    this.render();
}

LEWPano.prototype = {
    createSphereScene : function(image){
        var geometry = new THREE.SphereGeometry( this.sphereRadius, 60, 40 );
        geometry.scale( - 1, 1, 1 );
        var loader = new THREE.TextureLoader();
        var texture = loader.load(image);
        var material = new THREE.MeshBasicMaterial( {
            map: texture,
        } );
        var sphereMesh = new THREE.Mesh( geometry, material );
        sphereMesh.name = "NTESPano_SphereWorld"
        return sphereMesh;
    },
    render : function(timestamp) {
        window.requestAnimationFrame( this.render.bind(this) );

        // do some thing...
    }
}

世界坐标转换屏幕坐标系

var world_vector = new THREE.Vector3(500,0,0);
var vector = world_vector.project(camera);
// console.log(vector);
var halfWidth = container.clientWidth / 2;
var halfHeight = container.clientHeight / 2;

var result = {
 x: Math.round(vector.x * halfWidth + halfWidth),
 y: Math.round(-vector.y * halfHeight + halfHeight),
 inside : (vector.z > 0 && vector.z < 1)? true:false
};

转换后 vector 中 z 的值在 0-1 之间表示该坐标在相机视野内,其他值标识超出相机视野。

事件检测

var mouse;
mouse.x = ( event.offsetX / _domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.offsetY / _domElement.clientHeight ) * 2 + 1;

var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera );
var intersects = raycaster.intersectObject( mesh );
if (intersects.length > 0) {
    var selected = intersects[ 0 ]
    var point = selected.point;
}

加载 json 模型

var jsonLoader = new THREE.JSONLoader();
var mixer = null;
jsonLoader.load('images/json/huiji.js', function(geometry, materials) {
    // var material = new THREE.MeshFaceMaterial(materials);

    var originalMaterial = materials[ 0 ];
    originalMaterial.skinning = true;
    var mesh = new THREE.SkinnedMesh( geometry, originalMaterial );
    mesh.position.set( 5, 0, 0 );
    mesh.scale.set(5, 5, 5);
    scene.add(mesh);

    mixer = new THREE.AnimationMixer( mesh );
    var sceneAnimationClip = geometry.animations[0];
    var anima = mixer.clipAction( sceneAnimationClip );
    anima.play();
});

function render(){
    // 在渲染方法中更新动画
    var delta = clock.getDelta();
    if( mixer ) {
        mixer.update(delta);
    }

    this.renderer.clear();
}