React+Three.js 实现 Apple 2025 热成像 logo

news/2025/10/19 18:40:01/文章来源:https://www.cnblogs.com/dragonir/p/19151231

banner

Apple 2025 年度发布会 LOGO 以标志性的苹果图形被注入炽热的火焰质感,色彩从暖调橙黄向冷调湛蓝自然过渡,似高温灼烧下的金属表面,迸发出熔融的光泽;又若无形的能量在流动,勾勒出科技的脉搏与律动,将 “科技” 与 “力量” 的碰撞感具象化,光影的明暗交错削弱了平面的单薄感,赋予其近乎触手可及的质感,同时营造出浓郁的未来感与未知感。

摘要

如上述引用内容,本文将基于 React + Three.js + GLSL 的相关知识,实现 Apple 2025 动态热成像 logo 效果。通过本文的阅读和学习,你将学习到的知识点包括:离屏渲染技术 FBO、交互事件与动态参数控制、Leva 控制面板的应用、视频纹理、遮罩纹理、着色器材质的使用、热成像动画着色器实现和应用等。

效果

本文页面实现效果如下图所示,页面页面中心由 Apple 热成像动态图标构成,图标上面由橙色和蓝色渐变色动态流动,页面底部为蓝色渐变文案。

preview

当使用鼠标 🖱️ 或触控板 👋 网页上按压或拖动 Logo 时,可以看到颜色随手势展开变化,看起来像是模拟真实热量轨迹。

ctrl

本专栏系列代码托管在 Github 仓库【threejs-odessey】,后续所有目录也都将在此仓库中更新

🔗 代码仓库地址:git@github.com:dragonir/threejs-odessey.git

实现

本文代码实现效果参考自:https://github.com/vladmdgolam/apple-event-2025,实现内容模块旨在对其核心知识点进行汇总归纳学习,通过相同的原理并举一反三,实现专属自己的热成像动态 logo 😎

① 资源引入

以下是实现苹果热成像所需的主要依赖资源,其中:OrthographicCamera用于创建平行投影相机、LinearFilter 是纹理采样过滤方式的常量,用于在控制纹理在放大缩小时的平滑过渡效果、ShaderMaterial 用于通过 GLSL创建自定义的着色器材质,是实现本案例效果的关键、VideoTexture可以将视频元素作为数据源创建动态的视频纹理、Leva 是一个轻量级的前端调试工具库,主要用于快速创建交互式控制面板,方便开发者在开发过程中实时调试热成像的各种参数等。其他的依赖都是创建三维场景必须的一些内容,具体作用可自行查阅。

import { OrthographicCamera, DoubleSide, LinearFilter, Mesh, RGBFormat, RepeatWrapping, ShaderMaterial, Texture, TextureLoader, VideoTexture, } from "three"
import { Leva, levaStore, useControls } from "leva"

② 页面场景初始化 HeatmapScene

使用 React Three Fiber 初始化场景、相机等,其中 Leva 组件用于动态可视化调试着色器的多种参数,Scene 组件用于渲染 logo 场景,是整个交互可视化效果的核心统筹层。

return (<div><Leva hidden={levaHidden} /><InfoPanel onToggleControls={() => setLevaHidden((p) => !p)} onRandomizeColors={randomizeColors} /><div ref={containerRef} className="w-[560px] h-[560px] touch-none select-none"><Canvasorthographiccamera={{ position: [0, 0, 1], left: -2, right: 2, top: 2, bottom: -2, near: -1, far: 1, }}gl={{ antialias: true, alpha: true, outputColorSpace: "srgb" }}flat><Scene containerRef={containerRef} /></Canvas></div><div className="dragonir">@dragonir</div></div>
)

③ 实现动态热力图网格 HeatMesh

HeatMesh 组件,它主要通过视频纹理 VideoTexture、绘制纹理 drawTexture 和遮罩纹理 maskTexture 作为数据源,使用着色器材质 ShaderMaterial 渲染一个平面网格 planeGeometr,实现了可实时调整的热力图效果。ShaderMaterial 通过传入自定义顶点着色器和片元着色器实现复杂的热力图色彩映射和动态效果。

