3D网站LOGO动画


相关技术和实现分析
- 3D模型
- 帧动画
- threejs
- 推荐用blender创建3d模型,k帧实现从上到下翻转的帧动画
- threejs 中执行帧动画,并关联滚动条
- threejs 模型材质
Blender 建模
logo模型用的是glb格式,也可以使用已有模型
导出logo模型可以压缩一下,占用资源更小

Blender 动画k帧
用一个空立方体关联logo主体,k帧主要就是立方体的翻转动画,logo是静止的,自转的动画这块可以代码中实现
整个动画总共做了14个关键帧

导出带动画模型(导出时勾选动画信息)

编码
创建场景
<div id="container">
<div id="bg"></div>
</div>
import * as THREE from 'three';
// ...
// 基础数据
const container = document.getElementById('container');
const winHeight = 12000; // 页面高度,可按实际获取
container.style.height = winHeight + 'px';
// antialias 抗锯齿属性; alpha 透明背景
const renderer = window.WebGLRenderingContext
? new THREE.WebGLRenderer({ antialias: true, alpha: true })
: new THREE.CanvasRenderer();
//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 添加webgl渲染的canves内容
document.getElementById('bg').appendChild(renderer.domElement);
// 创建场景
const scene = new THREE.Scene();
scene.background = null;
// 创建相机
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.0001, // 近端视角尽量小 可避免相机穿模
1000
); //透视相机(角度,宽高比,近端,远端)
// 相机位置
const baseCameraPos = { x: 0, y: 0, z: 1.25 };
camera.position.set(baseCameraPos.x, baseCameraPos.y, baseCameraPos.z);
function render() {
requestAnimationFrame(render);
// 使用渲染器,通过相机,将场景渲染进来
renderer.render(scene, camera);
}
render()
材质准备
材质数据
貌似不同版Threejs 材质参数设置表现不太一样,可以具体情况调整
// LOGO材质
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0x3069c7, // 颜色
metalness: 0, // 金属贴图
roughness: 0.4, // 表层粗糙程度 磨砂质感
transparent: false, // 透明度
opacity: 0.98, // 设置透明度
envMapIntensity: 0.51, //需要搭配transparent
transmission: 0.9, // 折射度,表示光线经过材料时的衰减程度 越大越透光
clearcoat: 0.8, // 光亮层的程度
clearcoatRoughness: 0.9, // 光泽层的粗糙程度0-1 越大越粗糙
refractionRatio: 0.9, // 折射率,控制光的折射程度
side: THREE.DoubleSide,
});
// 外框材质
const wrapMaterial = new THREE.MeshPhysicalMaterial({
transparent: true, // 透明度设置为 true
opacity: 0, // 设置透明度
});
读取模型
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
// 模型动画相关
let AnimationAction = null;
let mixer = null;
let clip = null;
let AnimatDuration = 0;
let timeProgress = 0;
let newtimeProgress = 0;
let innerObj = null;
function loadGLB() {
// 创建外层物体
const group = new THREE.Group();
const parent = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), wrapMaterial);
// 外层模型名称
parent.name = '隐形框';
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(
'https://www.gstatic.com/draco/versioned/decoders/1.5.6/'
);
glbLoader.setDRACOLoader(dracoLoader);
glbLoader.load(
'static/model/G/logo.glb', // 可用网络地址
function (gltf) {
// 获取3D网格Mesh节点
const logoMesh = gltf.scene.children[0];
innerObj = logoMesh;
// 组合结构
parent.add(logoMesh);
group.add(parent);
// 场景中加入
scene.add(group);
parent.animations = [];
// animatInfo 帧动画数据
const tracks = animatInfo.tracks[0];
const tracks1 = animatInfo.tracks[1];
AnimatDuration = animatInfo.duration;
const rotationKeyFrame = new THREE.QuaternionKeyframeTrack(
// 固定格式 [模型名称+'.quaternion']
parent.name + '.quaternion',
tracks.times,
tracks.values
);
const VectorKeyFrame = new THREE.VectorKeyframeTrack(
// 固定格式 [模型名称+'.position']
parent.name + '.position',
tracks1.times,
tracks1.values
);
clip = new THREE.AnimationClip(animatInfo.name, animatInfo.duration, [
rotationKeyFrame,
VectorKeyFrame,
]);
group.animations = [clip];
// group.scale.set(1.2, 1.2, 1.2); // 缩放设置
if (group.animations.length) {
mixer = new THREE.AnimationMixer(group);
//创建动画clipAction对象
AnimationAction = mixer.clipAction(clip);
// 单帧播放
AnimationAction.loop = THREE.LoopOnce;
AnimationAction.clampWhenFinished = true;
animatPlay(scrollRate);
}
},
function (xhr) {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded');
},
function (error) {
console.log(error, 'An error happened');
}
);
}
loadGLB()
动画数据获取
分离动画数据的好处是可以降低引入模型大小,还能将动画数据复用到任何模型上
glbLoader.load(
'static/model/G/logoAnimat.glb', // 包含动画数据模型
function (gltf) {
// 读取 animatInfo
animatInfo = gltf.animations[0]
})
单帧控制
// 时间相关
var clock = new THREE.Clock();
var deltaTime = 0;
var newTime = new Date().getTime();
var oldTime = new Date().getTime();
// 监听滚动条
window.onscroll = function () {
const nextScrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
scrollTop = nextScrollTop;
scrollRate = scrollTop / totalHeight;
// 帧动画播放进度
animatPlay(scrollRate);
};
// 帧动画 播放进度
function animatPlay(scrollRate) {
newtimeProgress = AnimatDuration * scrollRate; // 目标进度时间
}
// 平滑播放动画
function updateGroup() {
if (!AnimationAction) return;
timeProgress += (newtimeProgress - timeProgress) * deltaTime * 0.005;
AnimationAction.time = timeProgress; //操作对象设置开始播放时间
clip.duration = AnimationAction.time; //剪辑对象设置播放结束时间
AnimationAction.play(); //开始播放
camera.updateProjectionMatrix();
}
function render() {
newTime = new Date().getTime();
deltaTime = newTime - oldTime;
oldTime = newTime;
// logo自转
if (innerObj) {
innerObj.rotation.z += 0.01;
}
// 一定要在这里面获取delta时间才能持续更新
if (mixer) mixer.update(clock.getDelta());
updateGroup();
// ...
}
至此可以获得一个3d动画logo,只是好像还缺点啥

