温州地区做网站/我的百度购物订单

温州地区做网站,我的百度购物订单,简易手机网站开发,公司集团网站建设9-Three.js 贴图与材质学习指南 环境准备 <!DOCTYPE html> <html> <head><title>Three.js Texture Demo</title><style> body { margin: 0; } </style> </head> <body><script src"https://cdnjs.cloudflare.…

9-Three.js 贴图与材质学习指南

环境准备

<!DOCTYPE html>
<html>
<head><title>Three.js Texture Demo</title><style> body { margin: 0; } </style>
</head>
<body><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r155/three.min.js"></script><script src="https://cdn.jsdelivr.net/npm/three@0.155.0/examples/js/controls/OrbitControls.js"></script><script src="./main.js"></script>
</body>
</html>

基础材质类型

// 基础材质
const basicMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00,wireframe: false
});// 标准物理材质
const standardMaterial = new THREE.MeshStandardMaterial({color: 0xffffff,metalness: 0.7,roughness: 0.3
});

核心知识点

1. 纹理加载

const textureLoader = new THREE.TextureLoader();
const colorMap = textureLoader.load('textures/wood_diffuse.jpg');
const normalMap = textureLoader.load('textures/wood_normal.jpg');// 带加载管理的示例
const manager = new THREE.LoadingManager();
manager.onProgress = (url, loaded, total) => {console.log(`加载进度: ${loaded}/${total}`);
};const customLoader = new THREE.TextureLoader(manager);

2. 材质属性配置

const material = new THREE.MeshStandardMaterial({map: colorMap,        // 基础颜色贴图normalMap: normalMap, // 法线贴图displacementMap: textureLoader.load('height.png'),displacementScale: 0.1,roughnessMap: textureLoader.load('roughness.jpg'),metalness: 0.5,roughness: 0.3
});

3. 环境贴图

const cubeLoader = new THREE.CubeTextureLoader().setPath('textures/cubemap/');const envMap = cubeLoader.load(['px.jpg', 'nx.jpg','py.jpg', 'ny.jpg','pz.jpg', 'nz.jpg'
]);material.envMap = envMap;
material.envMapIntensity = 1.5;

完整示例代码

let scene, camera, renderer;function init() {// 场景设置scene = new THREE.Scene();camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 材质创建const material = createComplexMaterial();// 几何体const sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 64, 64),material);scene.add(sphere);// 灯光const light = new THREE.PointLight(0xffffff, 1000);light.position.set(10, 10, 10);scene.add(light);// 相机控制const controls = new THREE.OrbitControls(camera, renderer.domElement);camera.position.z = 10;animate();
}function createComplexMaterial() {const loader = new THREE.TextureLoader();return new THREE.MeshStandardMaterial({map: loader.load('diffuse.jpg'),normalMap: loader.load('normal.jpg'),roughnessMap: loader.load('roughness.jpg'),metalness: 0.5,roughness: 0.3,aoMap: loader.load('ao.jpg'),displacementMap: loader.load('height.png'),displacementScale: 0.1});
}function animate() {requestAnimationFrame(animate);renderer.render(scene, camera);
}init();

关键知识要点

材质类型对比

材质类型特性性能光照支持
MeshBasicMaterial基础颜色显示
MeshPhongMaterial镜面高光
MeshStandardMaterial基于物理的渲染(PBR)
MeshPhysicalMaterial扩展PBR功能(透明涂层等)

常用贴图类型

  1. 颜色贴图 (map) - 基础表面颜色
  2. 法线贴图 (normalMap) - 表面细节凹凸
  3. 环境光遮蔽贴图 (aoMap) - 环境光遮蔽效果
  4. 粗糙度贴图 (roughnessMap) - 表面光滑程度
  5. 金属度贴图 (metalnessMap) - 金属质感表现
  6. 置换贴图 (displacementMap) - 真实几何形变

优化建议

  1. 使用压缩纹理格式(.basis, .ktx2)
  2. 合理设置纹理分辨率(避免超大尺寸)
  3. 复用纹理对象
  4. 使用mipmap提高渲染质量
  5. 对不可见物体禁用纹理更新

常见问题排查

  1. 纹理不显示:检查文件路径和格式

  2. 法线贴图效果异常:确认材质normalScale设置

  3. 性能低下:检查纹理尺寸是否过大

  4. 环境贴图失效:确认场景背景设置

  5. PBR材质暗淡:确保场景中有足够光照

    纹理贴图代码:

