一、先看看效果

二、实现方法:

实现思路: 先获取当前相机所在位置,在使用tween.js动画将相机位置平滑切换到目标位置点

// 当前相机所在点位置
p1 = {x: camera.position.x,y: camera.position.y,z: camera.position.z,
}
// 相机目标位置点
const p2 = {x:-400, y:520, z:760};
// 使用tween动画
var tween = new TWEEN.Tween(p1).to(p2, 6000).easing(TWEEN.Easing.Quadratic.InOut)
tween.onUpdate(() => {// 修改相机位置camera.position.set(p1.x, p1.y, p1.z)camera.lookAt(0, 0, 0)controls.target.set(0, 0, 0) // 确保镜头移动后,视觉中心还在圆点处controls.update()
})
// 开始动画
tween.start()

在循环中 调用 TWEEN.update()

三、实例代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>动画转场</title><style>body {height: 100vh;overflow: hidden;}.btns-con {position: absolute;left: 0;top: 0;z-index: 99;padding: 20px;color: #fff;}.btns-con span {cursor: pointer;}</style><script src="./lib/three.js"></script><script src="./lib/OrbitControls.js"></script><script src="./lib/Tween.js"></script>
</head>
<body><div class="btns-con"><span onclick="handleClick()">点击专场</span></div>
<script>let scene, camera, renderer, controls, mixer, tubeCurve, AgvCar;let width = window.innerWidth;let height = window.innerHeightlet p1 = {x:400, y:520, z:760};let ratio = {value: 0}function handleClick () {console.log(camera.position);// 当前相机所在点位置p1 = {x: camera.position.x,y: camera.position.y,z: camera.position.z,}// 相机目标位置点const p2 = {x:-400, y:520, z:760};// 使用tween动画var tween = new TWEEN.Tween(p1).to(p2, 6000).easing(TWEEN.Easing.Quadratic.InOut)tween.onUpdate(() => {// 修改相机位置camera.position.set(p1.x, p1.y, p1.z)camera.lookAt(0, 0, 0)controls.target.set(0, 0, 0) // 确保镜头移动后,视觉中心还在圆点处controls.update()})// 开始动画tween.start()}function init () {// 场景scene = new THREE.Scene();let helper = new THREE.AxesHelper(100, 100);scene.add(helper);// 环境光let light = new THREE.AmbientLight(0xadadad); // soft white lightscene.add(light);// 平行光源const directionalLight = new THREE.DirectionalLight(0xffffff, 1);directionalLight.position.set(1000, 1000, 0);scene.add(directionalLight); // 相机camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000)camera.position.copy(p1)scene.add(camera)// 渲染器renderer = new THREE.WebGLRenderer();renderer.setSize(width, height)renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));renderer.setClearColor(new THREE.Color('#32373E'), 1);document.body.appendChild(renderer.domElement);function randWidth (width) {return Math.random() * width + 10;}// 创建地板const planeGeo = new THREE.PlaneGeometry(900, 900);const planeMaterial = new THREE.MeshLambertMaterial({color: new THREE.Color('#040912'),side: THREE.DoubleSide});const planeMesh = new THREE.Mesh(planeGeo, planeMaterial);planeMesh.rotation.x = -Math.PI / 2;scene.add(planeMesh);// 楼宇扫描相关配置数据const flowData = {boxSize: { // 建筑群包围盒的尺寸x: 600,y: 200,z: 600},flowConf: {x: 1, // 开关 1 表示开始y: 20, // 范围z: 60 // 速度},color: "#5588aa",  // 建筑颜色flowColor: "#BF3EFF", // 扫描颜色topColor: '#00FF00' // 顶部颜色}// 顶点着色器const vertexShader = `// 向片元着色器传递顶点位置数据varying vec3 v_position;void main () {v_position = position;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`;// 片元着色器const fragmentShader = `// 接收顶点着色器传递的顶点位置数据varying vec3 v_position;// 接收js传入的值uniform float u_time;uniform vec3 u_size;uniform vec3 u_flow;uniform vec3 u_color;uniform vec3 u_flowColor;uniform vec3 u_topColor;uniform float u_selected;#define PI 3.14159265359void main () {// 给建筑设置从上到下的渐变颜色float indexPct = v_position.y / u_size.y;vec3 color = mix(u_color, u_topColor,indexPct);// 根据时间和速度计算出当前扫描点的位置, 以上顶点为准float flowTop = mod(u_flow.z * u_time, u_size.y);// 判断当前点是否在扫描范围内if (flowTop > v_position.y && flowTop - u_flow.y < v_position.y) {// 扫描范围内的位置设置从上到下的渐变颜色float flowPct = (u_flow.y - ( flowTop -  v_position.y)) / u_flow.y;color = mix(color ,u_flowColor, flowPct);}// 如果被选中if (u_selected > 0.5) {float selectPct = fract(sin(u_time * PI )) * 0.8;color = mix(color ,vec3(1.0, 1.0, .0), selectPct);}gl_FragColor = vec4(color, 1.0);}`;// 创建若干个建筑物const buildCount = 50;const group = new THREE.Group();for (let i=0; i<buildCount; i++) {const x = randWidth(20);const y = randWidth(100);const z = randWidth(10);const boxGeometry = new THREE.BoxBufferGeometry(x, y ,z);const positionX = 300 - randWidth(600);const positionZ = 300 - randWidth(600);boxGeometry.translate(positionX,  y / 2 ,positionZ);const material = new THREE.ShaderMaterial({transparent: true,uniforms : {u_time: ratio,u_size: {value: flowData.boxSize},u_flow: {value: flowData.flowConf},u_color: {value:  new THREE.Color(flowData.color) },u_flowColor: {value: new THREE.Color(flowData.flowColor) },u_topColor: {value: new THREE.Color(flowData.topColor) },u_selected: {value: 0},},vertexShader,fragmentShader});const mesh = new THREE.Mesh(boxGeometry, material);mesh.isBuild = true;group.add(mesh);}scene.add(group);addClick();function addClick () {var raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置var mouse = new THREE.Vector2();//创建二维平面window.addEventListener("mousedown",mousedown);//页面绑定鼠标点击事件//点击方法function mousedown(e){//将html坐标系转化为webgl坐标系,并确定鼠标点击位置mouse.x =  e.clientX / renderer.domElement.clientWidth*2-1;mouse.y =  -(e.clientY / renderer.domElement.clientHeight*2)+1;//以camera为z坐标,确定所点击物体的3D空间位置raycaster.setFromCamera(mouse,camera);//确定所点击位置上的物体数量var intersects = raycaster.intersectObjects(scene.children);//选中后进行的操作if(intersects.length){setSelected(intersects[0].object);}}}let selectedMeshArr = null;function setSelected (obj) {// 判断选中的对象是否是建筑块儿,如果是则修改其uniforms中的u_selected值if (obj.isBuild) {obj.material.uniforms.u_selected.value = 1;if (selectedMeshArr) {// 清除历史选中selectedMeshArr.material.uniforms.u_selected.value = 0;}selectedMeshArr = obj;}}let next = 0;render();function render () {TWEEN.update()next += 0.01ratio.value = next;requestAnimationFrame(render);renderer.render(scene, camera);}controls = new THREE.OrbitControls(camera, renderer.domElement);}window.onload = init
</script></body>
</html>

threejs的转场动画 (基于Tween实现)、平滑切换场景相关推荐

  1. android转场动画,让你的APP瞬间绚丽起来

    友好的交互体验能够吸引眼球,android API 21(5.0)后系统内置了Activity之间的切换动画,不仅可以让用户看起来舒服,而且实现起来也特别简单. 一.通过overridePending ...

  2. (0030) iOS 开发之跳转之转场动画

    demo: 1 iOS  ~ ViewController的Push,Pop和Present,Dismiss转场动画 // http://blog.csdn.net/zhangao0086/artic ...

  3. 动画体系知识梳理(1) 转场动画 ContentTransition 理论篇

    一.概述 在Android 5.0当中,Google基于Android 4.4中的Transition框架引入了转场动画,设计转场动画的目的,在于让Activity之间或者Fragment之间的切换更 ...

  4. iOS自定义转场动画实战讲解

    转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerAnimated:completio ...

  5. 控制器之间跳转实现转场动画,动画控制器概念

    在iOS7以前,开发者如果希望定制导航控制器推入推出视图时的转场动画,一般都只能通过子类化UINavigationController或者自己编写动画代码去覆盖相应的方法,现在iOS7为开发者带来了福 ...

  6. swift转场动画_Swift游乐场的演变

    swift转场动画 "An amazing platform to learn coding, a great developer tool" is a good definiti ...

  7. iOS动画之转场动画CATransition

    CATransition转场动画 提供层状态间动画转换的对象. 你可以通过创建和添加一个cattransitions对象到一个层的状态之间的过渡.默认转换是交叉渐隐,但是您可以从一组预定义转换指定不同 ...

  8. Material Design之定制动画--触摸反馈,循环揭露,转场动画,共享元素和曲线运动

    先贴下官网的API https://developer.android.com/training/material/animations.html 触摸反馈: 在按钮属性中添加 android:bac ...

  9. 腾讯T7手记:Android转场动画的前世今生!

    前一段时间做图片查看器的升级时,在打开图片查看器的时,找不到好的过渡方式. 有位大佬给我推荐了Android最新的Material Motion动画,虽然最终没有给我们的App安排,但给我学习Mate ...

  10. 转场动画-仿AppStore跳转及抖音评论

    有钱的捧个钱场,没钱的捧个人场,看一看瞧一瞧嘞. demo下载地址: demo-0 demo-1 demo-0为简化版,方便大家理解.demo-1为优化版,功能代码都比demo-0多一些,本文主要以d ...

最新文章

  1. 教育部回应:没有使用“第一学历”这个概念!
  2. Windows Azure Tools DSInit Error
  3. vsftpd匿名用户访问
  4. idea中二级包为什么创建不了_IDEA通过Maven打包JavaFX工程(OpenJFX11)
  5. screentogif 屏幕录制生成gif图片的软件安装过程
  6. C++ Aggregate 与 POD(Plain Old Data)的解释
  7. 章节十五、6-log4 2-用默认的配置
  8. 在PKM2 / CyberArticle / MetaProducts Inquiry / 网博士 中选择了网博士。 :)
  9. c语言pwm调制方式,pwm如何进行调制?3种pwm调制方式介绍
  10. 把sql中的image数据在网页中显示成图片
  11. 【数据报表中心】强大的迈安2019年大数据分析有哪些工具
  12. Python之父愤然退位:再也无法忍受他们鄙视我的意见
  13. mapreduce 论文 - 阅读笔记
  14. axios 全攻略之 API
  15. 华为Ensp软件入门
  16. 百度地图清除标注和聚合点
  17. linux 查看当前用户和组的信息,Linux查看所有用户和组信息
  18. 某徒步旅游网站python爬虫小练习
  19. 什么是JRE?Java运行环境简介
  20. 今日职业规划(测试了一下九型人格)

热门文章

  1. 百度网盘html资源,百度网盘目录索引搭建教程:如何把百度网盘文件做成在线html目录...
  2. mino文件服务器,mimo技术有什么用_mino技术原理解析
  3. fail can only be invoked by user TAP gesture.
  4. 【HDU 5956】The Elder(树上斜率DP)
  5. springboot启动时报错 错误:找不到或无法加载主类 xxx.SpringDemoApplication
  6. 一.数组(10)274. H 指数(不怎么理解)
  7. html中td是什么模块,html td什么意思
  8. table在html是什么意思,html5中table指的是什么意思
  9. html怎样把两张图片重叠6,两张照片重叠成一张-如何将两张相片重叠放在一起?...
  10. 用大白话聊聊JavaSE -- 自定义注解入门