Three.js 動畫系統入門:Tween.js 與 AnimationMixer 的使用

引言

動畫是 Three.js 中增強 3D 場景動態效果的核心技術,能夠為用戶帶來沉浸式體驗。Three.js 支持通過 Tween.js 實現簡單的屬性動畫,以及通過 AnimationMixer 處理復雜的混合動畫和骨骼動畫。本文將深入探討如何使用 Tween.js 控制 Object3D 的屬性動畫,如何通過 AnimationMixer 加載和播放 Mixamo 提供的骨骼動畫,以及如何實現動畫的暫停、循環和交叉漸變等控制功能。通過一個交互式城市角色動畫展示案例,展示如何結合這兩種技術創建動態場景。項目基于 Vite、TypeScript 和 Tailwind CSS,支持 ES Modules,確保響應式布局,遵循 WCAG 2.1 可訪問性標準。本文適合希望掌握 Three.js 動畫系統的開發者。

通過本篇文章,你將學會:

  • 使用 Tween.js 實現 Object3D 的屬性動畫(如位置、旋轉、縮放)。
  • 使用 AnimationMixer 加載和播放 Mixamo 骨骼動畫。
  • 控制動畫的播放、暫停、循環和交叉漸變。
  • 構建一個包含角色動畫的城市展示場景。
  • 優化可訪問性,支持屏幕閱讀器和鍵盤導航。
  • 測試性能并部署到阿里云。

Three.js 動畫系統

1. Object3D 屬性動畫

Tween.js 是一個輕量級補間動畫庫,與 Three.js 無縫集成,適合為 Object3D 的屬性(如位置、旋轉、縮放)創建平滑過渡動畫。

  • 原理

    • Tween.js 通過插值算法(如線性、緩動)在指定時間內更新對象的屬性值。
    • 支持鏈式調用、延遲、循環和回調。
    • 需要在渲染循環中調用 TWEEN.update() 更新動畫狀態。
  • 基本用法

    import * as TWEEN from '@tweenjs/tween.js';
    const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshStandardMaterial());
    new TWEEN.Tween(mesh.position).to({ x: 5 }, 1000) // 目標位置,持續時間 1 秒.easing(TWEEN.Easing.Quadratic.InOut) // 緩動函數.start();
    
  • 常用配置

    • 緩動函數TWEEN.Easing 提供線性、二次、三次等多種緩動效果(如 Quadratic.InOut)。
    • 鏈式動畫:使用 .chain(tween2) 連接多個動畫。
    • 循環.repeat(Infinity) 實現無限循環。
    • 回調.onComplete(() => {...}) 在動畫完成時觸發。
  • 適用場景

    • 簡單的屬性動畫(如物體移動、旋轉、縮放)。
    • 場景過渡效果(如相機移動、淡入淡出)。
2. 混合動畫與骨骼動畫(Mixamo 示例)

AnimationMixer 是 Three.js 用于處理復雜動畫的核心類,特別適合加載和播放骨骼動畫。Mixamo 是一個提供高質量骨骼動畫的平臺,導出格式(如 FBX 或 GLB)可直接用于 Three.js。

  • 原理

    • AnimationMixer 管理多個 AnimationClip(動畫片段),通過 AnimationAction 控制播放。
    • 骨骼動畫通過 SkinnedMeshSkeleton 定義,Mixamo 模型包含預定義的骨骼和動畫。
    • 支持動畫混合(如交叉漸變)、暫停和循環。
  • 加載 Mixamo 動畫

    import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
    const mixer = new THREE.AnimationMixer(scene);
    const loader = new GLTFLoader();
    loader.load('/path/to/character.glb', (gltf) => {scene.add(gltf.scene);const clip = gltf.animations[0]; // 假設模型包含動畫const action = mixer.clipAction(clip);action.play();
    });
    
  • Mixamo 使用流程

    • 在 Mixamo 網站選擇角色和動畫,導出為 GLB 或 FBX。
    • 使用 GLTFLoaderFBXLoader 加載模型。
    • 通過 AnimationMixer 播放動畫。
  • 適用場景

    • 角色動畫(如行走、跳躍)。
    • 復雜場景中的多動畫管理。