import * as THREE from 'three';// 初始化场景、相机、渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);// 创建平面几何体
const planeGeometry = new THREE.PlaneGeometry(2, 2);// 定义全局变量 plane
let plane;// 加载纹理并创建材质和网格
const textureLoader = new THREE.TextureLoader();
textureLoader.load('../public/assets/texture/2.jpg',(texture) => {const planeMaterial = new THREE.MeshBasicMaterial({ map: texture });plane = new THREE.Mesh(planeGeometry, planeMaterial); // 将 plane 赋值给全局变量scene.add(plane);// 调整相机位置camera.position.z = 5;// 启动动画循环animate();},(xhr) => {console.log('加载进度:', (xhr.loaded / xhr.total * 100) + '%');},(err) => {console.error('纹理加载失败:', err);}
);// 定义动画函数
function animate() {requestAnimationFrame(animate);if (plane) { // 确保 plane 已定义plane.rotation.x += 0.01;plane.rotation.y += 0.01;}renderer.render(scene, camera);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

10-纹理颜色空间、雾效及基础概念

目录

  1. Three.js 基础知识
  2. 纹理的颜色空间
  3. 雾效 (Fog)
  4. 示例代码

核心概念

  1. 场景 (Scene):所有 3D 对象的容器。
  2. 相机 (Camera):用于定义观察场景的视角。
  3. 渲染器 (Renderer):负责将场景渲染到屏幕上。
  4. 物体 (Object3D):场景中的基本元素,可以是模型、灯光等。
  5. 材质 (Material):定义物体表面的外观。
  6. 几何体 (Geometry):定义物体的形状。
  7. 灯光 (Light):为场景提供光照。
  8. 纹理 (Texture):为物体表面添加图像。

纹理的颜色空间

在 Three.js 中,纹理的颜色空间处理非常重要,因为它会影响最终的渲染效果。

sRGB 与线性颜色空间

  • sRGB:标准的颜色空间,用于显示器和图像。
  • 线性颜色空间:用于光线计算,确保物理正确的光照效果。

在 Three.js 中设置纹理颜色空间

Three.js 默认使用 sRGB 颜色空间。如果需要调整,可以通过 Texture 对象的属性进行设置。

示例:加载纹理并设置颜色空间
<!DOCTYPE html>
<html>
<head><title>Three.js 纹理颜色空间示例</title><style>body { margin: 0; }canvas { display: block; }</style>
</head>
<body><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script><script>const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 加载纹理const textureLoader = new THREE.TextureLoader();const texture = textureLoader.load('path/to/texture.jpg', function(texture) {// 设置纹理的颜色空间texture.encoding = THREE.sRGBEncoding; // 或 THREE.LinearEncoding});const geometry = new THREE.BoxGeometry();const material = new THREE.MeshBasicMaterial({ map: texture });const cube = new THREE.Mesh(geometry, material);scene.add(cube);camera.position.z = 5;function animate() {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);}animate();</script>
</body>
</html>

雾效 (Fog)

雾效可以为场景添加真实的氛围,模拟远距离物体的模糊效果。

Three.js 中的雾效类型

  1. 线性雾 (Linear Fog):雾的密度随距离线性变化。
  2. 指数雾 (Exponential Fog):雾的密度随距离指数变化。
  3. 指数平方雾 (Exponential Squared Fog):雾的密度随距离平方变化。

示例:添加雾效

<!DOCTYPE html>
<html>
<head><title>Three.js 雾效示例</title><style>body { margin: 0; }canvas { display: block; }</style>
</head>
<body><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script><script>const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 添加雾效scene.fog = new THREE.FogExp2(0x87CEEB, 0.0025);const geometry = new THREE.BoxGeometry();const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });const cube = new THREE.Mesh(geometry, material);scene.add(cube);camera.position.z = 5;function animate() {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);}animate();</script>
</body>
</html>

示例代码

1. 创建场景并添加物体

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);camera.position.z = 5;function animate() {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);
}
animate();

2. 加载并设置纹理

const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('path/to/texture.jpg', function(texture) {texture.encoding = THREE.sRGBEncoding;
});const material = new THREE.MeshBasicMaterial({ map: texture });