export const HeatMesh = ({ drawTexture }: { drawTexture: Texture | null }) => {const timeRef = useRef(0)const videoRef = useRef<HTMLVideoElement | null>(null)const [videoTexture, setVideoTexture] = useState<VideoTexture | null>(null)// Leva 控制面板着色器参数:power(强度)、opacity(透明度)、颜色映射、混合与过渡等参数可实时调整。const { power, opacity, color1, blend1, fade1,maxBlend4 ...} = useControls("Heat Map", {})// 遮罩纹理const maskTexture = useLoader(TextureLoader, "/logo.png")useEffect(() => {if (maskTexture) {maskTexture.wrapS = maskTexture.wrapT = RepeatWrappingmaskTexture.needsUpdate = true}}, [maskTexture])// 视频纹理useEffect(() => {const video = document.createElement("video")video.src = "/apple.mp4"video.loop = truevideo.playsInline = truevideo.autoplay = truevideo.preload = "auto"const onVideoLoad = () => {const texture = new VideoTexture(video)texture.minFilter = LinearFiltertexture.magFilter = LinearFiltertexture.format = RGBFormatsetVideoTexture(texture)}}, [])// 着色器材质const material = useMemo(() => {return new ShaderMaterial({uniforms: {blendVideo: { value: 1.0 },drawMap: { value: drawTexture },textureMap: { value: videoTexture || maskTexture },maskMap: { value: maskTexture },opacity: { value: opacity },amount: { value: 1.0 },color1: { value: color1 },blend: { value: [blend1, blend2, blend3, blend4] },fade: { value: [fade1, fade2, fade3, fade4] },power: { value: power },rnd: { value: 0 },maxBlend: { value: [maxBlend1, maxBlend2, maxBlend3, maxBlend4] },heat: { value: [0, 0, 0, 1.02] },stretch: { value: [1, 1, 0, 0] },},vertexShader: heatVertexShader,fragmentShader: heatFragmentShader,transparent: true,side: DoubleSide,})}, [...])// 动态更新与渲染,通过 useFrame 钩子每帧更新时间和随机值,使热力图呈现动态变化useFrame((_, delta) => {timeRef.current += deltaif (material) {material.uniforms.rnd.value = Math.random()material.uniforms.amount.value = 1.0}})// 渲染一个平面网格,应用自定义着色器材质,作为热力图的载体return (<mesh><planeGeometry /><primitive object={material} /></mesh>)
}

其中 heatVertexShaderheatFragmentShader 是着色器材质的顶点着色器和片元着色器,它们的详细内容见文章最后的着色器模块。

  • 顶点着色器 heatVertexShader:处理网格顶点的位置变换
  • 片元着色器 heatFragmentShader:根据输入纹理的像素值,结合颜色映射参数,计算每个像素的最终颜色,实现热力图效果。

遮罩纹理图片预览

mask

④ 实现绘制渲染器组件 DrawRenderer

DrawRenderer 组件的主要作用是实时处理动态绘制输入,通过双 FBO交替渲染机制,通过缓冲和自定义着色器实现渲染累积与渐隐效果,并接收外部输入的绘制位置、方向、强度等参数,通过自定义着色器实时更新绘制纹理,并将结果传递给外部使用。