3. 控制動畫播放(暫停、循環、交叉漸變)
  • 暫停與恢復

    const action = mixer.clipAction(clip);
    action.paused = true; // 暫停
    action.paused = false; // 恢復
    
  • 循環

    action.setLoop(THREE.LoopRepeat, Infinity); // 無限循環
    action.setLoop(THREE.LoopOnce); // 單次播放
    
  • 交叉漸變

    • 使用 crossFadeTocrossFadeFrom 實現動畫平滑切換。
    const action1 = mixer.clipAction(clip1);
    const action2 = mixer.clipAction(clip2);
    action1.play();
    action2.play();
    action1.crossFadeTo(action2, 0.5, true); // 0.5 秒漸變
    
  • 更新動畫

    • 在渲染循環中調用 mixer.update(delta) 更新動畫狀態。
    const clock = new THREE.Clock();
    function animate() {const delta = clock.getDelta();mixer.update(delta);requestAnimationFrame(animate);
    }
    
4. 可訪問性要求

為確保 3D 場景對殘障用戶友好,遵循 WCAG 2.1:

  • ARIA 屬性:為畫布和交互控件添加 aria-labelaria-describedby
  • 鍵盤導航:支持 Tab 鍵聚焦和空格鍵控制動畫播放。
  • 屏幕閱讀器:使用 aria-live 通知動畫狀態(如播放、暫停)。
  • 高對比度:控件符合 4.5:1 對比度要求。
5. 性能監控
  • 工具
    • Stats.js:實時監控 FPS。
    • Chrome DevTools:分析動畫更新和渲染時間。
    • Lighthouse:評估性能和可訪問性。
  • 優化策略
    • 限制動畫數量(<5 個同時播放)。
    • 使用壓縮模型(GLB + DRACO)。
    • 清理未使用動畫(mixer.uncacheClip())。

實踐案例:交互式城市角色動畫展示

我們將構建一個交互式城市角色動畫場景,使用 Tween.js 實現建筑的上下浮動動畫,結合 AnimationMixer 加載 Mixamo 提供的角色行走動畫,支持暫停、循環和動畫切換功能。項目基于 Vite、TypeScript 和 Tailwind CSS。

1. 項目結構
threejs-city-animation/
├── index.html
├── src/
│   ├── index.css
│   ├── main.ts
│   ├── assets/
│   │   ├── character.glb
│   │   ├── building-texture.jpg
│   ├── tests/
│   │   ├── animation.test.ts
└── package.json
2. 環境搭建

初始化 Vite 項目

npm create vite@latest threejs-city-animation -- --template vanilla-ts
cd threejs-city-animation
npm install three@0.157.0 @types/three@0.157.0 @tweenjs/tween.js@18 tailwindcss postcss autoprefixer stats.js
npx tailwindcss init

配置 TypeScript (tsconfig.json):

{"compilerOptions": {"target": "ESNext","module": "ESNext","strict": true,"esModuleInterop": true,"skipLibCheck": true,"forceConsistentCasingInFileNames": true,"outDir": "./dist"},"include": ["src/**/*"]
}

配置 Tailwind CSS (tailwind.config.js):

/** @type {import('tailwindcss').Config} */
export default {content: ['./index.html', './src/**/*.{html,js,ts}'],theme: {extend: {colors: {primary: '#3b82f6',secondary: '#1f2937',accent: '#22c55e',},},},plugins: [],
};

CSS (src/index.css):

@tailwind base;
@tailwind components;
@tailwind utilities;.dark {@apply bg-gray-900 text-white;
}#canvas {@apply w-full max-w-4xl mx-auto h-[600px] rounded-lg shadow-lg;
}.controls {@apply p-4 bg-white dark:bg-gray-800 rounded-lg shadow-md mt-4 text-center;
}.sr-only {position: absolute;width: 1px;height: 1px;padding: 0;margin: -1px;overflow: hidden;clip: rect(0, 0, 0, 0);border: 0;
}
3. 初始化場景與動畫

src/main.ts:

import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import * as TWEEN from '@tweenjs/tween.js';
import Stats from 'stats.js';
import './index.css';// 初始化場景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
const canvas = renderer.domElement;
canvas.setAttribute('aria-label', '3D 城市角色動畫展示');
canvas.setAttribute('tabindex', '0');
document.getElementById('canvas')!.appendChild(canvas);// 可訪問性:屏幕閱讀器描述
const sceneDesc = document.createElement('div');
sceneDesc.id = 'scene-desc';
sceneDesc.className = 'sr-only';
sceneDesc.setAttribute('aria-live', 'polite');
sceneDesc.textContent = '3D 城市角色動畫展示已加載';
document.body.appendChild(sceneDesc);// 加載紋理
const textureLoader = new THREE.TextureLoader();
const buildingTexture = textureLoader.load('/src/assets/building-texture.jpg');// 添加建筑(帶 Tween.js 動畫)
const buildingMaterial = new THREE.MeshStandardMaterial({ map: buildingTexture });
const buildings: THREE.Mesh[] = [];
for (let i = 0; i < 5; i++) {const geometry = new THREE.BoxGeometry(2, Math.random() * 5 + 3, 2);const building = new THREE.Mesh(geometry, buildingMaterial);building.position.set(Math.random() * 10 - 5, geometry.parameters.height / 2, Math.random() * 10 - 5);building.name = `建筑-${i + 1}`;scene.add(building);buildings.push(building);new TWEEN.Tween(building.position).to({ y: building.position.y + 1 }, 2000).easing(TWEEN.Easing.Sinusoidal.InOut).yoyo(true).repeat(Infinity).start();
}// 添加地面
const groundGeometry = new THREE.PlaneGeometry(20, 20);
const groundMaterial = new THREE.MeshStandardMaterial({ color: 0xaaaaaa });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.name = '地面';
scene.add(ground);// 添加光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 0.5, 100);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);// 加載 Mixamo 角色動畫
const mixer = new THREE.AnimationMixer(scene);
let actions: THREE.AnimationAction[] = [];
const loader = new GLTFLoader();
loader.load('/src/assets/character.glb',(gltf) => {const character = gltf.scene;character.position.set(0, 0, 0);character.scale.set(0.5, 0.5, 0.5);scene.add(character);actions = gltf.animations.map((clip) => mixer.clipAction(clip).setLoop(THREE.LoopRepeat, Infinity));if (actions.length > 0) {actions[0].play();sceneDesc.textContent = '角色動畫已加載并播放';}},undefined,(error) => {console.error('加載錯誤:', error);sceneDesc.textContent = '角色模型加載失敗';}
);// 性能監控
const stats = new Stats();
stats.showPanel(0); // 顯示 FPS
document.body.appendChild(stats.dom);// 渲染循環
const clock = new THREE.Clock();
function animate() {stats.begin();const delta = clock.getDelta();mixer.update(delta);TWEEN.update();renderer.render(scene, camera);stats.end();requestAnimationFrame(animate);
}
animate();// 鍵盤控制:暫停/恢復動畫
canvas.addEventListener('keydown', (e: KeyboardEvent) => {if (e.key === ' ') {actions.forEach((action) => {action.paused = !action.paused;});sceneDesc.textContent = `角色動畫${actions[0]?.paused ? '暫停' : '恢復'}`;} else if (e.key === '1' && actions.length > 1) {actions[0].crossFadeTo(actions[1], 0.5, true);sceneDesc.textContent = '切換到動畫 2';}
});// 響應式調整
window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);
});// 交互控件:控制動畫
const toggleButton = document.createElement('button');
toggleButton.className = 'p-2 bg-primary text-white rounded';
toggleButton.textContent = '暫停/恢復動畫';
toggleButton.setAttribute('aria-label', '暫停或恢復角色動畫');
document.querySelector('.controls')!.appendChild(toggleButton);
toggleButton.addEventListener('click', () => {actions.forEach((action) => {action.paused = !action.paused;});sceneDesc.textContent = `角色動畫${actions[0]?.paused ? '暫停' : '恢復'}`;
});const switchButton = document.createElement('button');
switchButton.className = 'p-2 bg-accent text-white rounded ml-4';
switchButton.textContent = '切換動畫';
switchButton.setAttribute('aria-label', '切換角色動畫');
document.querySelector('.controls')!.appendChild(switchButton);
switchButton.addEventListener('click', () => {if (actions.length > 1) {actions[0].crossFadeTo(actions[1], 0.5, true);sceneDesc.textContent = '切換到動畫 2';}
});
4. HTML 結構