3. 添加雾效

scene.fog = new THREE.FogExp2(0x87CEEB, 0.0025);

总结

通过以上内容,您可以了解 Three.js 的基础概念、纹理颜色空间的处理以及雾效的添加方法。希望这些知识点对您有所帮助!

### 图片示例#### 纹理颜色空间对比
![sRGB vs Linear](https://example.com/srgb-vs-linear.png)#### 雾效效果
![Fog Effect](https://example.com/fog-effect.png)---### 代码示例#### 创建场景并添加物体
```javascript
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);camera.position.z = 5;function animate() {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);
}
animate();
加载并设置纹理
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('path/to/texture.jpg', function(texture) {texture.encoding = THREE.sRGBEncoding;
});const material = new THREE.MeshBasicMaterial({ map: texture });
添加雾效
scene.fog = new THREE.FogExp2(0x87CEEB, 0.0025);

总结

通过以上内容,您可以了解 Three.js 的基础概念、纹理颜色空间的处理以及雾效的添加方法。希望这些知识点对您有所帮助!

以下是关于在Three.js中使用glTF模型的学习指南,包含知识点、代码实现和资源建议:

11-Three.js glTF 模型学习指南

📚 知识点思维导图

glTF基础
glTF是什么
glTF的优势
glTF文件结构
.gltf/json
.bin/二进制
贴图资源
Three.js集成
GLTFLoader
加载流程
初始化加载器
加载模型
添加到场景
模型控制
位置/旋转/缩放
动画控制
最佳实践
模型优化
错误处理
性能优化

🛠️ 学习步骤

  1. 环境准备

    • 安装Node.js
    • 创建项目文件夹
    mkdir threejs-gltf-demo && cd threejs-gltf-demo
    npm init -y
    npm install three @types/three three-orbitcontrols
    
  2. 基础Three.js场景搭建

    <!-- index.html -->
    <!DOCTYPE html>
    <html>
    <head><meta charset="UTF-8"><title>glTF Demo</title><style>body { margin: 0; }</style>
    </head>
    <body><script src="main.js"></script>
    </body>
    </html>
    
  3. 核心代码实现(自己要在src的同级目录下新建一个models然后里面放上glb即可)

    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';// 1. 初始化场景
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0xeeeeee); // 设置背景颜色
    document.body.appendChild(renderer.domElement);// 2. 添加光源
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 环境光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 平行光
    directionalLight.position.set(5, 5, 5);
    scene.add(ambientLight, directionalLight);// 3. 加载glTF模型
    const loader = new GLTFLoader();
    let model;// 本地模型路径
    const modelUrl = './models/DragonAttenuation.glb';loader.load(modelUrl,(gltf) => {model = gltf.scene;scene.add(model); // 将模型添加到场景中console.log('模型加载成功');},undefined,(error) => {console.error('加载错误:', error);}
    );// 4. 相机控制
    camera.position.z = 1; // 设置相机初始位置
    const controls = new OrbitControls(camera, renderer.domElement); // 添加轨道控制器
    controls.enableDamping = true; // 启用阻尼效果// 5. 动画循环
    function animate() {requestAnimationFrame(animate);controls.update(); // 更新控制器renderer.render(scene, camera); // 渲染场景
    }
    animate();// 6. 窗口响应
    window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight; // 更新相机宽高比camera.updateProjectionMatrix(); // 更新相机投影矩阵renderer.setSize(window.innerWidth, window.innerHeight); // 更新渲染器大小
    });
    

📌 关键知识点

  1. GLTFLoader使用要点

    // 带进度回调的加载示例
    loader.load('model.gltf',(gltf) => {// 成功回调},(xhr) => {// 进度回调console.log(`${(xhr.loaded / xhr.total * 100)}% loaded`);},(error) => {// 错误处理}
    );
    
  2. 模型操作示例

    // 调整模型属性
    if(model) {model.position.set(0, 0, 0);model.rotation.y += 0.01;model.scale.set(1, 1, 1);
    }// 遍历模型子元素
    model.traverse((child) => {if (child.isMesh) {child.castShadow = true;child.receiveShadow = true;}
    });
    
  3. 优化建议

    • 使用Draco压缩:
    import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');const loader = new GLTFLoader();
    loader.setDRACOLoader(dracoLoader);
    

🖼️ 示例模型资源

推荐使用官方示例模型:

  1. Damaged Helmet
  2. Flight Helmet

⚠️ 常见问题

  1. 跨域问题:建议使用本地服务器运行

    npx serve
    
  2. 模型不显示:检查控制台错误、确认模型路径、确认光源设置

  3. 性能优化:使用压缩格式、合并网格、简化材质

📁 项目结构建议

project-root/
├── index.html
├── main.js
├── models/
│   └── your_model.gltf
├── textures/
└── package.json

完整实现需要:

  1. 将glTF模型文件放入models目录
  2. 安装依赖后通过本地服务器运行
  3. 根据模型实际尺寸调整相机位置

需要测试模型可以先用Three.js示例模型:

loader.load('https://threejs.org/examples/models/gltf/Duck/glTF/Duck.gltf',// 其他参数保持不变
);

没有模型怎么办?需要的可以私聊波珠,点赞收藏加关注!

以下是获取 glTF 模型的推荐资源和详细方法,帮助你快速找到可用的测试模型:


🌟 免费 glTF 模型资源网站

(可直接下载使用,无需注册或商业授权)

  1. 官方示例模型

    • Khronos Group 官方示例库
      • 包含经典模型(如 Damaged Helmet、Flight Helmet 等)
      • 直接下载 .gltf + .bin + 贴图文件组合
  2. Sketchfab 免费专区

    • Sketchfab Free Models
      • 搜索时勾选 “Downloadable”“glTF” 格式
      • 推荐模型:
        • Sci-Fi Helmet
        • Low Poly Wolf
  3. Three.js 官方示例模型

    • 在线路径(直接用于代码测试):

      // 示例:加载 Three.js 自带的鸭子模型
      loader.load('https://threejs.org/examples/models/gltf/Duck/glTF/Duck.gltf',(gltf) => { /*...*/ }
      );
      
  4. 其他资源库

    • Poly Haven(CC0 授权,需转换格式)
    • Clara.io(部分免费)

🛠️ 快速获取测试模型的步骤

  1. 手动下载模型到本地

    • 从 Khronos 官方库 下载 ZIP

    • 解压后找到 glTF 文件夹(通常包含 .gltf + .bin + 贴图)

    • 在项目中创建 models 目录,将文件放入其中

    • 代码中修改路径:

      loader.load('./models/YourModel/glTF/Model.gltf', (gltf) => { /*...*/ });
      

⚠️ 注意事项

  1. 文件结构
    glTF 模型通常由多个文件组成,确保所有文件保持相对路径不变:

    models/
    └── DamagedHelmet/├── glTF/                  ← 使用这个文件夹│   ├── DamagedHelmet.gltf│   ├── DamagedHelmet.bin│   └── textures/           ← 贴图文件夹
    
  2. 跨域问题
    如果直接打开本地 HTML 文件加载模型会报错,需启动本地服务器:

    npx serve
    

    然后访问 `http://localhost:5000


🎨 最终效果参考

在这里插入图片描述
在这里插入图片描述

加上环境贴图则是这个效果。

12-Three.js 光线投射 (Raycasting) 实现3D交互

📚 核心知识点

1. 光线投射原理

屏幕点击位置
标准化设备坐标NDC
相机生成射线
检测与场景物体交集
返回相交对象信息

2. Three.js 实现步骤

  1. 坐标转换:将鼠标位置转换为标准化设备坐标(NDC)
  2. 射线生成:通过相机和鼠标位置创建射线
  3. 碰撞检测:检测射线与场景物体的交叉点
  4. 交互处理:根据检测结果执行操作

3. 关键API

  • THREE.Raycaster
  • raycaster.setFromCamera()
  • raycaster.intersectObjects()

4. 应用场景

  • 3D物体点击选中
  • 鼠标悬停高亮
  • 第一人称射击游戏
  • VR/AR中的交互

🛠️ 完整代码实现

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';// 初始化场景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);// 添加测试物体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00,metalness: 0.3,roughness: 0.8
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);// 添加光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(ambientLight, directionalLight);// 相机位置
camera.position.z = 5;
const controls = new OrbitControls(camera, renderer.domElement);// 初始化Raycaster
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();// 鼠标移动事件监听
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('click', onClick);function onMouseMove(event) {// 转换鼠标坐标到标准化设备坐标 [-1, 1]mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;// 更新射线raycaster.setFromCamera(mouse, camera);// 检测相交物体const intersects = raycaster.intersectObjects(scene.children);// 悬停效果scene.children.forEach(obj => {if (obj.isMesh) {obj.material.emissive.setHex(0x000000);}});if (intersects.length > 0) {intersects[0].object.material.emissive.setHex(0x444444);}
}function onClick(event) {raycaster.setFromCamera(mouse, camera);const intersects = raycaster.intersectObjects(scene.children);if (intersects.length > 0) {// 点击效果:随机改变颜色intersects[0].object.material.color.setHex(Math.random() * 0xffffff);}
}// 动画循环
function animate() {requestAnimationFrame(animate);controls.update();renderer.render(scene, camera);
}
animate();// 窗口响应
window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);
});

