How to show 360 images in the react native

时间:2018-02-03 07:35:03

标签: react-native

How can I show 360 images or video in the android apps. My react native version is 51

4 个答案:

答案 0 :(得分:2)

如果您使用的是Expo,则可以将expo-3与GLView结合使用以模拟全景视图(与本机360图片查看器应用程序不完全相同,但相似)。
您可以在这里找到全景等距照片示例的原始three.js源代码-https://github.com/mrdoob/three.js/blob/master/examples/webgl_panorama_equirectangular.html

我做了这种实验,并使以下代码起作用。

import React from 'react';
import NativeTachyons from 'react-native-style-tachyons';
import { GLView } from 'expo';
import ExpoTHREE, { THREE } from 'expo-three';
import PinchZoomResponder from 'react-native-pinch-zoom-responder';

THREE.suppressExpoWarnings(true);

@NativeTachyons.wrap
export default class PhotoView360 extends React.Component {
  constructor(props) {
    super(props);
    this.lat = 0;
    this.lon = 0;
    this.latOnTap = 0;
    this.lonOnTap = 0;
    this.locationXStart = null;

    this._panResponder = new PinchZoomResponder({
      onPinchZoomStart: e => {
        this.cameraFov = this.camera.fov;
      },
      onResponderMove: (e, gestureState) => {
        if (gestureState) {
          const { scaleX, scaleY } = gestureState;
          const scale = Math.sqrt(scaleX * scaleX + scaleY * scaleY);
          const fov = this.cameraFov / Math.max(0, scale - 0.4);
          this.camera.fov = THREE.Math.clamp(fov, 10, 75);
          this.camera.updateProjectionMatrix();
        }
      }
    });
    const { onResponderGrant, onResponderMove, onResponderRelease } = this._panResponder.handlers;
    this._panResponder.handlers.onResponderGrant = e => {
      if (e.nativeEvent.touches.length === 1) {
        this.latOnTap = this.lat;
        this.lonOnTap = this.lon;
        this.locationXStart = e.nativeEvent.touches[0].locationX;
        this.locationYStart = e.nativeEvent.touches[0].locationY;
      } else {
        onResponderGrant(e);
      }
    };
    this._panResponder.handlers.onResponderMove = e => {
      if (e.nativeEvent.touches.length === 1) {
        if (this.locationXStart !== null) {
          const factor = this.camera.fov / 75 * 0.1;
          this.lon = this.lonOnTap - (e.nativeEvent.touches[0].locationX - this.locationXStart) * factor;
          this.lat = this.latOnTap + (e.nativeEvent.touches[0].locationY - this.locationYStart) * factor;
        }
      } else {
        onResponderMove(e);
      }
    };
    this._panResponder.handlers.onResponderRelease = e => {
      this.locationXStart = null;
      onResponderRelease(e);
    };
  }

  render() {
    return pug`
      GLView.flx-i(
        ...this._panResponder.handlers
        onContextCreate=${async gl => {
          const scene = new THREE.Scene();
          const renderer = new ExpoTHREE.Renderer({ gl });
          const geometry = new THREE.SphereBufferGeometry(500, 60, 40);
          const material = new THREE.MeshBasicMaterial({
            map: await ExpoTHREE.loadTextureAsync({ asset: this.props.assetUri })
          });
          const mesh = new THREE.Mesh(geometry, material);
          renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
          geometry.scale(1, 1, -1);
          scene.add(mesh);
          this.camera = new THREE.PerspectiveCamera(
            75,
            gl.drawingBufferWidth / gl.drawingBufferHeight,
            1,
            1100
          );
          this.camera.target = new THREE.Vector3(0, 0, 0);
          let phi = 0;
          let theta = 0;
          const animate = () => {
            requestAnimationFrame(animate);
            this.lat = Math.max(-85, Math.min(85, this.lat));
            phi = THREE.Math.degToRad(90 - this.lat);
            theta = THREE.Math.degToRad(this.lon);
            this.camera.target.x = 500 * Math.sin(phi) * Math.cos(theta);
            this.camera.target.y = 500 * Math.cos(phi);
            this.camera.target.z = 500 * Math.sin(phi) * Math.sin(theta);
            this.camera.lookAt(this.camera.target);
            renderer.render(scene, this.camera);
            gl.endFrameEXP();
          }
          animate();
        }}
      )
    `;
  }
}

随时在评论中提问。

答案 1 :(得分:1)

You can use react-native-360. A React Native wrapper for Google VR Cardboard SDK for 360 images in react native.

Panorama Example

import { PanoramaView } from 'react-native-360';
<PanoramaView 
    style={{height:200,width:width}}
    image={require('./andes.jpg')}
    displayMode={'embedded'}
    enableFullscreenButton
    enableCardboardButton
    enableTouchTracking
    hidesTransitionView
    enableInfoButton={false}              
/>

The Android wrapper is still in progress, stay tuned

答案 2 :(得分:0)

在iOS上使用react-native-gvr,在android上使用react-native-gvr-video-android

答案 3 :(得分:-1)

Please read this :

https://facebook.github.io/react-vr/docs/pano.html

Panos are images projected onto a sphere that fully surrounds the viewer. These are a core image format for VR applications. You can create 360 photos by using special 360 camera hardware. These will be usually in the form of Equirectangular images covering full 360° horizontal and 180° vertical angles.