// 通过引入 useFBO 创建帧缓冲对象,用于在GPU上存储和处理绘制纹理。
import { useFBO } from "@react-three/drei"
const fboParams = {type: FloatType,format: RGBAFormat,minFilter: LinearFilter,magFilter: LinearFilter,
}
export const DrawRenderer = ({ size = 256, position, direction, drawAmount, onTextureUpdate, sizeDamping, fadeDamping, radiusSize }) => {const { size: canvasSize } = useThree()const dynamicRadius = radiusSizeconst fboA = useFBO(size, size, fboParams)const fboB = useFBO(size, size, fboParams)const renderTargets = useMemo(() => ({current: fboA,previous: fboB}), [fboA, fboB])const { drawScene, drawCamera, material } = useMemo(() => {const drawScene = new Scene()const drawCamera = new OrthographicCamera(-0.5, 0.5, 0.5, -0.5, 0.1, 10)drawCamera.position.z = 1// 通过 ShaderMaterial 定义绘制的核心逻辑,着色器接收外部参数并更新 FBO 纹理const material = new ShaderMaterial({uniforms: {uRadius: { value: [-8, 0.9, dynamicRadius] },uPosition: { value: [0, 0] },uDirection: { value: [0, 0, 0, 0] },uResolution: { value: [canvasSize.width, canvasSize.height, 1] },uTexture: { value: renderTargets.previous.texture },uSizeDamping: { value: sizeDamping },uFadeDamping: { value: fadeDamping },uDraw: { value: 0 },},// 处理平面顶点的坐标转换,确保与 FBO 纹理坐标对齐vertexShader: drawVertexShader,// 根据输入的 uPosition uRadius等参数,在上一帧纹理uTexture的基础上绘制新的渐变,并应用衰减uFadeDamping使旧渐变渐消失,实现动态流动效果fragmentShader: drawFragmentShader,depthTest: false,transparent: true,})// 创建一个平面网格,作为绘制的画布const mesh = new Mesh(new PlaneGeometry(1, 1), material)drawScene.add(mesh)return { drawScene, drawCamera, material }}, [renderTargets, dynamicRadius, sizeDamping, fadeDamping, canvasSize])// Update 着色器变量参数同步:通过 useEffect 将外部传入的 position、direction、drawAmount等参数实时更新到着色器的 uniforms 中useEffect(() => {material.uniforms.uRadius.value[2] = dynamicRadiusmaterial.uniforms.uPosition.value = positionmaterial.uniforms.uDirection.value = directionmaterial.uniforms.uDraw.value = drawAmount}, [material, dynamicRadius, position, direction, drawAmount])// 帧循环:每帧执行以下操作:将上一帧的FBO纹理previous作为输入传递给着色器;切换渲染目标到当前FBO current,渲染绘制场景;交换current和previous的角色,准备下一帧的累积;useFrame(({ gl }) => {const currentTarget = renderTargets.currentconst previousTarget = renderTargets.previousmaterial.uniforms.uTexture.value = previousTarget.textureconst originalTarget = gl.getRenderTarget()gl.setRenderTarget(currentTarget)gl.clear()gl.render(drawScene, drawCamera)gl.setRenderTarget(originalTarget)const temp = renderTargets.currentrenderTargets.current = renderTargets.previousrenderTargets.previous = temp// 通过 onTextureUpdate回调,将当前 FBO 的纹理传递给外部onTextureUpdate(currentTarget.texture)})// 组件本身不渲染任何可见元素,仅负责后台处理绘制纹理return null
}

💡 帧缓冲对象 FBO 与双缓冲机制

  • FBO 作用:FBOGPU 上的离屏渲染目标,用于存储中间绘制结果,避免直接渲染到屏幕,提高效率;
  • 双缓冲设计:创建两个 FBOfboAfboB),通过 renderTargets 管理当前帧 current 和上一帧previous
  • 每帧将上一帧的 FBO 纹理作为输入,绘制新内容到当前 FBO,然后交换两者的角色,实现绘制效果的热力图的渐隐效果。

⑤ 创建渲染场景组件 Scene

Scene 组件是整个交互可视化效果的核心统筹组件,它主要实现的功能包括:整合鼠标交互、参数控制、绘制渲染DrawRenderer 与热力图渲染 HeatMesh,实现鼠标 hover 或者 移动时生成动态热力图。最终实现的效果是:用户在画布上移动鼠标,鼠标轨迹会实时生成带有热力渐变的动态效果,且效果可通过 Leva 面板参数可以实时调整。

import { DrawRenderer } from "./DrawRenderer"
import { HeatMesh } from "./HeatMesh"export const Scene = ({ containerRef, }: { containerRef: React.RefObject<HTMLDivElement | null> }) => {const [mouse, setMouse] = useState<[number, number]>([0, 0])const [heatAmount, setHeatAmount] = useState(0)const [drawTexture, setDrawTexture] = useState<Texture | null>(null)const heatRef = useRef(0)const lastMousePos = useRef<[number, number]>([0, 0])const lastTime = useRef(performance.now())const holdRef = useRef(false)const { camera, size } = useThree((state) => ({ camera: state.camera, size: state.size }))// Leva 控制参数增加const { sizeDamping, fadeDamping, heatSensitivity, heatDecay, radiusSize } = useControls("Hover Heat",{// 控制粗细的变化平滑度sizeDamping: { value: 0.8, min: 0.0, max: 1.0, step: 0.01 },// 控制消失的速度fadeDamping: { value: 0.98, min: 0.9, max: 1.0, step: 0.001 },// 鼠标移动时热度累积的快慢heatSensitivity: { value: 0.25, min: 0.1, max: 2.0, step: 0.05 },// 鼠标停止后热度下降的快慢heatDecay: { value: 0.92, min: 0.8, max: 0.99, step: 0.01 },// 控制单次绘制的范围大小radiusSize: { value: 75, min: 20, max: 300, step: 5 },})// 根据画布尺寸计算相机的宽高比,动态设置 等参数;确保相机的投影矩阵实时更新useEffect(() => {if (camera && camera instanceof OrthographicCamera) {const aspect = size.width / size.heightlet width, heightif (aspect >= 1) {height = 1width = aspect} else {width = 1height = 1 / aspect}camera.left = -width / 2camera.right = width / 2camera.top = height / 2camera.bottom = -height / 2camera.near = -1camera.far = 1camera.updateProjectionMatrix()}}, [camera, size])// 通过pointermove/pointerleave事件监听鼠标在容器内的位置,计算鼠标相对于容器的归一化坐标const handleDOMPointerMove = useCallback((e: PointerEvent) => {if (containerRef.current) {const rect = containerRef.current.getBoundingClientRect()const clientX = e.clientX - rect.xconst clientY = e.clientY - rect.yconst normalizedX = clientX / rect.widthconst normalizedY = clientY / rect.heightconst x = 2 * (normalizedX - 0.5)const y = 2 * -(normalizedY - 0.5)holdRef.current = truesetMouse([x, y])lastMousePos.current = [x, y]lastTime.current = performance.now()}},[containerRef])const handleDOMPointerLeave = useCallback(() => {holdRef.current = false}, [])// 鼠标事件监听useEffect(() => {const canvas = containerRef.currentif (!canvas) returncanvas.addEventListener("pointermove", handleDOMPointerMove)canvas.addEventListener("pointerleave", handleDOMPointerLeave)return () => {canvas.removeEventListener("pointermove", handleDOMPointerMove)canvas.removeEventListener("pointerleave", handleDOMPointerLeave)}}, [handleDOMPointerMove, handleDOMPointerLeave, containerRef])useFrame((_, delta) => {// 热度累积:当鼠标在容器内移动holdRef.current = true时,根据heatSensitivity和帧间隔delta计算热度增量,heatRef.current持续累积最大限制为1.3,避免强度溢出if (holdRef.current) {const heatIncrease = heatSensitivity * delta * 60heatRef.current += heatIncreaseheatRef.current = Math.min(1.3, heatRef.current)setHeatAmount(heatRef.current)// 热度衰减:当鼠标离开容器pointerleave或停止移动时,热度值按 heatDecay衰减系数逐步降低,直到低于0.001时清零;} else if (heatRef.current > 0) {heatRef.current *= heatDecayheatRef.current = heatRef.current < 0.001 ? 0 : heatRef.currentsetHeatAmount(heatRef.current)}// 延迟重置:鼠标停止移动后,通过50ms延迟将 holdRef设为false,避免因短暂停顿导致热度突然中断,模拟自然残留感if (holdRef.current) {setTimeout(() => {holdRef.current = false}, 50)}})const direction = useMemo<[number, number, number, number]>(() => {return [0, 0, 0, 100]}, [])const drawPosition = useMemo<[number, number]>(() => {const x = 0.5 * mouse[0] + 0.5const y = 0.5 * mouse[1] + 0.5return [x, y]}, [mouse])// 向 DrawRenderer 传递绘制数据,接收绘制结果并传递给 HeatMeshreturn (<><DrawRenderersize={256}position={drawPosition}direction={direction}drawAmount={heatAmount}onTextureUpdate={setDrawTexture}sizeDamping={sizeDamping}fadeDamping={fadeDamping}radiusSize={radiusSize}/><HeatMesh drawTexture={drawTexture} /></>)
}

通过 Leva 控制面板动态调节着色器参数。

leva

⑥ 自定义颜色功能实现

可以通过如下的方法,生成随机色彩并将生成的参数传递到着色器,可以实现热力图 logo 颜色的动态切换。

const randomizeColors = useCallback(() => {const hslToHex = (h: number, s: number, l: number) => {s /= 100l /= 100const k = (n: number) => (n + h / 30) % 12const a = s * Math.min(l, 1 - l)const f = (n: number) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))const toHex = (x: number) => Math.round(255 * x).toString(16).padStart(2, "0")return `#${toHex(f(0))}${toHex(f(8))}${toHex(f(4))}`}// 生成6种随机颜色 color2..color7,color1保持黑色const base = Math.floor(Math.random() * 360)const steps = [15, 35, 55, 85, 140, 200]const palette = steps.map((step, i) => hslToHex((base + step) % 360, 80 - i * 4, 50 + (i - 3) * 3))const keys = ["color2", "color3", "color4", "color5", "color6", "color7"] as constkeys.forEach((key, i) => {levaStore.setValueAtPath(`Heat Map.${key}`, palette[i], false)})
}, [])