在这里插入图片描述

📌 关键代码解析

1. 坐标转换公式

mouse.x = (event.clientX / windowWidth) * 2 - 1;
mouse.y = -(event.clientY / windowHeight) * 2 + 1;

2. 射线检测优化

// 只检测可交互物体
const interactiveObjects = [cube, sphere]; 
raycaster.intersectObjects(interactiveObjects);// 性能优化:节流检测
let lastCheck = 0;
function throttleCheck() {const now = Date.now();if (now - lastCheck > 100) {checkIntersections();lastCheck = now;}
}

3. 高级交互示例

// 显示点击位置标记
const markerGeometry = new THREE.SphereGeometry(0.05, 16, 16);
const markerMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const marker = new THREE.Mesh(markerGeometry, markerMaterial);
scene.add(marker);function onClick() {const intersects = raycaster.intersectObjects(scene.children);if (intersects.length > 0) {// 在交点处显示标记marker.position.copy(intersects[0].point);marker.visible = true;// 添加点击动画new TWEEN.Tween(marker.scale).to({ x: 1.5, y: 1.5, z: 1.5 }, 300).easing(TWEEN.Easing.Exponential.Out).start();}
}

⚠️ 常见问题解决方案

  1. 检测不到物体

    • 确保物体matrixWorld已更新:object.updateMatrixWorld()
    • 检查物体是否在场景中
    • 确认物体visible属性为true
  2. 坐标偏移问题

    // 处理CSS偏移
    const rect = renderer.domElement.getBoundingClientRect();
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
    
  3. 性能优化建议

    • 使用intersectObject替代intersectObjects检测单个物体
    • 减少检测频率(使用节流)
    • 使用简化碰撞体(如BoxHelper

🖼️ 效果示意图

在这里插入图片描述

通过光线投射实现物体悬停高亮和点击变色效果

13-补间动画(Tween Animation)知识点与代码示例

1.1 什么是补间动画?

补间动画(Tween Animation)是一种在动画的起始状态和结束状态之间自动生成中间帧的动画技术。开发者只需要定义动画的起始状态和结束状态,系统会自动计算并生成中间的状态,从而实现平滑的动画效果。

1.2 补间动画的常见属性

  • 位移(Translation):改变对象的位置。
  • 缩放(Scale):改变对象的大小。
  • 旋转(Rotation):改变对象的旋转角度。
  • 透明度(Alpha):改变对象的透明度。

1.3 补间动画的优缺点

  • 优点:
    • 简单易用,只需定义起始和结束状态。
    • 适用于简单的动画效果。
  • 缺点:
    • 无法处理复杂的交互和动画逻辑。
    • 动画效果较为单一,缺乏灵活性。

1.4 补间动画的实现方式

  • XML定义:通过XML文件定义动画效果,然后在代码中加载并应用。
  • 代码实现:直接在代码中定义动画效果并应用。

2. 代码示例

2.1 XML定义补间动画

2.1.1 定义动画XML文件(res/anim/scale_anim.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"><scaleandroid:fromXScale="1.0"android:toXScale="2.0"android:fromYScale="1.0"android:toYScale="2.0"android:pivotX="50%"android:pivotY="50%"android:duration="1000" />
</set>
2.1.2 在代码中加载并应用动画
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ImageView imageView = findViewById(R.id.imageView);Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.scale_anim);imageView.startAnimation(scaleAnimation);}
}

