用 React Three Fiber 實現 3D 城市模型的擴散光圈特效

本文介紹了如何使用 React Three Fiber(R3F)和 Three.js 實現一個從中心向外擴散的光圈特效(DiffuseAperture 組件),并將其集成到城市 3D 模型(CityModel 組件)中。該特效通過動態調整圓柱幾何體的大小和透明度,模擬出類似水波擴散的視覺效果,可用于增強 3D 場景的交互反饋或氛圍營造。我們將從功能原理、實現細節和集成方式三個方面,用通俗易懂的語言講解技術要點。

?更多該系列更新請參考

Three.js 如何控制 GLB 模型的內置屬性實現精準顯示-CSDN博客

React Three Fiber 實現 3D 模型點擊高亮交互的核心技巧-CSDN博客

在 React Three Fiber 中實現 3D 模型點擊擴散波效果-CSDN博客

?什么是 “擴散光圈”?

想象一下,當你往平靜的湖面扔一顆石子,水波會從落點向四周一圈圈擴散,逐漸變大并消失 —— 我們實現的 “擴散光圈” 就是這個效果的 3D 版本。在 CityModel 城市模型中,這個特效表現為:從城市中心(原點)向外擴散的環形光圈,隨著時間推移,光圈半徑不斷增大,同時逐漸變得透明,最終消失;隨后又從中心重新開始擴散,形成循環動畫。

這個特效可以為 3D 城市模型增添動態感,比如:

  • 作為場景加載完成的 “開場動畫”
  • 作為用戶點擊城市中心的交互反饋
  • 模擬信號覆蓋、能量擴散等業務場景

?核心原理:用 “空心圓柱” 模擬光圈

實現這個特效的核心思路很簡單:用一個 “沒有上下底的空心圓柱” 作為光圈的載體,通過動態改變它的大小和透明度,讓它看起來像在 “擴散消失”。

為什么用圓柱?

  • 圓柱的側面是環形,天然適合模擬 “光圈”
  • 可以通過縮放控制半徑(大小),通過透明度控制可見度
  • 隱藏上下底面后,只剩側面,視覺上更像 “一圈光”

?實現細節:讓光圈 “動” 起來的關鍵

1. 基礎結構:構建空心圓柱

