前言
废话不多说,先上一波炫酷前端效果展示,点我去欣赏。最近有个任务,刚搞完一个卡通网 kt5.cn,没有一点点流量。 如何为卡通网带来点人气呢? ,于是就有了这篇《Three.js 制作 3D 动漫角色欣赏篇》,顺便想带旺一下给卡通网。
一、与卡通相关又与前端相关的主题及制作思路
突发奇想,要不针对一些 3d 动漫的角色,搞个展示 show 的页面吧:
-
- 3D 模型哪里来? ,当然是去大名鼎鼎的
- 3d warehouse(https://3dwarehouse.sketchup.com/),大品牌,放心;谷歌出品、必是精品;
- 如何把 3d 模型展示出来了,当然是选择来自 未来前端技术 的 Three.js,支持多种
- 3D 模型的加载,敲定 AR/VR 不在话下;
- 二话不说下载 3D 模型撸代码开干。
二、Three.js加载 3D 模型代码一般思路
Three.js 的代码经典思路:
- 创建一个场景
Scene
- 给场景加个相机
Camera
- 创建一个渲染器
Renderer
- 把 3D 模型加载进来,添加到场景
- 渲染循环(动画)。如果 3D 模型自带动画就直接播放其动画、不然后就自己添加平移 / 缩放 / 旋转等效果动画
三、源码及关键注释
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>3D 动漫角色欣赏 : Centaur-Vert</title>
<meta
content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"
name="viewport"
/>
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="black" name="apple-mobile-web-app-status-bar-style" />
<meta content="telephone=no" name="format-detection" />
<meta content="email=no" name="format-detection" />
<link type="text/css" rel="stylesheet" href="main.css" />
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#percent {
color: #fff;
position: absolute;
top: 10px;
right: 0;
width: 400px;
text-align: center;
z-index: 100;
display: block;
font-size: 20px;
font-weight: 700;
letter-spacing: 3px;
}
</style>
</head>
<body>
<div id="percent">0%</div>
<div id="container"></div>
<div id="info"></div>
<script src="https://threejs.org/build/three.js"></script><!-- 引入Three.js -->
<script src="./js/libs/stats.min.js"></script><!-- 可选:引入Three.js的渲染统计统计器 -->
<script src="./js/loaders/ColladaLoader.js"></script><!-- 引入Three.js的针对Collada文件(.dae后缀)的异步加载器,你可以理解为ajax相似的东西 -->
<script src="./js/controls/OrbitControls.js"></script><!-- 引入Three.js的模型控制器插件,用于绑定鼠标/触模操控3d模型 -->
<script>
var container, stats, clock, controls
var camera, scene, renderer, mixer, avatar
var loadingEl = document.getElementById('percent')
init()
animate()
function init() {
container = document.getElementById('container')
// 创建一个透视相机Camera
camera = new THREE.PerspectiveCamera(
25,
window.innerWidth / window.innerHeight,
1,
1000
)
camera.position.set(0, 10, 20)
scene = new THREE.Scene()
// 使用THREE.Clock来启动一个计时器
clock = new THREE.Clock()
// 加载collada 3d模型
var loader = new THREE.ColladaLoader()
loader.load(
'./models/centaur-vert/model.dae',
function(collada) {
loadingEl.remove()
var animations = collada.animations
avatar = collada.scene
// 加载完之后按需调整一下3D模型的比例
avatar.scale.x = 0.0025
avatar.scale.y = 0.0025
avatar.scale.z = 0.0025
// console.log(avatar)
avatar.traverse(function(node) {
if (node.isSkinnedMesh) { // 有皮肤就不进行视锥采集
node.frustumCulled = false
}
})
if (animations.length > 0) {
// 如果有动画就播放动画
mixer = new THREE.AnimationMixer(avatar)
mixer.clipAction(animations[0]).play()
}
scene.add(avatar) // 添加把3D模型添加到场景
},
function(event) { // 添加加载进度展示
loadingEl.innerHTML =
'3D模型加载进度:' +
(((event.loaded * 100) / event.total) | 0) +
'% <br>操作方式:鼠标 + 加上下左右键'
}
)
// 添加网格
var gridHelper = new THREE.GridHelper(10, 20)
scene.add(gridHelper)
// 添加灯光(环境光源,白光)
var ambientLight = new THREE.AmbientLight(0xffffff, 0.2)
scene.add(ambientLight)
// 添加灯光(点光源,白光)
var pointLight = new THREE.PointLight(0xffffff, 0.8)
scene.add(camera)
camera.add(pointLight)
// 创建渲染器
renderer = new THREE.WebGLRenderer({ antialias: true }) // 抗锯齿
renderer.setPixelRatio(window.devicePixelRatio) // 设置dpr
renderer.setSize(window.innerWidth, window.innerHeight) // 设置比率
container.appendChild(renderer.domElement)
// 绑定鼠标/触屏操控事件
controls = new THREE.OrbitControls(camera, renderer.domElement)
controls.screenSpacePanning = true
controls.minDistance = 5
controls.maxDistance = 40
controls.target.set(0, 2, 0)
controls.update()
// 添加左上角的渲染统计
stats = new Stats()
container.appendChild(stats.dom)
// 监控屏幕大小变化事件
window.addEventListener('resize', onWindowResize, false)
}
function onWindowResize() { // 监控屏幕大小变化进行适配渲染
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
// 动画代码,绕z轴旋转
function animate() {
avatar && avatar.rotation && (avatar.rotation.z += 0.005)
requestAnimationFrame(animate)
render()
stats.update()
}
function render() {
var delta = clock.getDelta()
if (mixer !== undefined) {
mixer.update(delta)
}
renderer.render(scene, camera)
}
</script>
</body>
</html>
<script></script>
参考引用
1: https://threejs.org/
2: https://github.com/mrdoob/three.js/
本文同步发布于:https://blog.csdn.net/u012609766/article/details/100771979#_6