您好,登錄后才能下訂單哦!
這篇“React+Threejs+Swiper如何實現全景圖效果”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“React+Threejs+Swiper如何實現全景圖效果”文章吧。
??有了上面的提示,對 threejs 有一點了解的小伙伴可能就猜出來了,這個全景效果其實就是使用一個球體實現的~ 而我們只是在球體內表面上貼了一張紋理貼圖而已(滾輪向外滾就可以看到這個球體了,看上去像個玻璃球,怪好看的,還有個彩蛋?(好吧,說出來就不是彩蛋了)):
??初始時,我們的視角在球體正中心,視角的移動則是依靠 threejs 提供的工具 OrbitControls
來控制。
??那么創建這個球體的代碼如下:
const geometry = new THREE.SphereBufferGeometry(500, 32, 32); geometry.scale(-1, 1, 1); // 將紋理反貼 const material = new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(imglist[0].default) // 傳入圖片的URL或者路徑,也可以是 Data URI. }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); const controls = new OrbitControls(camera, renderer.domElement); controls.enablePan = false; controls.maxDistance = 1000;
不知道 Data URI 是什么的可以看看 MDN 文檔
??輪播圖實現則是使用 swiper 這個庫,使用起來非常方便,具體可自行查閱文檔。
??在滑動輪播圖時,會觸發一個 onSliderChange
事件,這個事件傳入當前的 swiper
作為參數,我們就可以通過當前激活的元素來獲取圖片并替換球體的紋理貼圖了:
onSliderChange = curSwiper => { const mesh = this.mesh; const texture = imglist[curSwiper.activeIndex].default; mesh.material.map = new THREE.TextureLoader().load(texture); };
??下面是我的 swiper 設置,其中 SwiperSlider 是一個可滑動的輪播圖卡片,EffectCoverflow 是滑動時觸發的效果,swiper 中提供了四種可選效果:Fade、Coverflow、Flip 以及 Cube。imglist
則是一組圖片,其中 imglist[i].default
屬性保存了圖片的 base64 編碼。
import { Swiper, SwiperSlide } from 'swiper/react'; import SwiperCore, { EffectCoverflow } from 'swiper'; import 'swiper/swiper.min.css'; import 'swiper/components/effect-coverflow/effect-coverflow.min.css'; SwiperCore.use([EffectCoverflow]); //.... <Swiper className='panoramic-imgs' spaceBetween={50} // 間距 slidesPerView={3} // 輪播圖里可預覽圖片數 onSlideChange={this.onSliderChange} // 滑動時觸發的回調 onSwiper={(swiper) => console.log(swiper)} // 初始加載時觸發的回調 direction='vertical' // 輪播圖方向,默認是水平 horizontal effect={'coverflow'} // 滑動效果 grabCursor={true} // 鼠標放在輪播圖上是否顯示拖拽 centeredSlides={true} // 當前處于激活狀態的圖片是否要居中 coverflowEffect={{ // coverflow 效果參數設置,可自行調整 "rotate": 50, "stretch": 0, "depth": 100, "modifier": 1, "slideShadows": true }} { imglist.map((img, idx) => { return <SwiperSlide key={idx}> <img src={img.default} className='panoramic-img'></img> </SwiperSlide> }) } </Swiper>
??全景效果的實現就說到這了,當然,如果什么地方有疑問可以留言或者參考我的代碼(下面貼出來),只要對 threejs 和 react 有一定了解的同學我相信實現這么一個效果并不難,代碼量也很小~
完整代碼
import React, { Component } from 'react'; import Layout from '@theme/Layout'; import Head from '@docusaurus/Head'; import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; import * as _ from 'underscore'; import { message } from 'antd'; import { Swiper, SwiperSlide } from 'swiper/react'; import SwiperCore, { EffectCoverflow } from 'swiper'; import 'swiper/swiper.min.css'; import 'swiper/components/effect-coverflow/effect-coverflow.min.css'; import './index.css'; import imgs from './imgs.json'; SwiperCore.use([EffectCoverflow]); const imglist = imgs.map(img => { return require('../../../static/img/panoramic/' + img.name); }); export default class Panormatic extends Component { constructor() { super(); this.renderer = null; this.camera = null; this.scene = null; this.container = null; this.controls = null; this.showMessage = true; // 彩蛋提示 } componentDidMount() { const container = document.getElementById('panoramic-canvas-container'); const canvas = document.getElementById('panoramic-canvas'); const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }); renderer.setClearColor(0xffffff); // b2e0df 綠豆沙色 renderer.setPixelRatio( window.devicePixelRatio ); const height = container.clientHeight; const width = container.clientWidth; renderer.setSize(width, height); const camera = new THREE.PerspectiveCamera(60, width / height, 1, 30000); camera.position.set(0, 0, 1); camera.center = new THREE.Vector3(0, 0, 0); const scene = new THREE.Scene(); const geometry = new THREE.SphereBufferGeometry(500, 32, 32); geometry.scale(-1, 1, 1); // 將紋理反貼 const material = new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(imglist[0].default) }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); const controls = new OrbitControls(camera, renderer.domElement); // controls.enableZoom = false; controls.enablePan = false; controls.maxDistance = 1000; this.renderer = renderer; this.camera = camera; this.scene = scene; this.container = container; this.controls = controls; this.mesh = mesh; // 設置提示框的全局配置 message.config({ top: 100, duration: 3.5, maxCount: 1, }); this.onControlsChange = _.throttle(this.onChange, 100); controls.addEventListener('change', this.onControlsChange); window.addEventListener('resize', this.onWindowResize); this.renderLoop(); } componentWillUnmount() { const mesh = this.mesh; mesh.material.dispose(); mesh.geometry.dispose(); this.scene.remove(mesh); window.removeEventListener('resize', this.onWindowResize); this.controls.removeEventListener('change', this.onControlsChange); message.destroy(); } onChange = (e) => { const camera = this.camera; if (camera.position.distanceTo(camera.center) >= 700) { if (this.showMessage) { message.success('?恭喜你發現了全景效果的小秘密~?'); this.showMessage = false; } } else { this.showMessage = true; } } onSliderChange = (curSwiper) => { const mesh = this.mesh; const texture = imglist[curSwiper.activeIndex].default; mesh.material.map = new THREE.TextureLoader().load(texture); }; onWindowResize = () => { const camera = this.camera; const renderer = this.renderer; const width = this.container.clientWidth; const height = this.container.clientHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); }; renderLoop = () => { this.renderer.render(this.scene, this.camera); requestAnimationFrame(this.renderLoop); }; render() { return ( <Layout> <Head> <title>全景圖 | Yle</title> </Head> <div id='panoramic-container'> <Swiper className='panoramic-imgs' spaceBetween={50} slidesPerView={3} onSlideChange={this.onSliderChange} onSwiper={(swiper) => console.log(swiper)} direction='vertical' effect={'coverflow'} grabCursor={true} centeredSlides={true} coverflowEffect={{ "rotate": 50, "stretch": 0, "depth": 100, "modifier": 1, "slideShadows": true }} > { imglist.map((img, idx) => { return <SwiperSlide key={idx}> <img src={img.default} className='panoramic-img'></img> </SwiperSlide> }) } </Swiper> <div id='panoramic-canvas-container'> <canvas id='panoramic-canvas'></canvas> </div> </div> </Layout> ); } }
以上就是關于“React+Threejs+Swiper如何實現全景圖效果”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。