color1

⑦ 着色器

📦 draw.frag

precision highp float;
uniform float uDraw;
uniform vec3 uRadius;
uniform vec3 uResolution;
uniform vec2 uPosition;
uniform vec4 uDirection;
uniform float uSizeDamping;
uniform float uFadeDamping;
uniform sampler2D uTexture;
varying vec2 vUv;void main() {float aspect = uResolution.x / uResolution.y;vec2 pos = uPosition;pos.y /= aspect;vec2 uv = vUv;uv.y /= aspect;float dist = distance(pos, uv) / (uRadius.z / uResolution.x);dist = smoothstep(uRadius.x, uRadius.y, dist);vec3 dir = uDirection.xyz * uDirection.w;vec2 offset = vec2((-dir.x) * (1.0-dist), (dir.y) * (1.0-dist));vec2 uvt = vUv;vec4 color = texture2D(uTexture, uvt + (offset * 0.01));color *= uFadeDamping;color.r += offset.x;color.g += offset.y;color.rg = clamp(color.rg, -1.0, 1.0);float d = uDraw;color.b += d * (1.0-dist);gl_FragColor = vec4(color.rgb, 1.0);
}

📦 heat.frag

precision highp isampler2D;
precision highp usampler2D;
uniform sampler2D drawMap;
uniform sampler2D textureMap;
uniform sampler2D maskMap;
uniform float amount;
uniform float opacity;
uniform vec3 color1;
uniform vec3 color2;
uniform vec3 color3;
uniform vec3 color4;
uniform vec3 color5;
uniform vec3 color6;
uniform vec3 color7;
uniform vec4 blend;
uniform vec4 fade;
uniform vec4 maxBlend;
uniform float power;
varying vec2 vUv;
varying vec4 vClipPosition;
vec3 linearRgbToLuminance(vec3 linearRgb){float finalColor = dot(linearRgb, vec3(0.2126729, 0.7151522, 0.0721750));return vec3(finalColor);
}
vec3 saturation(vec3 color, float saturation){return mix(linearRgbToLuminance(color), color, saturation);
}
vec3 gradient(float t) {float p1 = blend.x;float p2 = blend.y;float p3 = blend.z;float p4 = blend.w;float p5 = maxBlend.x;float p6 = maxBlend.y;float f1 = fade.x;float f2 = fade.y;float f3 = fade.z;float f4 = fade.w;float f5 = maxBlend.z;float f6 = maxBlend.w;float blend1 = smoothstep(p1 - f1 * 0.5, p1 + f1 * 0.5, t);float blend2 = smoothstep(p2 - f2 * 0.5, p2 + f2 * 0.5, t);float blend3 = smoothstep(p3 - f3 * 0.5, p3 + f3 * 0.5, t);float blend4 = smoothstep(p4 - f4 * 0.5, p4 + f4 * 0.5, t);float blend5 = smoothstep(p5 - f5 * 0.5, p5 + f5 * 0.5, t);float blend6 = smoothstep(p6 - f6 * 0.5, p6 + f6 * 0.5, t);vec3 color = color1;color = mix(color, color2, blend1);color = mix(color, color3, blend2);color = mix(color, color4, blend3);color = mix(color, color5, blend4);color = mix(color, color6, blend5);color = mix(color, color7, blend6);return color;
}
void main() {vec2 duv = vClipPosition.xy/vClipPosition.w;duv = 0.5 + duv * 0.5;vec2 uv = vUv;uv -= 0.5;uv += 0.5;float o = clamp(opacity, 0.0, 1.0);float a = clamp(amount, 0.0, 1.0);float v = o * a;vec4 tex = texture2D(maskMap, uv);float mask = tex.g;float logo = smoothstep(0.58, 0.6, 1.0-tex.b);vec2 wuv = uv;vec3 draw = texture2D(drawMap, duv).rgb;float heatDraw = draw.b;heatDraw *= mix(0.1, 1.0, mask);vec2 offset2 = draw.rg * 0.01;vec3 video = textureLod(textureMap, wuv + offset2, 0.0).rgb;float h = mix(pow(1.0-video.r, 1.5), 1.0, 0.2) * 1.25;heatDraw *= h;float map = video.r;map = pow(map, power);float msk = smoothstep(0.2, 0.5, uv.y);map = mix( map * 0.91, map, msk);map = mix(0.0, map, v);float fade2 = distance(vUv, vec2(0.5, 0.52));fade2 = smoothstep(0.5, 0.62, 1.0-fade2);vec3 finalColor = gradient(map + heatDraw);finalColor = saturation(finalColor, 1.3);finalColor *= fade2;finalColor = mix(vec3(0.0), finalColor, a);gl_FragColor = vec4(finalColor, 1.0);
}