// 核心代碼片段:創建圓柱幾何體
<cylinderGeometryargs={[initialRadius, // 頂部半徑(初始大小)initialRadius, // 底部半徑(和頂部相同,保證是正圓)height, // 圓柱高度(光圈的“厚度”,越薄越像2D光圈)64, // 徑向分段數(數值越大,光圈邊緣越平滑)1, // 高度分段數(固定為1即可)true, // 開口(關鍵!讓圓柱沒有上下底,只剩側面)]}
/>

通俗解釋:就像用一張紙條卷成一個空心圓筒,然后把上下兩個口剪掉,只剩中間的環形側面 —— 這就是我們的 “光圈” 雛形。

2. 動態變大:讓光圈 “擴散”

光圈的 “擴散” 效果,本質是讓圓柱的半徑隨時間不斷增大:

// 核心代碼片段:每幀更新半徑
useFrame(() => {// 1. 讓半徑隨時間增大(expandSpeed 控制擴散快慢)radiusRef.current += expandSpeed * 0.016;// 用縮放控制大小(x和z軸同時放大,保證是正圓)apertureRef.current.scale.set(radiusRef.current, // x軸縮放1, // y軸不縮放(保持厚度不變)radiusRef.current, // z軸縮放);
});

通俗解釋:想象圓筒被吹氣球一樣慢慢變大,而且是均勻地向四周擴張,就像水波越來越大。這里的?0.016?是為了適配屏幕刷新率(約 60 幀 / 秒),讓不同設備上的擴散速度一致。

3. 逐漸消失:讓光圈 “淡化”

光擴散的同時會慢慢變淡,通過降低材質的透明度實現:

// 核心代碼片段:控制透明度
useFrame(() => {// 2. 讓透明度隨時間降低(fadeSpeed 控制消失快慢)opacityRef.current -= fadeSpeed * 0.016;material.opacity = Math.max(opacityRef.current, 0); // 透明度不小于0
});

通俗解釋:就像用半透明的紙做的圓筒,隨著擴散,紙張越來越薄,直到完全看不見。

4. 循環動畫:讓光圈 “重復擴散”

當光圈擴散到最大范圍或完全消失后,需要重置狀態重新開始:

// 核心代碼片段:重置條件
if (radiusRef.current > maxRadius || opacityRef.current <= 0) {radiusRef.current = initialRadius; // 半徑變回初始大小opacityRef.current = 1; // 透明度重置為完全可見
}

通俗解釋:這就像設置了一個循環播放的 “水波” 動畫,一波消失后,新的一波從中心重新開始擴散。

5. 紋理增強:讓光圈更生動(可選)

如果想讓光圈有紋路(比如光斑、條紋),可以添加紋理貼圖:

// 核心代碼片段:添加紋理
if (textureUrl) {const texture = textureLoader.load(textureUrl); // 加載紋理圖片materialParams.map = texture; // 應用到材質上
}

通俗解釋:就像給圓筒的側面貼上帶花紋的貼紙,讓光圈看起來更有細節(比如模擬雷達掃描的波紋)。

光波組件代碼(完整)

import { useFrame } from '@react-three/fiber'
import * as THREE from 'three'
import { useRef, useMemo } from 'react'// 擴散光圈組件
export const DiffuseAperture = ({color = ' 0x4C8BF5', // 光圈顏色initialRadius = 0.5, // 初始半徑maxRadius = 10, // 最大擴散半徑expandSpeed = 2, // 擴散速度(半徑增長速率)fadeSpeed = 0.8, // 淡出速度(透明度降低速率)textureUrl, // 側面紋理貼圖URL(可選)height = 1.5, // 從 0.1 增大到 1.5(根據場景比例調整)radialSegments = 128, // 徑向分段數(從64增至128,邊緣更平滑)heightSegments = 3, // 高度分段數(從1增至3,厚度方向有細節)
}: {color?: stringinitialRadius?: numbermaxRadius?: numberexpandSpeed?: numberfadeSpeed?: numberheight?: numbertextureUrl?: string
}) => {const apertureRef = useRef<THREE.Mesh>(null)const radiusRef = useRef(initialRadius) // 跟蹤當前半徑const opacityRef = useRef(1) // 跟蹤當前透明度// 創建圓柱側面材質(帶紋理支持)const material = useMemo(() => {const textureLoader = new THREE.TextureLoader()const materialParams: THREE.MeshBasicMaterialParameters = {color: new THREE.Color(color),transparent: true, // 啟用透明度side: THREE.DoubleSide, // 確保側面可見}// 若提供紋理URL,加載紋理并應用if (textureUrl) {const texture = textureLoader.load(textureUrl)materialParams.map = texture}return new THREE.MeshBasicMaterial(materialParams)}, [color, textureUrl])// 每幀更新圓柱狀態(半徑增大+透明度降低)useFrame(() => {if (!apertureRef.current) return// 1. 更新半徑(逐漸增大)radiusRef.current += expandSpeed * 0.016 // 基于幀率的平滑增長apertureRef.current.scale.set(radiusRef.current, // X軸縮放(控制半徑)1, // Y軸不縮放(保持高度)radiusRef.current, // Z軸縮放(控制半徑))// 2. 更新透明度(逐漸降低)opacityRef.current -= fadeSpeed * 0.016material.opacity = Math.max(opacityRef.current, 0) // 不小于0// 3. 當完全透明或超出最大半徑時,重置狀態(循環擴散)if (radiusRef.current > maxRadius || opacityRef.current <= 0) {radiusRef.current = initialRadiusopacityRef.current = 1}})return (<mesh ref={apertureRef}>{/* 圓柱幾何體:頂面和底面隱藏,僅保留側面 */}<cylinderGeometryargs={[initialRadius, // 頂部半徑initialRadius, // 底部半徑(與頂部相同,確保是正圓柱)height, // 圓柱高度(厚度)64, // 徑向分段數(越高越平滑)1, // 高度分段數true, // 開口(無頂面和底面)]}/><primitive object={material} /></mesh>)
}

集成到城市模型:讓特效 “服務于場景”

我們的擴散光圈不是孤立存在的,需要和城市模型(CityModel 組件)配合使用,才能發揮最大效果:?

1. 位置對齊:讓光圈從城市中心擴散

// 在 CityModel 組件中使用 DiffuseAperture
return (<>{/* 城市模型(已居中到原點) */}<primitive object={scene} ref={modelRef} />{/* 擴散光圈:放在城市中心 */}<DiffuseAperturecolor="#4C8BF5"initialRadius={0.5}maxRadius={20} // 擴散范圍適配城市大小rotation={[Math.PI/2, 0, 0]} // 旋轉90度,讓光圈與地面平行/></>
);

關鍵細節:城市模型通過?modelRef.current.position.sub(center)?已居中到原點(0,0,0),光圈默認也在原點,因此能從城市中心開始擴散。rotation?是為了讓光圈 “躺平” 在地面上(默認是直立的)。

2. 參數適配:讓特效和場景協調

參數作用適配城市模型的建議值
maxRadius光圈最大擴散范圍設為城市寬度的 1.5 倍
height光圈厚度0.05-0.1(薄一點更自然)
expandSpeed擴散速度2-3(太快看不清,太慢拖沓)
color光圈顏色與城市主色調對比(如藍色)

3. 增強體驗:多光圈疊加

通過同時渲染多個參數不同的光圈,可以形成更豐富的效果:

// 多光圈疊加示例
<><DiffuseAperture color="#ff6b3b" maxRadius={15} /><DiffuseAperture color="#ffc154" maxRadius={25} expandSpeed={2.5} /><DiffuseAperture color="#609bdf" maxRadius={35} expandSpeed={3} />
</>

效果:就像同時往水里扔三顆石子,形成的水波一圈套一圈,顏色從內到外漸變(紅→黃→藍),增強層次感。

?完整組件引用代碼

注釋掉的部分是模型的點擊高亮,現在為了演示效果,默認是初始化高亮的

import { useGLTF } from '@react-three/drei'
import { useThree } from '@react-three/fiber'
import { useEffect, useRef } from 'react'
import * as THREE from 'three'
import { useModelManager } from '../../../utils/viewHelper/viewContext'
import { DiffuseAperture } from '../../WaveEffect'export const CityModel = ({ url }: { url: string }) => {const { scene } = useGLTF(url)const modelRef = useRef<THREE.Group>(null)const helper = useModelManager()const { camera } = useThree()// const raycaster = useRef(new THREE.Raycaster())// const pointer = useRef(new THREE.Vector2())const highlightedMeshRef = useRef<THREE.Mesh[]>([])// 存儲所有創建的邊緣線對象const edgeLines = useRef<Map<string, THREE.LineSegments>>(new Map())// 添加邊緣高亮效果const addHighlight = (object: THREE.Mesh) => {if (!object.geometry) return// 創建邊緣幾何體const geometry = new THREE.EdgesGeometry(object.geometry)// 創建邊緣線材質const material = new THREE.LineBasicMaterial({color: 0x4c8bf5, // 藍色邊緣linewidth: 2, // 線寬})// 創建邊緣線對象const line = new THREE.LineSegments(geometry, material)line.name = 'surroundLine'// 復制原始網格的變換line.position.copy(object.position)line.rotation.copy(object.rotation)line.scale.copy(object.scale)// 設置為模型的子對象,確保跟隨模型變換object.add(line)edgeLines.current.set(object.uuid, line)}// 移除邊緣高亮效果const removeHighlight = (object: THREE.Mesh) => {const line = edgeLines.current.get(object.uuid)if (line && object.children.includes(line)) {object.remove(line)}edgeLines.current.delete(object.uuid)}// 處理左鍵點擊事件// const handleClick = (event: MouseEvent) => {//   // 僅響應左鍵點擊(排除右鍵/中鍵/滾輪)//   if (event.button !== 0) return//   // 計算點擊位置的標準化設備坐標//   pointer.current.x = (event.clientX / window.innerWidth) * 2 - 1//   pointer.current.y = -(event.clientY / window.innerHeight) * 2 + 1//   // 執行射線檢測,判斷點擊目標//   detectClickedMesh()// }// 檢測點擊的Mesh并切換高亮狀態// const detectClickedMesh = () => {//   if (!modelRef.current) return//   // 更新射線(從相機到點擊位置)//   raycaster.current.setFromCamera(pointer.current, camera)//   // 檢測與模型的交點(遞歸檢測所有子Mesh)//   const intersects = raycaster.current.intersectObject(modelRef.current, true)//   if (intersects.length > 0) {//     const clickedObject = intersects[0].object as THREE.Mesh//     // 僅處理標記為可交互的Mesh//     if (//       clickedObject instanceof THREE.Mesh &&//       clickedObject.userData.interactive//     ) {//       // 切換高亮狀態:點擊已高亮的Mesh則取消,否則高亮新Mesh//       if (highlightedMeshRef.current?.includes(clickedObject)) {//         console.log('取消高亮', clickedObject.name)//         // 移除邊框高亮//         removeHighlight(clickedObject)//         const newHighlighted = highlightedMeshRef.current.filter(//           (m) => m.name !== clickedObject.name,//         )//         highlightedMeshRef.current = [...newHighlighted]//       } else {//         console.log('高亮', clickedObject.name)//         // 添加邊框高亮//         addHighlight(clickedObject)//         highlightedMeshRef.current = [//           ...highlightedMeshRef.current,//           clickedObject,//         ]//       }//     }//   }// }// 模型加載后初始化useEffect(() => {if (!modelRef.current) returnaddModel()const box = new THREE.Box3().setFromObject(modelRef.current)const center = new THREE.Vector3()box.getCenter(center)const size = new THREE.Vector3()box.getSize(size)// 2. 將模型中心移到世界原點(居中)modelRef.current.position.sub(new THREE.Vector3(center.x, 0, center.z)) // 反向移動模型,使其中心對齊原點const maxDim = Math.max(size.x, size.y, size.z)const fov = 100const cameraZ = Math.abs(maxDim / 2 / Math.tan((Math.PI * fov) / 360))camera.position.set(0, maxDim * 0.3, cameraZ * 1)camera.lookAt(0, 0, 0)// 遍歷模型設置通用屬性并標記可交互modelRef.current.traverse((child) => {if (child instanceof THREE.Mesh) {child.castShadow = truechild.receiveShadow = truechild.material.transparent = true// 標記為可交互(后續可通過此屬性過濾)child.userData.interactive = truechild.material.color.setStyle('#040912')addHighlight(child)// 保存原始材質(用于后續恢復或高亮邏輯)if (!child.userData.baseMaterial) {child.userData.baseMaterial = child.material // 存儲原始材質}}})// 綁定點擊事件監聽// window.addEventListener('click', handleClick)// 組件卸載時清理return () => {// window.removeEventListener('click', handleClick)// 移除所有高亮邊緣線highlightedMeshRef.current.forEach((mesh) => {removeHighlight(mesh)})edgeLines.current.clear()highlightedMeshRef.current = []}}, [modelRef.current])// 添加模型到管理器const addModel = () => {if (modelRef.current) {helper.addModel({id: '模型1',name: '模型1',url: url,model: modelRef.current,})}}return (<><primitive object={scene} ref={modelRef} />{/* 擴散光圈:位于模型中心,與模型平面平行 */}{/* 內層光圈:暖紅色系,擴散范圍最小,亮度最高 */}<DiffuseAperturecolor="#ff6b3b" // 內層暖紅(鮮艷)initialRadius={0.1}maxRadius={15} // 最小擴散范圍expandSpeed={2} // 中等擴散速度fadeSpeed={0.6} // 較慢淡出(停留更久)height={0.08}/>{/* 中層光圈:橙黃色系,銜接內外層 */}<DiffuseAperturecolor="#ffc154" // 中層橙黃(過渡色)initialRadius={0.2}maxRadius={20} // 中等擴散范圍expandSpeed={2.5} // 稍快于內層fadeSpeed={0.7} // 中等淡出速度height={0.06}/>{/* 外層光圈:藍紫色系,擴散范圍最大,亮度最低 */}<DiffuseAperturecolor="#609bdf" // 外層淺藍(冷色)initialRadius={0.3}maxRadius={25} // 最大擴散范圍expandSpeed={3} // 最快擴散速度fadeSpeed={0.8} // 最快淡出(快速消失)height={0.04}/></>)
}

?總結:技術點與應用場景

這個擴散光圈特效的核心是 “動態變化”—— 通過 React Three Fiber 的?useFrame?實現每一幀的更新,用 Three.js 的圓柱幾何體和材質屬性控制視覺表現。它的優勢在于:

  1. 性能友好:只用一個簡單的圓柱幾何體,避免復雜計算
  2. 易于控制:通過參數可輕松調整大小、速度、顏色
  3. 場景適配:旋轉和位置調整可適配任何 3D 模型

在 CityModel 中,這個特效可用于:

  • 城市加載完成的 “開場動畫”
  • 用戶點擊城市中心的 “交互反饋”
  • 模擬信號覆蓋、能量擴散等業務場景

通過這個小功能,我們可以感受到 3D 特效的魅力 —— 看似復雜的視覺效果,往往是由簡單的幾何變換和動態更新組合而成。

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

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

相關文章

【牛客刷題】COUNT數字計數

文章目錄 一、題目介紹二、題解思路三、算法實現四、復雜度分析五 、關鍵步驟解析5.1 數字分解5.2 三種情況處理5.2.1 情況1: d < c u r d < cur d<cur(完整周期)5.2.2 情況2: d = c u r d = cur d=cur(混合周期)5.2.3 情況3: d > c u r d > cur d>cu…

AGV穿梭不“迷路”CCLinkIE轉Modbus TCP的銜接技巧

在AGV控制系統集成中&#xff0c;工程師常面臨一個現實難題&#xff1a;如何讓CCLinkIE總線與Modbus TCP設備實現高效通信&#xff1f;這種跨協議的連接需求&#xff0c;往往需要耗費大量時間調試。本文將通過實際案例解析&#xff0c;為制造行業工程師提供可復用的解決方案。【…

【代碼隨想錄】刷題筆記——哈希表篇

目錄 242. 有效的字母異位詞 349. 兩個數組的交集 202. 快樂數 1. 兩數之和 454. 四數相加 II 383. 贖金信 15. 三數之和 18. 四數之和 242. 有效的字母異位詞 思路 代碼 class Solution {public boolean isAnagram(String s, String t) {if (s.length() ! t.length()…

Python爬蟲實戰:研究messytables庫相關技術

1. 引言 在當今數字化時代,互聯網上存在著大量有價值的數據。然而,這些數據通常以不規則的格式存在,尤其是表格數據,可能包含復雜的表頭、合并單元格、不規則布局等問題。傳統的數據處理工具往往難以應對這些挑戰。 網絡爬蟲技術可以幫助我們從網頁上自動提取數據,而 mes…

Vue3的組件通信方式

通信方式適用層級數據流向復雜度Props/Emits父子組件單向/雙向★☆☆v-model父子組件雙向★☆☆Provide/Inject跨層級組件自上而下★★☆事件總線任意組件任意方向★★★Pinia/Vuex全局狀態任意方向★★☆Refs模板引用父子組件父→子★☆☆作用域插槽父子組件子→父★★☆Web W…

創客匠人:大健康創始人IP如何用“社會責任”構建品牌護城河

一、商業與責任的失衡困局部分大健康IP將利潤置于首位&#xff0c;甚至犧牲用戶利益&#xff0c;導致品牌形象脆弱。某保健品公司因夸大宣傳被曝光后&#xff0c;盡管銷量曾達千萬&#xff0c;卻因缺乏社會認同&#xff0c;一夜之間崩塌&#xff0c;證明沒有社會責任支撐的商業…

AI:機器人未來的形態是什么?

機器人未來的形態將受到技術進步、應用場景需求和社會接受度的綜合影響&#xff0c;以下是對未來機器人形態的預測&#xff0c;涵蓋技術趨勢、設計方向和應用場景&#xff1a; 1. 形態多樣化與通用化 人形機器人&#xff08;Humanoid Robots&#xff09;&#xff1a; 趨勢&…

創建 UIKit 項目教程

一、打開 XCode&#xff0c;選擇 iOS 下的 App&#xff0c;然后點 Next二、Interface 選擇 Storyboard&#xff0c;然后點 Next三、刪掉 Main.storyboard四、刪掉 SceneDelegate.swift五、AppDelegate.swift 只保留第一個函數六、在 AppDelegate.swift 文件里的 application 函…

防爬蟲君子協定 Robots.txt 文件

1.什么是robots.txt ? robots.txt是一個位于網站根目錄的文本文件,用于指導搜索引擎爬蟲如何訪問和抓取網站內容。它遵循特定的語法規則,是網站與爬蟲通信的重要工具。當搜索引擎訪問一個網站時,它首先會檢查該網站的根域下是否有一個叫做robots.txt的純文本文件。Robots.…

淺談 Python 中的 yield——生成器對象與函數調用的區別

我們來看這么一個例子&#xff1a; def greeter():name yield "你是誰&#xff1f;"yield f"你好&#xff0c;{name}"g greeter() print(next(g)) # → "你是誰&#xff1f;" print(g.send("張三")) # → "你好&#xf…

云端docker小知識

1、docker的三個關鍵概念image、container、dockerfile2、docker的container3、dockerfile4、docker制作image5、linux&#xff08;ubuntu&#xff09;安裝docker&#xff08;步驟1和4&#xff09;6、docker基本命令docker images 查看全部鏡像docker rmi -f 1e5f3c5b981a 刪除…

【Elasticsearch】昂貴算法與廉價算法

在 Elasticsearch 里&#xff0c;“昂貴”并不單指“CPU 時間”&#xff0c;而是綜合了 **CPU、內存、磁盤 I/O、網絡傳輸** 以及 **實現復雜度** 的代價。下面把常見“昂貴算法”拆開說&#xff1a;1. **高計算密度的文本算法** ? **match_phrase slop**&#xff08;帶跨距…

深度學習-多分類

?開頭摘要??&#xff1a; 本文將深入探討如何使用PyTorch實現基于Softmax回歸的MNIST手寫數字識別系統。從多分類問題的核心概念出發&#xff0c;詳細解析??One-Hot編碼??技術如何將類別標簽向量化&#xff0c;剖析??交叉熵損失函數??的數學原理及其在訓練中的優化機…

JVM 類加載過程

一、加載&#xff08;Loading&#xff09;目標&#xff1a;把字節碼文件&#xff08;.class&#xff09;“讀入 JVM”&#xff0c;生成類的 “半成品”&#xff08;Class 對象&#xff09;。Bootstrap ClassLoader&#xff08;啟動類加載器&#xff09;&#xff1a;負責加載 JV…

通俗范疇論13 雞與蛋的故事番外篇

通俗范疇論13 雞與蛋的故事番外篇 在上一篇中,我們得到了雞與蛋的Set局部小范疇如下: 雞與蛋 SetSetSet 局部小范疇 如上圖所示,每個雞來自于一個蛋,每個蛋來自于一只雞,如此循環,以至于無窮… 是的,假設雞與蛋兩個對象代表的集合,都是無窮集合,這個系統就沒有問題…

記錄跟隨recyclerview滑動的指示器

老早之前做的一個功能&#xff0c;橫向recyclerview滑動時&#xff0c;底部做跟隨滑動指示器。今天代碼不用了&#xff0c;記錄下代碼。<LinearLayoutandroid:layout_width"match_parent"android:layout_height"wrap_content"android:layout_marginTop&…

快速過一遍Python基礎語法

前言 本文章是深度學習的前導課&#xff0c;對有編程基礎的小伙伴更加的友好&#xff08;C、C&#xff09;&#xff0c;如果完全沒有學過任何一門編程語言也沒有關系&#xff0c;本文章不會涉及到晦澀難懂的原理&#xff0c;只是簡單的帶大家過一遍Python的基礎語法。 下面的操…

[爬蟲實戰] 多進程/多線程/協程-異步爬取豆瓣Top250

相關爬蟲知識點&#xff1a;[爬蟲知識] 深入理解多進程/多線程/協程的異步邏輯 相關爬蟲專欄&#xff1a;JS逆向爬蟲實戰 爬蟲知識點合集 爬蟲實戰案例 逆向知識點合集 前言&#xff1a; 在之前文章中&#xff0c;我們深入探討了多進程、多線程和協程這三大異步技術的工作…

Git系列--1.初始Git

一、背景 目錄 一、背景 二、認識 三、如何在Linux上安裝Git 3.1檢測git是否存在和版本 3.2安裝和卸載git 3.2.1Centos 3.2.2Ubuntu 四、基本操作 4.1創建本地倉庫 4.2必須的配置項 4.3宏觀認識基本分區 我們會根據需求不斷更改我們的文件內容&#xff0c;但有時我們會…

QWidget的屬性

QWidget的屬性 windowOpacityAPI說明windowOpacity()獲取不透明數值&#xff0c;返回float&#xff0c;取值為0.0到1.0&#xff0c;其中0.0為全透明&#xff0c;1.0為完全不透明setWindowOpacity()設置控件的不透明數值注意點&#xff1a;窗口不透明度的變化并非精確的&#xf…