2.2 代码实现补间动画

import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ImageView imageView = findViewById(R.id.imageView);ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 2.0f, // 起始和结束的X缩放比例1.0f, 2.0f, // 起始和结束的Y缩放比例Animation.RELATIVE_TO_SELF, 0.5f, // 缩放中心点X坐标Animation.RELATIVE_TO_SELF, 0.5f  // 缩放中心点Y坐标);scaleAnimation.setDuration(1000); // 动画持续时间imageView.startAnimation(scaleAnimation);}
}

好玩的代码示例:

import * as THREE from 'three';
import * as TWEEN from '@tweenjs/tween.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';// 初始化场景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);// 添加银河系背景
const starGeometry = new THREE.BufferGeometry();
const starPositions = [];
for (let i = 0; i < 5000; i++) {starPositions.push((Math.random() - 0.5) * 2000,(Math.random() - 0.5) * 2000,(Math.random() - 0.5) * 2000);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const starMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.7 });
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);// 创建炫光立方体
const geometry = new THREE.IcosahedronGeometry(1, 3);
const material = new THREE.MeshStandardMaterial({color: 0x00ff00,metalness: 0.9,roughness: 0.1,emissive: 0x00ff00,emissiveIntensity: 0.5
});
const cube = new THREE.Mesh(geometry, material);
cube.castShadow = true;
cube.receiveShadow = true;
scene.add(cube);// 添加粒子环绕系统
const particleGeometry = new THREE.BufferGeometry();
const particleCount = 2000;
const posArray = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount * 3; i++) {posArray[i] = (Math.random() - 0.5) * 5;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
const particleMaterial = new THREE.PointsMaterial({size: 0.005,color: 0x00ffff,transparent: true,blending: THREE.AdditiveBlending
});
const particleMesh = new THREE.Points(particleGeometry, particleMaterial);
cube.add(particleMesh);// 动态光源配置
const pointLight = new THREE.PointLight(0x00ff00, 1, 100);
pointLight.position.set(5, 5, 5);
pointLight.castShadow = true;
scene.add(pointLight);// 后期处理配置
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight),1.5, 0.4, 0.85
);
composer.addPass(bloomPass);
const glitchPass = new GlitchPass();
glitchPass.goWild = false;
composer.addPass(glitchPass);// 镜头光晕特效
const textureLoader = new THREE.TextureLoader();
const flareTexture = textureLoader.load('./textures/lensflare/lensflare0.png');
const lensFlare = new THREE.Sprite(new THREE.SpriteMaterial({map: flareTexture,color: 0xffffff,transparent: true,blending: THREE.AdditiveBlending
}));
lensFlare.scale.set(2, 2, 1);
lensFlare.position.copy(pointLight.position);
scene.add(lensFlare);// 相机控制
camera.position.z = 7;
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;// 光线投射交互
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();window.addEventListener('mousemove', onMouseMove);
window.addEventListener('click', onClick);function onMouseMove(event) {mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;raycaster.setFromCamera(mouse, camera);const intersects = raycaster.intersectObjects([cube]);scene.traverse(obj => {if (obj.isMesh && obj !== cube) obj.material.emissive.setHex(0x000000);});if (intersects.length > 0) {intersects[0].object.material.emissive.setHex(0xff00ff);bloomPass.strength = 2.0;} else {bloomPass.strength = 1.5;}
}function onClick() {raycaster.setFromCamera(mouse, camera);const intersects = raycaster.intersectObjects([cube]);if (intersects.length > 0) {// 点击爆炸粒子效果new TWEEN.Tween(particleMesh.material).to({ size: 0.02 }, 300).easing(TWEEN.Easing.Exponential.Out).onComplete(() => {particleMesh.material.size = 0.005;}).start();// 颜色渐变new TWEEN.Tween(cube.material.color).to({ r: Math.random(), g: Math.random(), b: Math.random() }, 500).start();}
}// 动画循环
const clock = new THREE.Clock();
function animate() {requestAnimationFrame(animate);const time = clock.getElapsedTime();// 立方体动态旋转cube.rotation.x = time * 0.5;cube.rotation.y = time * 0.3;// 粒子系统动画const positions = particleMesh.geometry.attributes.position.array;for (let i = 0; i < positions.length; i += 3) {positions[i] += Math.sin(time + i) * 0.001;positions[i + 1] += Math.cos(time + i) * 0.001;}particleMesh.geometry.attributes.position.needsUpdate = true;// 光源颜色变化pointLight.color.setHSL(Math.sin(time * 0.5) * 0.5 + 0.5, 1, 0.5);// 更新光晕位置lensFlare.position.copy(pointLight.position);// 更新后期处理TWEEN.update();controls.update();composer.render();
}
animate();// 窗口响应
window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);composer.setSize(window.innerWidth, window.innerHeight);
});

