Three.js+React使二维图片呈现3D效果
目录
- 背景
- 效果
- 实现
- 素材制作
- 资源引入
- 场景初始化
- 创建漫画主体
- 创建Boom背景
- 镜头控制、缩放适配、动画
- 总结
背景 逛
sketchfab
网站的时候我看到有很多二维平面转 3D
的模型例子,于是仿照他们的例子,使用 Three.js
+ React
技术栈,将二维漫画图片转化为三维视觉效果。本文包含的内容主要包括:THREE.Group
层级模型、MeshPhongMaterial
高光网格材质、正弦余弦函数
创建模型移动轨迹等。效果 实现效果如下图所示:页面主要有背景图、漫画图片主体以及 Boom 爆炸背景图片构成,按住鼠标左键移动模型可以获得不同视图,让图片在视觉上有 3D 景深效果。
已适配:
PC端
移动端
在线预览:https://dragonir.github.io/3d/#/comic
实现 本文实现比较简单,和我前面几篇文章实现基本上是相同的,流程也比较简单,主要是素材准备流程比较复杂。下面看看具体实现方法。
素材制作
准备一张自己喜欢的图片作为素材原图,图片内容最好可以分成多个层级,以实现
3D
景深效果,本实例中使用的是一张漫画图片,刚好可以切分成多个层级。文章图片
在 Photoshop 中打开图片,根据自己需要的分层数量,创建若干图层,并将地图复制到每个图层上,然后根据对图层景深层级的划分,编辑每个图层,结合使用魔棒工具和套索工具删除多余的部分,然后将每个图层单独导出作为素材。我分为如上 7 个图层,外加一个边框,一共有 8 个图层。
文章图片
资源引入
其中
OrbitControls
用于镜头轨道控制、TWEEN
用于镜头补间动画。import React from 'react'; import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
场景初始化
初始化渲染容器、场景、摄像机、光源。摄像机初始位置设置为位于偏左方的
(-12, 0, 0)
,以便于后面使用 TWEEN
实现翻转动画效果。// 场景container = document.getElementById('container'); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); container.appendChild(renderer.domElement); scene = new THREE.Scene(); // 添加背景图片scene.background = new THREE.TextureLoader().load(background); // 相机camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(-12, 0, 0); camera.lookAt(new THREE.Vector3(0, 0, 0)); // 直射光light = new THREE.DirectionalLight(0xffffff, 1); light.intensity = .2; light.position.set(10, 10, 30); light.castShadow = true; light.shadow.mapSize.width = 512 * 12; light.shadow.mapSize.height = 512 * 12; light.shadow.camera.top = 100; light.shadow.camera.bottom = - 50; light.shadow.camera.left = - 50; light.shadow.camera.right = 100; scene.add(light); // 环境光ambientLight = new THREE.AmbientLight(0xdddddd); scene.add(ambientLight);
创建漫画主体
首先创建一个
Group
,用于添加图层网格,然后遍历图层背景图片数组,在循环体中创建每个面的网格,该网格使用平面立方体 PlaneGeometry
,材质使用物理材质 MeshPhysicalMaterial
,对每个网格位置设置相同的x轴和y轴值和不同的z轴值以创建景深效果。最后将 Group
添加到场景 Scene
中。var layerGroup = new THREE.Group(); let aspect = 18; for (let i=0; i
到这一步,实现效果如下图所示:
THREE.Group 层级模型
将具有相同主体的网格可以通过Group
合并在一起,以便于提高运行效率。Three.js
层级模型Group
的基类是Object3D
,它是Three.js
中大部分对象的基类,提供了一系列的属性和方法来对三维空间中的物体进行操纵。如可以通过.add(object)
方法来将对象进行组合,该方法将对象添加为子对象。
但最好使用Group
来作为父对象,因为Group
相比较Object3D
更语义化,可以使用Group
作为点、线、网格等模型的父对象,用来构建一个层级模型。
创建Boom背景
为了加强视觉效果,我添加了一个Boom 爆炸图形平面作为背景,用鼠标移动的时候随着光线的变化,可以看到该图案有金属渐变效果,这种效果主要是通过高光材质MeshPhongMaterial
的specular
和shininess
属性实现的。
文章图片
const boom = new THREE.Mesh(new THREE.PlaneGeometry(36.76, 27.05), new THREE.MeshPhongMaterial({map: new THREE.TextureLoader().load(boomImage),transparent: true,shininess: 160,specular: new THREE.Color(0xff6d00),opacity: .7})); boom.scale.set(.8, .8, .8); boom.position.set(0, 0, -3); layerGroup.add(boom)scene.add(layerGroup);
添加后效果:
文章图片
MeshPhongMaterial 高光网格材质
MeshPhongMaterial
是一种用于具有镜面高光的光泽表面的材质。该材质使用非物理的Blinn-Phong
模型来计算反射率。与MeshLambertMaterial
中使用的Lambertian
模型不同,该材质可以模拟具有镜面高光的光泽表面,如涂漆木材。
构造函数:
MeshPhongMaterial(parameters: Object)
parameters
:可选,用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material
继承的任何属性)。
特殊属性:
使用
.emissive[Color]
:材质的放射光颜色,基本上是不受其他光照影响的固有颜色。默认为黑色
。.emissiveMap[Texture]
:设置发光贴图。默认值为null
。放射贴图颜色由放射颜色和强度所调节。.emissiveIntensity[Float]
:放射光强度。调节发光颜色。默认为1
。.envMap[TextureCube]
:环境贴图。默认值为null
。.isMeshPhongMaterial[Boolean]
:用于检查此类或派生类是否为Phong
网格材质。默认值为true
。.lightMap[Texture]
:光照贴图。默认值为null
。.lightMapIntensity[Float]
:烘焙光的强度。默认值为1
。.reflectivity[Float]
:环境贴图对表面的影响程度。默认值为1
,有效范围介于0(无反射)
和1(完全反射)
之间。.refractionRatio[Float]
:空气的折射率除以材质的折射率。折射率不应超过1
。默认值为0.98
。.shininess[Float]
:.specular
高亮的程度,越高的值越闪亮。默认值为30
。.skinning[Boolean]
:材质是否使用蒙皮。默认值为false
。.specular[Color]
:材质的高光颜色。默认值为0x111111
的颜色Color
。这定义了材质的光泽度和光泽的颜色。.specularMap[Texture]
:镜面反射贴图值会影响镜面高光以及环境贴图对表面的影响程度。默认值为null
。Phong
着色模型计算着色时,会计算每个像素的阴影,与MeshLambertMaterial
使用的Gouraud
模型相比,该模型的结果更准确,但代价是牺牲一些性能。
镜头控制、缩放适配、动画
镜头补间动画,镜头切换到正确位置。
Animations.animateCamera(camera, controls, { x: 0, y: 0, z: 20 }, { x: 0, y: 0, z: 0 }, 3600, () => { });
镜头控制,本示例中显示了模型平移以及水平垂直旋转的角度,以达到最好的预览效果。
controls = new OrbitControls(camera, renderer.domElement); controls.target.set(0, 0, 0); controls.enableDamping = true; controls.enablePan = false; // 垂直旋转角度限制controls.minPolarAngle = 1.2; controls.maxPolarAngle = 1.8; // 水平旋转角度限制controls.minAzimuthAngle = -.6; controls.maxAzimuthAngle = .6;
屏幕缩放适配。
window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }, false);
对于会话框图层网格,我给它添加了在一条光滑曲线上左右移动的动画效果,主要是通过修改它在x
轴和y
轴上的position
来实现的 。
function animate() {requestAnimationFrame(animate); renderer.render(scene, camera); controls && controls.update(); TWEEN && TWEEN.update(); // 会话框摆动动画step += 0.01; animateLayer.position.x = 2.4 + Math.cos(step); animateLayer.position.y = .4 + Math.abs(Math.sin(step)); }
正弦余弦函数创建模型移动轨迹
使用step
变量并在函数Math.cos()
和Math.sin()
的帮助下 ,创建出一条光滑的轨迹。step+= 0.01
定义的是球的弹跳速度。
到此,本示例的完整实现都描述完毕了,大家感兴趣的话,可以动手试着把自己喜欢的图片改造成3D
视图。拜托,使用Three.js
这样展示图片超酷的好吗!
完整代码:https://github.com/dragonir/3d/tree/master/src/containers/Comic
总结 本文知识点主要包含的的新知识:
THREE.Group
层级模型
MeshPhongMaterial
高光网格材质
正弦余弦函数
创建模型移动轨迹
【Three.js+React使二维图片呈现3D效果】以上就是Three.js+React使二维图片呈现3D效果的详细内容,更多关于Three.js React图片3D效果的资料请关注脚本之家其它相关文章!
推荐阅读
- springcloud使用profile实现多环境配置方式
- 基于Three.js制作一个3D中国地图
- 使用Three.js制作一个3D奖牌页面
- 使用Docker镜像构建Go应用的实现方法
- 使用Three.js实现神奇的3D文字悬浮效果
- AliOS|新一代嵌入式UI框架 HaaS UI 使用JS在嵌入式开发炫酷前端
- AliOS|开源社区第一步 使用 Pull Request 向 git 仓库贡献代码
- 教你如何使用Python破解WIFI密码
- #|JWT——概念、认证流程、结构、使用JWT
- 图解大数据|图解大数据 | 综合案例-使用Spark分析挖掘音乐专辑数据