直接上代码

CameraControls.js相机控制器

import * as THREE from 'three';function CameraControls(object, domElement, cb, update) {this.object = object;this.domElement = domElement !== undefined ? domElement : document;this.enabled = true;this.lookSpeed = 0.1;this.activeLook = true;this.cameraFov = object.fov;this.minPolarAngle = 0; // radiansthis.maxPolarAngle = Math.PI; // radiansthis.minAzimuthAngle = -Infinity; // radiansthis.maxAzimuthAngle = Infinity; // radiansconst lookDirection = new THREE.Vector3();const target = new THREE.Vector3();const near = 40; //最小范围const far = object.fov; //最大范围// 只要无状态和旋转的两个状态。const STATE = {NONE: -1,ROTATE: 0,};let state = STATE.NONE;const rotateStart = new THREE.Vector2();const rotateEnd = new THREE.Vector2();const rotateDelta = new THREE.Vector2();const spherical = new THREE.Spherical();const sphericalDelta = new THREE.Spherical(); // 球面function rotateLeft(angle) {sphericalDelta.theta -= angle;}function rotateUp(angle) {sphericalDelta.phi += angle;}this.handleMouseDownRotate = function (event) {rotateStart.set(event.clientX, event.clientY);};this.handleMouseMoveRotate = function (event) {rotateEnd.set(event.clientX, event.clientY);rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(this.lookSpeed);const element = this.domElement === document ? this.domElement.body : this.domElement;rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, heightrotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight);rotateStart.copy(rotateEnd);if (cb) cb();this.update();};//鼠标按下执行的事件this.onMouseDown = function (event) {if (this.enabled === false) return;event.preventDefault();event.stopPropagation();if (this.domElement !== document) {this.domElement.focus();} else {window.focus();}if (this.activeLook && event.button === 0) {this.handleMouseDownRotate(event);state = STATE.ROTATE;}if (state !== STATE.NONE) {document.addEventListener('mousemove', _onMouseMove, false);document.addEventListener('mouseup', _onMouseUp, false);}};this.onMouseUp = function (event) {if (this.enabled === false) return;event.preventDefault();event.stopPropagation();document.removeEventListener('mousemove', _onMouseMove, false);document.removeEventListener('mouseup', _onMouseUp, false);state = STATE.NONE;};this.onMouseMove = function (event) {if (this.enabled === false) return;event.preventDefault();event.stopPropagation();if (state === STATE.ROTATE) {this.handleMouseMoveRotate(event);}};this.onMouseWheel = function (event) {if (this.enabled === false) return;event.preventDefault();event.stopPropagation();if (event.wheelDelta) {if (event.wheelDelta < 0) {this.cameraFov -= near < this.cameraFov ? 2 : 0;}if (event.wheelDelta > 0) {this.cameraFov += this.cameraFov < far ? 2 : 0;}} else if (event.detail) {if (event.detail < 0) {this.cameraFov -= near < this.cameraFov ? 2 : 0;}if (event.detail > 0) {this.cameraFov += this.cameraFov < far ? 2 : 0;}}this.object.fov = this.cameraFov;this.object.updateProjectionMatrix();};this.lookAt = function (x, y, z) {if (x.isVector3) {target.copy(x);} else {target.set(x, y, z);}this.object.lookAt(target);setOrientation(this);return this;};this.update = (function () {const targetPosition = new THREE.Vector3();return function update() {if (this.enabled === false) return;spherical.theta -= sphericalDelta.theta;spherical.phi -= sphericalDelta.phi;spherical.theta = Math.max(this.minAzimuthAngle,Math.min(this.maxAzimuthAngle, spherical.theta));spherical.phi = Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle, spherical.phi));spherical.makeSafe();const { position } = this.object;targetPosition.setFromSphericalCoords(1, spherical.phi, spherical.theta).add(position);this.object.lookAt(targetPosition);this.object.target = targetPosition;sphericalDelta.set(0, 0, 0);return false;};})();function contextmenu(event) {event.preventDefault();}this.dispose = function () {this.domElement.removeEventListener('contextmenu', contextmenu, false);this.domElement.removeEventListener('mousedown', _onMouseDown, false);this.domElement.removeEventListener('mousewheel', _onMouseWheel, false);document.removeEventListener('mousemove', _onMouseMove, false);document.removeEventListener('mouseup', _onMouseUp, false);};const _onMouseMove = bind(this, this.onMouseMove);const _onMouseDown = bind(this, this.onMouseDown);const _onMouseUp = bind(this, this.onMouseUp);const _onMouseWheel = bind(this, this.onMouseWheel);this.domElement.addEventListener('contextmenu', contextmenu, false);this.domElement.addEventListener('mousedown', _onMouseDown, false);this.domElement.addEventListener('mousewheel', _onMouseWheel, false);document.addEventListener('mousemove', _onMouseMove, false);document.addEventListener('mouseup', _onMouseUp, false);function bind(scope, fn) {return function () {fn.apply(scope, arguments);};}function setOrientation(controls) {const { quaternion } = controls.object;lookDirection.set(0, 0, -1).applyQuaternion(quaternion);spherical.setFromVector3(lookDirection);}setOrientation(this);
}THREE.CameraControls = CameraControls;