总结

📌 本项目代码主要由 4 个核心组件构成,其中:

  • HeatmapScene:是全局容器,作为顶层组件,管理 Three.js 、Leva 控制面板和其他页面信息;通过 levaStore 全局管理热力图颜色参数,传递容器引用给子组件。
  • Scene:交互与统筹,处理鼠标交互,计算热度值,模拟鼠标轨迹的累积与衰减,串联 DrawRendererHeatMesh,传递交互参数。
  • DrawRenderer:绘制处理,使用双帧缓冲 FBO 实现离屏绘制,高效累积鼠标轨迹,通过自定义着色器处理轨迹的绘制、渐隐与衰减,输出处理后的绘制纹理 drawTextureHeatMesh
  • HeatMesh:热力图渲染,基于 DrawRenderer输出的纹理,结合视频纹理和遮罩纹理,通过自定义着色器生成热力图效果。

📌 本文中主要包含的新知识点如下:

  • Three.js 离屏渲染技术 FBO:通过 useFBO 创建帧缓冲对象,实现 GPU 层面的离屏绘制,避免直接操作 DOM 提升性能;双缓冲机制 fboA/fboB 交替渲染实现绘制轨迹的累积与动态更新。
  • 交互事件与动态参数控制:鼠标键盘事件监听:将用户输入转换为可量化的参数。
  • Leva 控制面板:通过 useControls 实时调整视觉参数,提升开发灵活性。
  • 视频纹理、遮罩纹理、着色器材质的使用等。