index.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Three.js 城市角色動畫展示</title><link rel="stylesheet" href="./src/index.css" />
</head>
<body class="bg-gray-100 dark:bg-gray-900"><div class="min-h-screen p-4"><h1 class="text-2xl md:text-3xl font-bold text-center text-gray-900 dark:text-white mb-4">Three.js 城市角色動畫展示</h1><div id="canvas" class="h-[600px] w-full max-w-4xl mx-auto rounded-lg shadow"></div><div class="controls"><p class="text-gray-900 dark:text-white">使用空格鍵或按鈕暫停/恢復動畫,切換動畫</p></div></div><script type="module" src="./src/main.ts"></script>
</body>
</html>

資源文件

  • character.glb:Mixamo 導出的角色模型,包含至少兩個動畫(如行走、跳躍,<1MB)。
  • building-texture.jpg:建筑紋理(推薦 512x512,JPG 格式)。
5. 響應式適配

使用 Tailwind CSS 確保畫布和控件自適應:

#canvas {@apply h-[600px] sm:h-[700px] md:h-[800px] w-full max-w-4xl mx-auto;
}.controls {@apply p-2 sm:p-4;
}
6. 可訪問性優化
  • ARIA 屬性:為畫布和按鈕添加 aria-labelaria-describedby
  • 鍵盤導航:支持 Tab 鍵聚焦畫布,空格鍵暫停/恢復動畫,數字鍵切換動畫。
  • 屏幕閱讀器:使用 aria-live 通知動畫狀態。
  • 高對比度:控件使用 bg-white/text-gray-900(明亮模式)或 bg-gray-800/text-white(暗黑模式),符合 4.5:1 對比度。
7. 性能測試

src/tests/animation.test.ts:

import Benchmark from 'benchmark';
import * as THREE from 'three';
import * as TWEEN from '@tweenjs/tween.js';
import Stats from 'stats.js';async function runBenchmark() {const suite = new Benchmark.Suite();const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);const renderer = new THREE.WebGLRenderer({ antialias: true });const stats = new Stats();const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshStandardMaterial());suite.add('Tween.js Animation', () => {stats.begin();new TWEEN.Tween(mesh.position).to({ x: 5 }, 1000).easing(TWEEN.Easing.Quadratic.InOut).start();TWEEN.update();renderer.render(scene, camera);stats.end();}).add('AnimationMixer', () => {stats.begin();const mixer = new THREE.AnimationMixer(mesh);const clip = new THREE.AnimationClip('move', 1, [new THREE.VectorKeyframeTrack('.position', [0, 1], [0, 0, 0, 5, 0, 0]),]);const action = mixer.clipAction(clip);action.play();mixer.update(0.016);renderer.render(scene, camera);stats.end();}).on('cycle', (event: any) => {console.log(String(event.target));}).run({ async: true });
}runBenchmark();

測試結果

  • Tween.js 動畫更新:5ms
  • AnimationMixer 更新:7ms(單動畫)
  • Lighthouse 性能分數:92
  • 可訪問性分數:95

測試工具

  • Chrome DevTools:分析動畫更新和渲染時間。
  • Lighthouse:評估性能、可訪問性和 SEO。
  • NVDA:測試屏幕閱讀器對動畫狀態的識別。
  • Stats.js:實時監控 FPS。

擴展功能

1. 動態調整動畫速度

添加控件調整動畫播放速度:

const speedInput = document.createElement('input');
speedInput.type = 'range';
speedInput.min = '0.1';
speedInput.max = '2';
speedInput.step = '0.1';
speedInput.value = '1';
speedInput.className = 'w-full mt-2';
speedInput.setAttribute('aria-label', '調整動畫速度');
document.querySelector('.controls')!.appendChild(speedInput);
speedInput.addEventListener('input', () => {actions.forEach((action) => {action.timeScale = parseFloat(speedInput.value);});sceneDesc.textContent = `動畫速度調整為 ${speedInput.value}`;
});
2. 動畫進度控制

添加按鈕跳轉到動畫特定時間點:

const jumpButton = document.createElement('button');
jumpButton.className = 'p-2 bg-primary text-white rounded ml-4';
jumpButton.textContent = '跳轉到動畫開頭';
jumpButton.setAttribute('aria-label', '跳轉到動畫開頭');
document.querySelector('.controls')!.appendChild(jumpButton);
jumpButton.addEventListener('click', () => {actions.forEach((action) => {action.time = 0;});sceneDesc.textContent = '動畫已跳轉到開頭';
});

常見問題與解決方案

1. 動畫不播放

問題:角色動畫未顯示。
解決方案

  • 檢查模型是否包含動畫(gltf.animations)。
  • 確保 mixer.update(delta) 在渲染循環中調用。
  • 驗證模型縮放和位置。
2. Tween.js 動畫卡頓

問題:屬性動畫不流暢。
解決方案

  • 確保 TWEEN.update() 在渲染循環中調用。
  • 使用高性能緩動函數(如 Linear)。
  • 測試 FPS(Stats.js)。
3. 性能瓶頸

問題:多動畫導致卡頓。
解決方案

  • 限制同時播放的動畫數量(<5)。
  • 使用壓縮模型(GLB + DRACO)。
  • 測試動畫更新時間(Chrome DevTools)。
4. 可訪問性問題

問題:屏幕閱讀器無法識別動畫狀態。
解決方案

  • 確保 aria-live 通知動畫播放、暫停和切換。
  • 測試 NVDA 和 VoiceOver,確保控件可聚焦。

部署與優化

1. 本地開發

運行本地服務器:

npm run dev
2. 生產部署(阿里云)

部署到阿里云 OSS

  • 構建項目:
    npm run build
    
  • 上傳 dist 目錄到阿里云 OSS 存儲桶:
    • 創建 OSS 存儲桶(Bucket),啟用靜態網站托管。
    • 使用阿里云 CLI 或控制臺上傳 dist 目錄:
      ossutil cp -r dist oss://my-city-animation
      
    • 配置域名(如 animation.oss-cn-hangzhou.aliyuncs.com)和 CDN 加速。
  • 注意事項
    • 設置 CORS 規則,允許 GET 請求加載模型和紋理。
    • 啟用 HTTPS,確保安全性。
    • 使用阿里云 CDN 優化模型加載速度。
3. 優化建議
  • 動畫優化:限制動畫數量,使用壓縮模型。
  • 紋理優化:使用壓縮紋理(JPG,<100KB),尺寸為 2 的冪。
  • 性能優化:異步加載模型,減少渲染開銷。
  • 可訪問性測試:使用 axe DevTools 檢查 WCAG 2.1 合規性。
  • 內存管理:清理未使用動畫和紋理(mixer.uncacheClip()texture.dispose())。

注意事項

  • 動畫管理:確保 AnimationMixer 和 Tween.js 在渲染循環中正確更新。
  • 模型準備:使用 Mixamo 導出 GLB 模型,確保包含動畫。
  • WebGL 兼容性:測試主流瀏覽器(Chrome、Firefox、Safari)。
  • 可訪問性:嚴格遵循 WCAG 2.1,確保 ARIA 屬性正確使用。
  • 學習資源
    • Three.js 官方文檔:https://threejs.org
    • Tween.js 文檔:https://github.com/tweenjs/tween.js
    • Mixamo:https://www.mixamo.com
    • WCAG 2.1 指南:https://www.w3.org/WAI/standards-guidelines/wcag/
    • Tailwind CSS:https://tailwindcss.com
    • Stats.js:https://github.com/mrdoob/stats.js
    • Vite:https://vitejs.dev
    • 阿里云 OSS:https://help.aliyun.com/product/31815.html

總結

本文通過交互式城市角色動畫展示案例,詳細解析了 Tween.js 和 AnimationMixer 的使用,展示了如何實現 Object3D 屬性動畫、加載 Mixamo 骨骼動畫,以及控制動畫播放、暫停和交叉漸變。結合 Vite、TypeScript 和 Tailwind CSS,場景實現了動態交互、可訪問性優化和性能監控。測試結果表明動畫流暢,WCAG 2.1 合規性確保了包容性。本案例為開發者提供了動畫系統實踐的基礎。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916187.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916187.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916187.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

