react实现js控制样式(React + Threejs + Swiper 实现全景图效果的完整代码)
react实现js控制样式
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> <li 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> <li id='panoramic-canvas-container'> <canvas id='panoramic-canvas'></canvas> </li> </li> </Layout> ); } }
到此这篇关于React + Threejs + Swiper 实现全景图效果的完整代码的文章就介绍到这了,更多相关React全景图内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
- react的基本知识(React中refs的一些常见用法汇总)
- react组件的参数怎样定义的(详解React中组件之间通信的方式)
- react常见问题(React编程中需要注意的两个错误)
- react动态创建菜单并实现局部刷新(使用react-virtualized实现图片动态高度长列表的问题)
- react native web白屏(关于React Native 无法链接模拟器的问题)
- react初学难点(使用react的7个避坑案例小结)
- vscode react插件(基于visual studio code + react 开发环境搭建过程)
- reactredux任务处理进度(一文搞懂redux在react中的初步用法)
- 使用react生命周期的常见情况(react+ts实现简单jira项目的最佳实践记录)
- react 封装下拉选择框(React鼠标多选功能的配置方法)
- react循环有几种方法(React forwardRef的使用方法及注意点)
- react中state的作用是什么(React中useEffect 与 useLayoutEffect的区别)
- reacthooks用法(详解React Hooks是如何工作的)
- react配置上下文路由(React中Portals与错误边界处理实现)
- react表单组件怎么写(react antd实现动态增减表单)
- yii2对比springboot(yii2.0框架使用 beforeAction 防非法登陆的方法分析)
- 《寄生虫》 三观不正 人类悲欢从来不相通,感同身受也并非本能(寄生虫三观不正)
- 这部动漫中的女孩子,可比101女孩更加励志(这部动漫中的女孩子)
- 《白狐的人生》热拍 贾征宇偶像包袱难自弃 图(白狐的人生热拍)
- 七夕取消了,牛郎织女没做核酸七夕已经取消(牛郎织女没做核酸七夕已经取消)
- 网友抵制 多地取消 夏日祭 为何惹众怒(网友抵制多地取消)
- 兄弟萌,今年的七夕又取消了 思考 思考(今年的七夕又取消了)
热门推荐
- mysqljoin语句用法(MySQL的join buffer原理)
- vue3 ref 的用法(Vue3中watchEffect的用途浅析)
- mac鼠标怎么实现触摸板功能(鼠标滚轮事件和Mac触控板双指事件)
- jquery无缝滚动代码(jQuery实现表格行数据滚动效果)
- mysql必背知识点高级(MySQL 8.0 Online DDL快速加列的相关总结)
- HTML5 播放 RTSP 视频的实例代码(HTML5 播放 RTSP 视频的实例代码)
- laravel自定义命令(laravel-admin select框默认选中的方法)
- html 设置canvas的背景图可缩放(浅析canvas元素的html尺寸和css尺寸对元素视觉的影响)
- 腾讯云服务器如何安装宝塔面板(腾讯云服务器打开宝塔面板失败是怎么回事?)
- 腾讯云服务器操作系统怎么选(如何选择腾讯云服务器配置?)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9