想了解其他前端知识或其他未在本文中详细描述的Web 3D开发技术相关知识,可阅读我往期的文章。如果有疑问可以在评论中留言,如果觉得文章对你有帮助,不要忘了一键三连哦 👍

footer

附录

  • [1]. 🌴 Three.js 打造缤纷夏日3D梦中情岛
  • [2]. 🔥 Three.js 实现炫酷的赛博朋克风格3D数字地球大屏
  • [3]. 🐼 Three.js 实现2022冬奥主题3D趣味页面,含冰墩墩
  • [4]. 🦊 Three.js 实现3D开放世界小游戏:阿狸的多元宇宙
  • [5]. 🏡 Three.js 进阶之旅:全景漫游-高阶版在线看房
  • ...
  • 【Three.js 进阶之旅】系列专栏访问 👈
  • 更多往期【3D】专栏访问 👈
  • 更多往期【前端】专栏访问 👈

参考

  • [1]. https://github.com/vladmdgolam/apple-event-2025
  • [2]. https://www.apple.com/apple-events/

本文地址:https://www.cnblogs.com/dragonir/p/19151231 本文作者:dragonir

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

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

相关文章

详细介绍:遥感目标检测数据集汇总,覆盖城市问题/工业安全/农业健康/室内场景……

详细介绍:遥感目标检测数据集汇总,覆盖城市问题/工业安全/农业健康/室内场景……pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fon…