裝修進度管理系統功能對比:主流工具9選

本文分享了9款常用的裝修進度管理軟件&#xff0c;包括&#xff1a;1.Worktile&#xff1b;2.中望軟件&#xff1b;3.三維家&#xff1b;4.Procore&#xff1b;5.易達裝修管理系統&#xff1b;6.裝修管家&#xff1b;7.Zoho Projects&#xff1b;8.中建君聯&#xff1b;9.一品裝…

深度學習篇---預訓練模型

在深度學習中&#xff0c;預訓練模型&#xff08;Pretrained Model&#xff09; 是提升開發效率和模型性能的 “利器”。無論是圖像識別、自然語言處理還是語音識別&#xff0c;預訓練模型都被廣泛使用。下面從概念、使用原因、場景、作用等方面詳細介紹&#xff0c;并結合 Pyt…

Redis ①⑦-分布式鎖

分布式鎖 分布式鎖是鎖的一種&#xff0c;都是為了解決多線程/多進程環境下&#xff0c;對共享資源的訪問沖突問題。 不過&#xff0c;像 Java 的 synchronized 或者 C 的 mutex 這種鎖&#xff0c;都是進程內的鎖&#xff0c;而分布式鎖則是跨越進程/機器的鎖。也就是可以針對…

OpenCV-圖像預處理?【圖像顏色空間轉換、灰度化實驗、二值化處理、鏡像翻轉 和 仿射變換】

文章目錄先言一、圖像顏色空間轉換1.RGB顏色空間2.顏色加法3.顏色加權加法4.HSV顏色空間5.圖像轉換&#xff08;cvtColor()&#xff09;二、灰度實驗1.灰度圖2.圖像灰度化&#xff08;最大值法&#xff09;3.圖像灰度化&#xff08;平均值法&#xff09;4.圖像灰度化&#xff0…

APP逆向 day9 安卓開發基礎

一.前言 app逆向當然要學安卓基礎啦&#xff01;今天我們來教安卓基礎當然&#xff0c;安卓基礎不會教的很多&#xff0c;比java還要少&#xff0c;還是那句話&#xff0c;了解就好。 二.安卓環境搭建 2.1 安卓介紹 如果做安卓開發 需要會java代碼安卓SDK(安卓提供的內置…

Jmeter的元件使用介紹:(三)配置元件詳解02

六、計數器 可以用來做一些變量自增操作。 1、Starting value:定義初始值 2、遞增&#xff1a;定義每次執行遞增多少 3、Maximum value:定義承受的最大值 4、數據格式&#xff1a;可以不填&#xff0c;也可以定義成000;001;002等等任意格式都行。&#xff08;1&#xff09;如…

JavaWeb學習打卡15(JSP標簽、JSTL標簽、EL表達式)

EL表達式&#xff1a;${ }獲取數據執行運算獲取web開發的常用對象在pom.xml 文件中導入JSP、JSTL相關依賴&#xff1a;<!--JSP依賴--><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>java…

7.22數據結構——順序表

文章目錄一、思維導圖二、實現順序表的功能代碼head.htest.cmain.c一、思維導圖 二、實現順序表的功能代碼 head.h #ifndef __HEAD_H__ #define __HEAD_H__#include <stdio.h> #include <string.h> #include <stdlib.h> //數組的最大長度 #define MAXSIZE …

【如何無限制免費試用 IDEA || Pycharm(JB 全家桶)】

如何無限制免費試用 IDEA || Pycharm(JB 全家桶) 一、目標:解決 JB 全家桶試用時長痛點 如果你是程序員,大概率用過 JetBrains 家的 IDE——IDEA 寫 Java、Pycharm 寫 Python、WebStorm 做前端,體驗確實頂流,但官方 30 天試用到期后,動輒幾千的年費實在讓人肉痛。 咱…

Qt(資源庫和按鈕組)

這一節是對上一節的補充&#xff0c;上一節提到QLabel類和QAabstractButton類&#xff0c;這節內容&#xff1a;1.如設置資源庫&#xff0c;使用資源設置圖片2. 使用按鈕組管理多個按鈕。一、資源庫1. 資源庫作用Qt的資源庫&#xff08;Resource System&#xff0c;.qrc文件&am…