在这里插入图片描述

3. 总结

补间动画是一种简单易用的动画技术,适用于实现基本的动画效果。通过XML定义或代码实现,开发者可以轻松地创建位移、缩放、旋转和透明度变化的动画效果。然而,对于更复杂的动画需求,建议使用属性动画(Property Animation)或其他更高级的动画技术。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/73490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端NVM安装

https://v0.dev/chat/settings 本地启动环境 1安装 nvm 2安装node nvm install v18.19.0 nvm install v20.9.0 nvm use 18 node -v 3安装 pnpm npm install -g pnpm 或者 npm i -g pnpm 4启动 代码 目录下 执行 pnpm i pnpm run dev 4.1到代码目录下 4.2直接cmd…

cmd命令查看电脑的CPU、内存、存储量

目录 获取计算机硬件的相关信息的命令分别的功能结果展示结果说明获取计算机硬件的相关信息的命令 wmic cpu get name wmic memorychip get capacity wmic diskdrive get model,size,mediaType分别的功能 获取计算机中央处理器(CPU)的名称 获取计算机内存(RAM)芯片的容量…

如何监控 SQL Server

监控 SQL Server 对于维护数据库性能、确保数据可用性和最大限度地减少停机时间至关重要。随着企业越来越依赖数据驱动的决策&#xff0c;高效的SQL Server监控策略能显著提升组织生产力和用户满意度。 为什么要监控 SQL Server SQL Server 是许多关键应用程序的支柱&#xf…