Player.js 最终导出的api

import * as THREE from 'three';import './CameraControls';class Player {scene = null;camera = null;renderer = null;controls = null;parentDom = null;panoramaMesh = null;clientWidth = 0;clientHeight = 0;cameraFov = 80;T0 = new Date();constructor(config) {const { parentDom, cameraFov } = config;if (cameraFov) {if (cameraFov <= 40) {this.cameraFov = 40;} else if (cameraFov >= 120) {this.cameraFov = 120;} else {this.cameraFov = cameraFov;}} else {this.cameraFov = 80;}this.parentDom = parentDom || document.body;this.clientWidth = this.parentDom.clientWidth;this.clientHeight = this.parentDom.clientHeight;this.init();}init() {this.initScene();this.initRenderer();this.initCamera();this.initLight();this.initControls();this.animate();}initScene() {this.scene = new THREE.Scene();}initControls() {this.controls = new THREE.CameraControls(this.camera,this.renderer.domElement);this.controls.lookSpeed = 0.2; // 鼠标移动查看的速度// this.controls.minPolarAngle = Math.PI / 6; // radians// this.controls.maxPolarAngle = (Math.PI / 6) * 5; // radians}updateFov() {console.log(1);}initCamera() {this.camera = new THREE.PerspectiveCamera(this.cameraFov,this.clientWidth / this.clientHeight,1,10000);this.camera.position.x = 0;this.camera.position.y = 0;this.camera.position.z = 0;}initRenderer() {this.renderer = new THREE.WebGLRenderer();this.renderer.setSize(this.clientWidth, this.clientHeight);this.parentDom.appendChild(this.renderer.domElement);}initLight() {const ambientLight = new THREE.AmbientLight(0xffffff);ambientLight.name = 'ambientLight';const directionalLight = new THREE.DirectionalLight(0xffffff);// 把平行光放在y轴正方向上的无穷远处directionalLight.position.set(0, 1, 0);directionalLight.name = 'directionalLight';// 把平行光加到场景中this.scene.add(ambientLight);this.scene.add(directionalLight);}animate = () => {requestAnimationFrame(this.animate);this.renderer && this.renderer.render(this.scene, this.camera);};createPanorama = imageUrl => {const geometry = new THREE.SphereGeometry(100, 64, 32);geometry.scale(-1, 1, 1);const material = new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(imageUrl), // 加载一整张纹理图片});this.panoramaMesh = new THREE.Mesh(geometry, material);this.scene.add(this.panoramaMesh);};changePanorama = imageUrl => {if (!this.panoramaMesh) {this.createPanorama(imageUrl);return;}this.panoramaMesh.material.map.dispose();this.panoramaMesh.material.dispose();this.panoramaMesh.material.map = new THREE.TextureLoader().load(imageUrl);};clearRenderer = () => {this.renderer.clear();this.renderer.dispose();this.renderer.forceContextLoss();this.renderer.domElement.remove();this.renderer = null;};dispose() {this.controls.dispose();this.clearRenderer();this.scene.children.forEach(c => c.dispose && c.dispose());this.scene.clear();}
}export default Player;

使用方法

//<div id="app"></div>
const parentDom = document.getElementById('app');
const app = new Player({parentDom});
app.createPanorama('https://img.zcool.cn/community/019d425a5c4793a8012113c7dac382.jpg@1280w_1l_2o_100sh.jpg')

效果图

基于threejs,完成一个简单的全景图播放器相关推荐

  1. 一个基于Android开发的简单的音乐播放器

    一个基于Android开发的简单的音乐播放器 记得当时老师让我们写因为播放器时,脑子一头雾水,网上杂七杂八的资料也很少有用,因此索性就自己写一篇,希望对有缘人有用. 因为有好多人问我要源码,所以附上g ...

  2. 如何使用aframe.js构建一个简单的VR播放器

    在当今这个信息化的时代,虚拟现实(VR)已经开始逐渐成为一种新的生活方式.作为一名前端开发工程师,在学习和探索VR技术方面,aframe.js是一个非常有趣和有用的工具.在本文中,我将介绍如何使用af ...

  3. GStreamer 编写一个简单的MP3播放器

    本文介绍如何使用GStreamer 编写一个简单的MP3播放器. 1,需要使用mad解码插件,因此需要先安装gstreamer0.10-plugins-ugly 2,编写mp3播放器 下面来看看如何利 ...

  4. 自制一个简单的音乐播放器

    这两天刚学完了contentprovider和service组件,就综合下所学的,自制了一个简单的音乐播放器. 代码如下: 主activity代码 public class MainActivity ...

  5. 用Qt写一个简单的音乐播放器(三):增加界面(播放跳转与音量控制)

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  6. 用Qt写一个简单的音乐播放器(六):显示歌词(正则表达式)

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  7. 用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐

    一.前言 QMediaplayer可以用于解析音频文件和视频文件,继承自QMediaObject,涉及到的对象为QMediaContent.QMediaObject可以提供关于媒体内容的接入,通过UR ...

  8. 用Qt写一个简单的音乐播放器(五):歌曲播放时间显示

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  9. Android开发做一个简单的音乐播放器

    Android开发如何做一个简单的音乐播放器,首先我们先要知道用到的知识点有哪些. 1.MediaPlayer:可以播放本地资源.sd卡内存资源以及网络uri资源,在这里我们播放sd卡上的音乐资源. ...

最新文章

  1. 人类倾向于高估人工智能的进步,低估自身智能的复杂性-读《AI 3.0》
  2. scratch学习_学习scratch编程能学到什么?对孩子有帮助吗?
  3. 精品软件 推荐 ACPsoft PDF Converter 免费的多功能 PDF 转换器
  4. c语言中post协议,c/c++的http协议的get和post方法
  5. c语言编程 排序,C语言编程-9_3 排序
  6. Notice: Undefined offset 的解决方法
  7. 拓端tecdat|R语言中使用线性模型、回归决策树自动组合特征因子水平
  8. python加法程序结果图片_OpenCV-Python系列之图像上的算术运算
  9. 项目管理系列文章——关于软件工程在软件整个生命周期的位置
  10. SPSS缺失值处理【SPSS 009期】
  11. python结巴分词_Python中文分词工具之结巴分词用法实例总结【经典案例】
  12. kindle导出笔记html,手把手教你导出kindle笔记链接Evernote
  13. 谷歌浏览器安装json-handle插件
  14. vivado布线congestion拥塞
  15. 等比求和模版,下标从1开始
  16. supervisor+cesi多服务器进程集中管理
  17. 高通modem侧新增AT命令
  18. Chrome下载危险文件拦截手动绕过
  19. 算法-数塔问题-c语言
  20. java 线性回归_Java线性回归

热门文章

  1. Linux3._Linux环境基础开发工具使用
  2. 可用于SDR的C语言纠错编码通用算法收集(1)-朴素字典查表BCH纠错
  3. 王者荣耀的服务器是什么系统,王者荣耀健康系统 健康系统是什么
  4. 工商管理专业知识与实务(中级)【6】
  5. Keil5 平台 S3C2440裸机程序开发-----中断系统/UART
  6. 深度学习制作自己的样本
  7. 使用BP网络逼近函数-matlab
  8. 第三方远程控制工具TeamViewer的安装和使用教程,可下载window版和linux版,windows使用虚拟机可以与linux之间通讯
  9. ocx 加载 页面卡死
  10. Python 变量作用域与函数(4)