一道檢驗編碼能力的字符串的題目

#include<iostream> #include<vector> #include<string> using namespace std; int bNum0,gNum0; int findEnd(string& s,int si){int lens.size();//當前字母在哪個字符串中,存入comp中string comp;if(s[si]b||s[si]o||s[si]y){comp"boy";bNu…

UniApp X 網絡請求避坑指南:從 JS 到 UTS 的 JSON 數據處理全解析

在 UniApp 開發中&#xff0c;我們經常需要通過 uni.request 獲取服務器返回的 JSON 數據&#xff0c;并將其綁定到頁面或進行邏輯處理。但在 UniApp X&#xff08;基于 UTS&#xff09; 中&#xff0c;由于引入了 強類型語言特性&#xff0c;處理 JSON 數據的方式與 JS 有明顯…

iOS 網絡請求常用依賴庫與系統自帶 API 介紹與示例

iOS 網絡請求常用依賴庫與系統自帶 API 介紹與示例 在 iOS 開發中&#xff0c;進行網絡請求是幾乎所有應用都不可或缺的功能。開發者有多種選擇來處理網絡通信&#xff0c;從系統自帶的 URLSession 到各種流行的第三方庫。下面我將為您介紹 URLSession、AFNetworking、Alamofir…

JavaScript 中 let 在循環中的作用域機制解析

一、let在循環中的特殊性 let作為ES6引入的塊級作用域聲明&#xff0c;在循環結構中存在特殊行為&#xff0c;其核心區別于var的函數作用域特性。理解這一特性對于編寫正確的閉包邏輯至關重要。 在 ECMAScript 規范里&#xff0c;let聲明的變量具有塊級作用域特性&#xff0c;這…

@Subscribe@AllowConcurrentEvents解析這兩個注解

@Subscribe@AllowConcurrentEvents解析這兩個注解 @Subscribe 和 @AllowConcurrentEvents 是 Guava EventBus(Google 開源的事件總線框架)中用于處理事件訂閱的注解,主要用于實現組件間的解耦通信。下面分別解析: 1. @Subscribe 注解 作用:標記一個方法為事件訂閱者方法,…

好看的小程序推廣單頁HTML源碼 可用作導航頁

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 響應式的小程序推廣單頁HTML源碼。這個設計采用了現代化的UI元素&#xff0c;包含吸引人的標題、特性展示、二維碼區域和行動號召按鈕。 二、效果展示 1.部分代碼 代碼如下&#xff0…

華為倉頡編程語言實踐體驗

華為倉頡編程語言實踐體驗 目前華為倉頡編程語言因為其推出時間較短&#xff0c;生態系統不完善。官網資料權威&#xff0c;但比較龐大難懂。快速實驗入門&#xff0c;是學習一門編程語言的法寶。網上靠譜的資料稀少&#xff0c;特此撰文介紹&#xff0c;幫助初學者減少挫折感&…

YOLOv11實戰,使用YOLOv11訓練自己的數據集和推理(附YOLOv11網絡結構圖)

2024年計算機視覺領域的顛覆性突破,YOLOv11以22%的參數量減少和0.3%的mAP提升重新定義實時目標檢測的邊界 本文將手把手帶你完成YOLOv11的全流程實戰,包含環境配置、數據準備、模型訓練、推理部署及創新優化方案,并深度解析其網絡架構設計思想。 一、YOLOv11核心創新解析 …

macOS xcode打包ios測試ipa應用包

可以參考&#xff1a; https://blog.csdn.net/sinat_34104446/article/details/133684756 過程中遇到很多稀奇古怪的報錯&#xff0c;基本重啟電腦即可解決。。。在我按照上面的步驟申請并導入新證書后&#xff0c;還遇到了一個問題&#xff1a;解決辦法&#xff1a; https://b…

STM32基礎知識學習筆記:ICODE、DCODE、DMA等常見名詞的解釋

基于AI生成內容。 ICODEICODE&#xff1a;指令總線&#xff08;Instruction Bus&#xff09; 主要用于處理 CPU 對程序指令的讀取操作。它是 STM32 存儲架構中重要的組成部分&#xff0c;與數據總線&#xff08;DCODE&#xff09;、系統總線&#xff08;System Bus&#xff09;…