画秒杀系统流程图

秒杀系统流程图 秒杀系统关键点 高并发处理: 使用网关&#xff08;如 Nginx&#xff09;进行流量限流&#xff0c;避免过载。分布式锁或 Redis 原子操作控制并发。 活动状态检查: Redis 存储活动状态&#xff08;如 seckill:activity:1:status&#xff09;&#xff0c;快速…

【js逆向入门】图灵爬虫练习平台 第九题

地址&#xff1a;aHR0cHM6Ly9zdHUudHVsaW5ncHl0b24uY24vcHJvYmxlbS1kZXRhaWwvOS8 f12进入了debugger&#xff0c;右击选择一律不在此处暂停&#xff0c; 点击继续执行 查看请求信息 查看载荷&#xff0c;2个加密参数&#xff0c;m和tt 查看启动器&#xff0c;打上断点 进来 往…

Vue中的状态管理器Vuex被Pinia所替代-上手使用指南

Pinia.js 是新一代的状态管理器&#xff0c;由 Vue.js团队中成员所开发的&#xff0c;因此也被认为是下一代的 Vuex&#xff0c;即 Vuex5.x&#xff0c;在 Vue3.0 的项目中使用也是备受推崇 Pinia.js 有如下特点&#xff1a; 完整的 typescript 的支持&#xff1b;足够轻量&…

向量数据库学习笔记(1) —— 基础概念

一、 嵌入模型 Embedding Models 嵌入模型是将复杂数据&#xff08;如文本、图像、音频等&#xff09;转换为向量表示的机器学习模型 1. 核心概念 嵌入(Embedding)&#xff1a;将高维、非结构化的数据映射到低维、稠密的向量空间 向量表示&#xff1a;输出固定长度的数值向量…

[NO-WX179]基于springboot+微信小程序的在线选课系统

[NO-WX179]基于springboot微信小程序的在线选课系统 1、管理员角色&#xff08;web端&#xff09;&#xff1a;2、教师角色&#xff08;web端&#xff09;&#xff1a;3、用户角色&#xff08;小程序或web端&#xff09;&#xff1a;4、部分运行截图管理端--教师管理管理端--学…