神说,要有光!
光照的设置非常影响玻璃质感,这里给的都是固定角度光,实际有光照是运动的,效果更好
// 环境光
const light0 = new THREE.AmbientLight(0x404040, 1);
scene.add(light0);
// 添加光照 设置角度和强度
lightPingXing(0, -5, 0, 5);
lightPingXing(10, 0, 2, 1);
lightPingXing(0, 2, 0, 20);
lightPingXing(0, -2, -8, 1);
// 平行光
function lightPingXing(x, y, z, energy = 1) {
const directionalLight = new THREE.DirectionalLight('#fff', energy);
directionalLight.position.set(x, y, z);
directionalLight.castShadow = true;
directionalLight.visible = true;
scene.add(directionalLight);
}
打光后效果

其他细节
- 浮动效果
这块没有想到好的实现方式,目前是让镜头略微移动,感觉凑合;
- 背景和虚化效果
实现起来不难,也可自行发挥
- 背景小logo
可复制logo按需展示
3D网站LOGO动画的更多相关文章
- Logo小变动,心境大不同,SVG矢量动画格式网站Logo图片制作与实践教程(Python3)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_207 曾几何时,SVG(Scalable Vector Graphics)矢量动画图被坊间称之为一种被浏览器诅咒的技术,只因为糟糕 ...
- Three.js实现脸书元宇宙3D动态Logo
背景 Facebook 近期将其母公司改名为 Meta,宣布正式开始进军 元宇宙 领域.本文主要讲述通过 Three.js + Blender 技术栈,实现 Meta 公司炫酷的 3D 动态 Logo ...
- jQuery鼠标悬停3d菜单展开动画
效果体验:http://hovertree.com/texiao/jquery/93/ 竖直的主菜单贴着页面左侧,当光标移入菜单项时,以3D动画的方式弹出对应的二级菜单.采用jQuery和CSS3实现 ...
- Qt Creator中的3D绘图及动画教程(参照NeHe)
Qt Creator中的3D绘图及动画教程(参照NeHe) http://blog.csdn.net/cly116/article/details/47184729 刚刚学习了Qt Creator,发 ...
- Python3.7将普通图片(png)转换为SVG图片格式并且让你的网站Logo(图标)从此”动”起来
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_148 在之前的几篇文章中,介绍了业界中比较火爆的图片技术SVG(Scalable Vector Graphics),比如Iconf ...
- 网站logo正确写法,个人拙见,不喜勿喷
网站logo既要考虑seo又需要用图片代替网站名字,所有H1标签带来的权重还是需要使用 有些人喜欢直接把<H1></H1>标签直接hidden掉,个人喜欢使用css Text- ...
- css3 3D变换和动画
3D变换和动画 建立3D空间,transform-style: preserve-3d perspective: 100px; 景深 perspective-origin:center center ...
- 【翻译】我如何使用CSS来制作bitsofcode Logo动画
翻译文章,翻译不好,还望大家指出 原文地址:How I Animated the bitsofcode Logo with CSS 我是css动画的新手,这样说是因为我只在有限的案例中使用过他们,而且 ...
- 在百度搜索里展现网站LOGO
我们经常在百度搜索一些网站可以看到一个网站在百度上展示的三个部分: 网站的名称 如(趣学车) 网站的描述 一段比较详细的对网站的介绍 网站的logo,一张logo图片 如下图 ------ 接下来我们 ...
- WordPress 后台上传自定义网站Logo
需求: 众所周知一般网站的logo都是固定的所以我在做网站时也是使用的静态logo文件,但最近用wp给一个客户做的网站时,因为网站现在的logo可能会需要重新设计,所以客户提出了需要在后台可以自己修改 ...
随机推荐
- 对比 MyBatis 和 MyBatis-Plus 批量插入、批量更新的性能和区别
1 环境准备 demo 地址:learn-mybatis · Sean/spring-cloud-alibaba - 码云(gitee.com) 1.1 搭建 MyBatis-Plus 环境 创建 m ...
- [初学C#] 第二习题 : 快递跟踪信息查询
刚学C#, 折腾的一个小玩意. 熟悉和了解C#这门编程语言. 没有啥特殊意义 解锁技能 - System.Net 的 WebRequest等http请求 - Newtonsoft.Json 这个第三方 ...
- 【krpano】KRPano打开黑屏: FATAL ERROR
在KRPano开发过程中,初学者打开项目经常遇到如下的问题: FATAL ERROR:tour.xml – loading failed! (0) 或者是: ERROR:Local usage wit ...
- 记一次基于 PowerShell 的 Git 自动化部署 Java 多服务实践
前言 有这么一个自动化部署的需求,凑巧 git 还直接建立在测试服务器上,部署后可以直接在测试服务器上演示 步骤 建立 Git 仓库 与一般的 Git 部署一样,区别是需要添加 --bare 开关,这 ...
- RK3588平台产测之ArmSoM产品低温环境测试
1. 简介 专栏总目录 ArmSoM团队在产品量产之前都会对产品做几次专业化的功能测试以及性能压力测试,以此来保证产品的质量以及稳定性 优秀的产品都要进行严苛的多次全方位的功能测试以及性能压力测试才能 ...
- C#/.NET/.NET Core优秀项目和框架精选(2023年10月更新,项目分类已整理完成欢迎大家踊跃提交PR一起完善让优秀的项目和框架不被埋没)
前言 帮助开发者发现功能强大.性能优越.创新前沿.简单易用的C#/.NET/.NET Core优秀项目和框架,无论你是寻找灵感.学习新技术.改进代码质量,还是想拓展自己的技术视野,都能为你提供有价值的 ...
- 基于落点打分的井字棋智能下棋算法(C语言实现)
本文设计了一种基于落地打分的井字棋下棋算法,能够实现电脑不败,所以如果玩家会玩的话,一般是平局. 算法核心 电脑根据对落子位置的打分,选择分数最高的位置,若不同落点分数相同则随机选择位置(随机选择就不 ...
- P4899 [IOI2018] werewolf 狼人 题解
P4899 [IOI2018] werewolf 狼人 题解 题目描述 省流: \(n\) 个点,\(m\) 条边,\(q\) 次询问,对于每一次询问,给定一个起点 \(S\) 和终点 \(T\) , ...
- 挑战程序设计竞赛 2.2 poj 3040 Allowance 贪心
https://vjudge.csgrandeur.cn/problem/POJ-3040 /* 作为创纪录的牛奶产量的奖励,约翰决定每周给贝西一小笔零用钱.FJ拥有一组N(1 <= N < ...
- APIO 2023 游记
真心话大冒险很有趣. rand 一个房间去敲门加 QQ 很有趣.这么看社恐猫好像也没那么社恐. 面到了 zpl pcq iee dx.单方面认识了很多神仙. 比赛只会写暴力,评测 queue 害人不浅 ...