学习华为昇腾AI教材人工智能研发框架部分Day2

学习华为昇腾AI教材人工智能研发框架部分Day2pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &qu…

实用指南:WebSocket和长轮询技术在实时性和资源消耗方面有哪些具体的数据对比?

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年氧化镁厂家最新推荐排行榜,活性氧化镁,肥料级氧化镁,优质供应与技术实力之选!

2025年氧化镁厂家最新推荐排行榜,活性氧化镁,肥料级氧化镁,优质供应与技术实力之选!随着科技的不断进步和工业需求的日益增长,氧化镁、活性氧化镁及肥料级氧化镁在各个行业中的应用越来越广泛。为了帮助采购商筛选…

完整教程:【无人机】无人机群在三维环境中的碰撞和静态避障仿真(Matlab代码实现)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

DAO模式代码阅读及应用

DAO模式代码阅读及应用项目名称 DAO模式代码阅读及应用课程名称 Java程序设计班级 网安XXX指导教师 郑如滨学生姓名 王嘉熙学号 202421336061一、StudenDaoListlmpl.java与StudentDaoArraylmpl.java有何不同?1.Studen…

数据采集与融合作业1

第一题: 核心代码及运行结果点击查看代码 import requests from bs4 import BeautifulSoup import pandas as pd import redef main():"""主函数 - 包含所有爬虫功能"""url = "ht…

CSP-S2023题解

[CSP-S 2023] 密码锁 容易发现,最多状态只有 \(10^5\) 种,所以直接对于每一个密码,处理出来这个密码对应的正确密码可能有哪些,然后给这些密码 \(cnt\)++ ,最后看哪些密码的 \(cnt\) 为 \(n\) 即可。 #include<…

2025年家居ERP/MES/CRM厂家推荐榜单,家居ERP系统,家居MES软件,家居CRM产品,全面解析与选购指南!

2025年家居ERP/MES/CRM厂家推荐榜单,家居ERP系统,家居MES软件,家居CRM产品,全面解析与选购指南!随着家居行业的快速发展,企业对于数字化转型的需求日益迫切。家居ERP(企业资源计划)、MES(制造执行系统)和CRM…