2025年渗透测试面试题总结-某 长亭(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 长亭 一、Spring SpEL表达式注入漏洞 1. 技术原理 2. 利用条件 3. 攻击方法 4. 防御策略 二、Jav…

conda环境下解决gitk乱码模糊

关键词 conda、git、gitk、git gui、模糊、linux、乱码 现象 操作系统&#xff1a;ubuntu24.04 conda版本&#xff1a;25.1.1 正常的终端里gitk显示不会模糊 但是在conda创建的python虚拟环境中使用gitk&#xff0c;字体开始变得模糊不清 分析 根据deepseek的原因原因分析…

【C++项目实战】:基于正倒排索引的Boost搜索引擎(1)

1. 项目的相关背景与目标 针对boost网站没有搜索导航功能&#xff0c;为boost网站文档的查找提供搜索功能 站内搜索&#xff1a;搜索的数据更垂直&#xff0c;数据量小 类似于cplusplus.com的搜索 2.搜索引擎的相关宏观原理 3.技术栈和项目环境 技术栈&#xff1a;C/C&am…

深入理解指针(1)(C语言版)

文章目录 前言一、内存和地址1.1 内存1.2 究竟该如何理解编址 二、指针变量和地址2.1 取地址操作符&2.2 指针变量和解引用操作符*2.2.1 指针变量2.2.2 如何拆解指针类型2.2.3 解引用操作符 2.3 指针变量的大小 三、指针变量类型的意义3.1 指针的解引用3.2 指针-整数3.3 voi…

第一天学爬虫

阅读提示&#xff1a;我今天才开始尝试爬虫&#xff0c;写的不好请见谅。 一、准备工具 requests库&#xff1a;发送HTTP请求并获取网页内容。BeautifulSoup库&#xff1a;解析HTML页面并提取数据。pandas库&#xff1a;保存抓取到的数据到CSV文件中。 二、爬取步骤 发送请求…

重学Java基础篇—线程池参数优化指南

一、核心参数解析 线程池&#xff08;ThreadPoolExecutor&#xff09;的性能取决于以下关键参数&#xff1a; 参数说明corePoolSize核心线程数&#xff0c;即使空闲也不会被回收maximumPoolSize最大线程数&#xff0c;当队列满且核心线程忙时创建新线程workQueue任务队列&…

记一次线上环境JAR冲突导致程序报错org.springframework.web.util.NestedServletException

一、问题描述 有个文件导入功能&#xff0c;用到了Hutool 的加密解密功能&#xff0c;本地运行完全可以&#xff0c;但是线上报错&#xff1a;“org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFou…

2.基于多线程的TCP服务器实现

目录 1. 简单分析之前的代码 2. 多线程服务器设计 2.1 C11线程的基本使用 2.2 服务器主体逻辑 3. 错误处理的封装 4. 完整的代码实现 客户端代码&#xff08;client.cpp&#xff09; 服务器代码&#xff08;server.cpp&#xff09; 5. 运行方式 在我们预想中&#xff…

从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.2.3实战案例:在笔记本电脑上运行轻量级LLM

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 实战案例:在笔记本电脑上运行轻量级LLM2.2.3 模型架构设计与实现1. 环境与工具准备1.1 硬件要求1.2 软件栈选择2. 轻量级模型架构设计2.1 模型参数配置2.2 关键技术优化3. 实战流程3.1 数据准备流程3.2…

工业软件的破局与重构:从技术依赖到自主创新的未来路径

工业软件作为现代工业的“神经与大脑”&#xff0c;不仅是制造业数字化转型的核心工具&#xff0c;更是国家工业竞争力的战略制高点。近年来&#xff0c;中国工业软件市场在政策驱动与技术迭代中迅猛发展&#xff0c;但核心技术受制于人的困境仍待突破。如何实现从“跟跑”到“…

歌曲缓存相关功能

1. 核心组件 MusicCacheManager (音乐缓存管理器) 单例模式&#xff1a;确保全局只有一个实例&#xff0c;方便管理。 private static var instance: MusicCacheManager?static func shared() -> MusicCacheManager {if instance nil {instance MusicCacheManager()}ret…

阿里开源的免费数据集成工具——DataX

企业里真实的数据流转是什么样子的呢&#xff1f; 左侧描述了一个企业真实的样子&#xff0c;我们总是需要把数据从一个地方搬到另一个地方&#xff0c;最后就是搬来搬去搬成了一张张解不开的网。 右侧则表达了使用DataX为中心实现数据的同步。 什么是DataX DataX是一个异构…