使用autoDL gpu云服务器训练yolo的常用操作 - 东南西北风

网站:https://www.autodl.com/ 购置服务器 上传 文件 1. Linux压缩及解压缩常用命令 1.1 zip :文件压缩(跨平台兼容)基本语法:zip [选项] [压缩文件名.zip] [要压缩的文件/目录]选项 含义-r 递归压缩目录(必须加…

软件工程第三次作业-结对项目

这个作业属于哪个课程 计科23级12班这个作业要求在哪里 作业要求这个作业的目标 训练协同项目软件开发能力,学会使用性能测试工具和实现单元测试优化程序作者:高圣凯3123004566 姚沛鸿 3123004590 GitHub 代码仓库…

运算符与自增自减

运算符与自增自减运算符与自增自减 package cperator;public class Demo01 {public static void main(String[] args) {//二元运算符//Ctrl + D :复制当前行到下一行int a = 10;int b = 20;int c = 30;int d = 40;Syst…

2025年通风天窗/排烟天窗/通风气楼厂家最新推荐榜单,屋顶通风器/顺坡气楼/10A/1型/TC5A/TC12B/屋脊通风天窗公司推荐!

2025年通风天窗/排烟天窗/通风气楼厂家最新推荐榜单,屋顶通风器/顺坡气楼/10A/1型/TC5A/TC12B/屋脊通风天窗公司推荐!随着工业和建筑业的快速发展,通风天窗、排烟天窗、通风气楼等设备在厂房、仓库、办公楼等建筑中…

Azure DevOps Server 25H2 安装手册

Azure DevOps Server 25H2 安装手册Contents1. 概述 •2. 安装手册◦下载安装包 ◦安装操作系统 ◦安装数据库SQL Server ◦安装和配置服务器 ◦验证系统1. 概述经过一年多时间的积累,微软在2025年10月9日发布了最新版…

with关键字

with 关键字 with关键字为我们提供了一种优雅的方式来处理文件操作、数据库连接等需要明确释放资源的场景 with是python中的一个关键字,用于上下文管理协议(context Mangement protocol),它简化了资源管理代码,特…

2025精密球轴承优质厂家推荐:无锡雨露精工,国产高端定制首选!

2025精密球轴承优质厂家推荐:无锡雨露精工,国产高端定制首选!随着科技的不断发展和工业制造水平的提升,精密球轴承在各个领域的应用越来越广泛。从半导体设备到加工中心,从机床主轴到电主轴,从晶圆搬运机械手臂到…

2025 年电磁流量计最新推荐榜,聚焦企业技术实力与市场口碑深度解析

在工业自动化进程加速的当下,电磁流量计作为流体测量的核心设备,广泛应用于环保、化工、市政、核电等关键领域,其性能直接影响企业生产效率与成本控制。当前市场中,电磁流量计厂家数量繁杂,部分企业缺乏核心技术支…

2025 年涡轮流量计厂家企业品牌推荐排行榜,揭秘行业前十优质品牌涡轮流量计公司推荐

引言在工业自动化快速发展的当下,涡轮流量计作为重要的流量测量设备,被广泛应用于节能、环保、市政工程、化工、核电等多个关键行业。然而当前涡轮流量计市场却面临诸多问题,市场上品牌数量众多,产品质量参差不齐,…

2025 年涡街流量计厂家企业品牌推荐排行榜,实力铸就良好口碑涡街流量计公司推荐

引言在工业自动化仪表领域,涡街流量计凭借结构简单牢固、测量精度高、应用范围广等优势,已成为众多行业流量测量的重要设备,广泛应用于节能、环保、市政工程、化工、核电等领域。然而,当前涡街流量计市场却存在诸多…

练习篇:从零开始了解网络空间安全(网导1)

学期2023-2024-1 学号20252332 《网络》第一周学习总结教材学习消化总结重点第一章:网络空间安全概述学科概念:Cybersecurity 在中国相关规定中对网络空间的描述为:互联网,通信网,计算机系统,自动化控制系统....…