HarmonyOS图形图像处理与OpenGL ES实战

1. HarmonyOS图形系统架构解析

HarmonyOS图形系统采用分层架构模块化设计,为开发者提供高性能的图形渲染能力。整个图形栈从底层驱动到上层应用接口都进行了深度优化,确保在各种设备上都能提供流畅的图形体验。

1.1 图形子系统整体架构

HarmonyOS图形子系统包含四个核心层次:

  • 应用层:提供图形绘制组件和动画框架,支持ArkUI声明式开发
  • 框架层:包含图形服务、窗口管理和合成器,提供统一的图形接口
  • 引擎层:集成2D/3D渲染引擎,包括OpenGL ES、Vulkan等图形API支持
  • 驱动层:通过HDF驱动框架抽象硬件差异,支持GPU硬件加速

这种分层设计使得应用开发者既能使用高级图形组件快速开发,又能通过底层图形API实现高性能自定义渲染。

1.2 图形渲染管线

HarmonyOS图形渲染管线针对移动设备进行了专门优化:

复制代码
// 图形渲染上下文管理
import graphics from '@ohos.graphics';

class GraphicsContext {
    private renderEngine: graphics.RenderEngine | null = null;
    private surface: graphics.Surface | null = null;
    
    // 初始化图形上下文
    async initGraphicsContext(canvas: graphics.Canvas): Promise<boolean> {
        try {
            // 创建渲染表面
            this.surface = graphics.createSurface(canvas);
            
            // 初始化渲染引擎
            const config: graphics.RenderConfig = {
                deviceType: graphics.DeviceType.GPU_PREFERRED,
                enableVSync: true,
                maxFrameRate: 60
            };
            
            this.renderEngine = await graphics.createRenderEngine(this.surface, config);
            console.info('图形上下文初始化成功');
            return true;
        } catch (error) {
            console.error('图形上下文初始化失败:', error);
            return false;
        }
    }
}

2. OpenGL ES基础与环境搭建

2.1 OpenGL ES环境配置

在HarmonyOS中使用OpenGL ES需要进行正确的环境配置和资源管理:

复制代码
import opengles from '@ohos.opengles';
import window from '@ohos.window';

class OpenGLESContext {
    private eglContext: opengles.EGLContext | null = null;
    private eglSurface: opengles.EGLSurface | null = null;
    private windowHandle: window.Window | null = null;
    
    // 初始化OpenGL ES上下文
    async initGLContext(windowHandle: window.Window): Promise<boolean> {
        try {
            this.windowHandle = windowHandle;
            
            // 获取原生窗口
            const nativeWindow = await windowHandle.getNativeWindow();
            
            // 创建EGL显示
            const eglDisplay = opengles.eglGetDisplay(opengles.EGL_DEFAULT_DISPLAY);
            if (eglDisplay === opengles.EGL_NO_DISPLAY) {
                throw new Error('无法获取EGL显示');
            }
            
            // 初始化EGL
            const eglVersion = opengles.eglInitialize(eglDisplay);
            console.info(`EGL初始化成功,版本: ${eglVersion[0]}.${eglVersion[1]}`);
            
            // 选择配置
            const configAttribs = [
                opengles.EGL_RED_SIZE, 8,
                opengles.EGL_GREEN_SIZE, 8,
                opengles.EGL_BLUE_SIZE, 8,
                opengles.EGL_ALPHA_SIZE, 8,
                opengles.EGL_DEPTH_SIZE, 24,
                opengles.EGL_STENCIL_SIZE, 8,
                opengles.EGL_RENDERABLE_TYPE, opengles.EGL_OPENGL_ES3_BIT,
                opengles.EGL_NONE
            ];
            
            const configs = opengles.eglChooseConfig(eglDisplay, configAttribs);
            if (configs.length === 0) {
                throw new Error('没有找到合适的EGL配置');
            }
            
            // 创建上下文
            const contextAttribs = [
                opengles.EGL_CONTEXT_MAJOR_VERSION, 3,
                opengles.EGL_CONTEXT_MINOR_VERSION, 2,
                opengles.EGL_NONE
            ];
            
            this.eglContext = opengles.eglCreateContext(
                eglDisplay, configs[0], opengles.EGL_NO_CONTEXT, contextAttribs
            );
            
            // 创建表面
            this.eglSurface = opengles.eglCreateWindowSurface(
                eglDisplay, configs[0], nativeWindow, null
            );
            
            // 设置为当前上下文
            opengles.eglMakeCurrent(eglDisplay, this.eglSurface, this.eglSurface, this.eglContext);
            
            console.info('OpenGL ES上下文创建成功');
            return true;
        } catch (error) {
            console.error('OpenGL ES上下文创建失败:', error);
            return false;
        }
    }
}

2.2 基础渲染流程

实现完整的OpenGL ES渲染管线:

复制代码
class BasicRenderer {
    private gl: WebGLRenderingContext | null = null;
    private shaderProgram: WebGLProgram | null = null;
    
    // 初始化渲染器
    async initRenderer(canvas: HTMLCanvasElement): Promise<boolean> {
        try {
            // 获取WebGL上下文
            this.gl = canvas.getContext('webgl') as WebGLRenderingContext;
            if (!this.gl) {
                throw new Error('无法获取WebGL上下文');
            }
            
            // 设置视口
            this.gl.viewport(0, 0, canvas.width, canvas.height);
            
            // 初始化着色器
            await this.initShaders();
            
            // 设置清除颜色
            this.gl.clearColor(0.1, 0.1, 0.1, 1.0);
            
            console.info('渲染器初始化成功');
            return true;
        } catch (error) {
            console.error('渲染器初始化失败:', error);
            return false;
        }
    }
    
    // 初始化着色器程序
    private async initShaders(): Promise<void> {
        if (!this.gl) return;
        
        const vertexShaderSource = `
            attribute vec3 aPosition;
            attribute vec4 aColor;
            varying vec4 vColor;
            
            void main() {
                gl_Position = vec4(aPosition, 1.0);
                vColor = aColor;
            }
        `;
        
        const fragmentShaderSource = `
            precision mediump float;
            varying vec4 vColor;
            
            void main() {
                gl_FragColor = vColor;
            }
        `;
        
        // 编译着色器
        const vertexShader = this.compileShader(this.gl.VERTEX_SHADER, vertexShaderSource);
        const fragmentShader = this.compileShader(this.gl.FRAGMENT_SHADER, fragmentShaderSource);
        
        if (!vertexShader || !fragmentShader) {
            throw new Error('着色器编译失败');
        }
        
        // 创建着色器程序
        this.shaderProgram = this.gl.createProgram();
        if (!this.shaderProgram) {
            throw new Error('无法创建着色器程序');
        }
        
        this.gl.attachShader(this.shaderProgram, vertexShader);
        this.gl.attachShader(this.shaderProgram, fragmentShader);
        this.gl.linkProgram(this.shaderProgram);
        
        if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) {
            const error = this.gl.getProgramInfoLog(this.shaderProgram);
            throw new Error(`着色器程序链接失败: ${error}`);
        }
        
        this.gl.useProgram(this.shaderProgram);
    }
    
    // 编译着色器
    private compileShader(type: number, source: string): WebGLShader | null {
        if (!this.gl) return null;
        
        const shader = this.gl.createShader(type);
        if (!shader) return null;
        
        this.gl.shaderSource(shader, source);
        this.gl.compileShader(shader);
        
        if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
            const error = this.gl.getShaderInfoLog(shader);
            console.error(`着色器编译错误: ${error}`);
            this.gl.deleteShader(shader);
            return null;
        }
        
        return shader;
    }
}

3. 高级图形渲染技术

3.1 纹理映射与多重纹理

实现复杂的纹理操作和多重纹理渲染:

复制代码
class TextureRenderer extends BasicRenderer {
    private textures: Map<string, WebGLTexture> = new Map();
    
    // 加载纹理
    async loadTexture(name: string, imageSource: ImageBitmap | HTMLImageElement): Promise<boolean> {
        if (!this.gl) return false;
        
        try {
            const texture = this.gl.createTexture();
            if (!texture) {
                throw new Error('无法创建纹理对象');
            }
            
            this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
            
            // 设置纹理参数
            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
            
            // 上传纹理数据
            this.gl.texImage2D(
                this.gl.TEXTURE_2D, 0, this.gl.RGBA, 
                this.gl.RGBA, this.gl.UNSIGNED_BYTE, imageSource
            );
            
            // 生成mipmap
            this.gl.generateMipmap(this.gl.TEXTURE_2D);
            
            this.textures.set(name, texture);
            console.info(`纹理加载成功: ${name}`);
            return true;
        } catch (error) {
            console.error(`纹理加载失败: ${name}`, error);
            return false;
        }
    }
    
    // 多重纹理渲染
    renderWithMultipleTextures(): void {
        if (!this.gl || !this.shaderProgram) return;
        
        // 激活多个纹理单元
        this.gl.activeTexture(this.gl.TEXTURE0);
        this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures.get('diffuse'));
        
        this.gl.activeTexture(this.gl.TEXTURE1);
        this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures.get('normal'));
        
        this.gl.activeTexture(this.gl.TEXTURE2);
        this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures.get('specular'));
        
        // 设置纹理uniform
        const diffuseLoc = this.gl.getUniformLocation(this.shaderProgram, 'uDiffuseMap');
        const normalLoc = this.gl.getUniformLocation(this.shaderProgram, 'uNormalMap');
        const specularLoc = this.gl.getUniformLocation(this.shaderProgram, 'uSpecularMap');
        
        this.gl.uniform1i(diffuseLoc, 0);
        this.gl.uniform1i(normalLoc, 1);
        this.gl.uniform1i(specularLoc, 2);
    }
}

3.2 光照与材质系统

实现基于物理的渲染(PBR)光照模型:

复制代码
class PBRRenderer extends TextureRenderer {
    // 初始化PBR着色器
    async initPBRShaders(): Promise<void> {
        if (!this.gl) return;
        
        const vertexShaderSource = `
            attribute vec3 aPosition;
            attribute vec3 aNormal;
            attribute vec2 aTexCoord;
            
            uniform mat4 uModelMatrix;
            uniform mat4 uViewMatrix;
            uniform mat4 uProjectionMatrix;
            uniform mat3 uNormalMatrix;
            
            varying vec3 vNormal;
            varying vec3 vPosition;
            varying vec2 vTexCoord;
            
            void main() {
                vec4 worldPosition = uModelMatrix * vec4(aPosition, 1.0);
                vPosition = worldPosition.xyz;
                vNormal = uNormalMatrix * aNormal;
                vTexCoord = aTexCoord;
                
                gl_Position = uProjectionMatrix * uViewMatrix * worldPosition;
            }
        `;
        
        const fragmentShaderSource = `
            precision mediump float;
            
            varying vec3 vNormal;
            varying vec3 vPosition;
            varying vec2 vTexCoord;
            
            uniform vec3 uLightPosition;
            uniform vec3 uLightColor;
            uniform vec3 uCameraPosition;
            
            uniform sampler2D uAlbedoMap;
            uniform sampler2D uNormalMap;
            uniform sampler2D uMetallicRoughnessMap;
            
            // PBR光照计算
            vec3 calculatePBR() {
                // 法线贴图
                vec3 normal = normalize(vNormal);
                vec3 tangentNormal = texture2D(uNormalMap, vTexCoord).xyz * 2.0 - 1.0;
                
                // 光照向量
                vec3 lightDir = normalize(uLightPosition - vPosition);
                vec3 viewDir = normalize(uCameraPosition - vPosition);
                vec3 reflectDir = reflect(-lightDir, normal);
                
                // 基础颜色
                vec3 albedo = texture2D(uAlbedoMap, vTexCoord).rgb;
                
                // 粗糙度和金属度
                vec2 metallicRoughness = texture2D(uMetallicRoughnessMap, vTexCoord).rg;
                float metallic = metallicRoughness.r;
                float roughness = metallicRoughness.g;
                
                // 计算光照
                vec3 diffuse = albedo * max(dot(normal, lightDir), 0.0);
                vec3 specular = calculateSpecular(normal, lightDir, viewDir, metallic, roughness);
                
                return (diffuse + specular) * uLightColor;
            }
            
            void main() {
                vec3 color = calculatePBR();
                gl_FragColor = vec4(color, 1.0);
            }
        `;
        
        await this.compileAndLinkShaders(vertexShaderSource, fragmentShaderSource);
    }
}

4. 性能优化实战

4.1 渲染性能优化

实现多层次渲染性能优化策略:

复制代码
class PerformanceOptimizedRenderer extends PBRRenderer {
    private frameRate: number = 60;
    private lastFrameTime: number = 0;
    private frameCount: number = 0;
    
    // 渲染循环优化
    startRenderLoop(): void {
        const renderFrame = (currentTime: number) => {
            // 计算帧率
            this.calculateFrameRate(currentTime);
            
            // 性能监控
            if (this.needPerformanceAdjustment()) {
                this.adjustRenderingQuality();
            }
            
            // 执行渲染
            this.renderScene();
            
            // 请求下一帧
            requestAnimationFrame(renderFrame);
        };
        
        requestAnimationFrame(renderFrame);
    }
    
    // 计算帧率
    private calculateFrameRate(currentTime: number): void {
        this.frameCount++;
        
        if (currentTime - this.lastFrameTime >= 1000) {
            this.frameRate = this.frameCount;
            this.frameCount = 0;
            this.lastFrameTime = currentTime;
            
            console.info(`当前帧率: ${this.frameRate}FPS`);
        }
    }
    
    // 动态质量调整
    private adjustRenderingQuality(): void {
        if (this.frameRate < 30) {
            // 降低渲染质量
            this.reduceRenderQuality();
        } else if (this.frameRate > 55) {
            // 提高渲染质量
            this.increaseRenderQuality();
        }
    }
    
    // 实例化渲染优化
    setupInstancedRendering(instanceCount: number): void {
        if (!this.gl) return;
        
        // 创建实例化数组
        const instanceData = new Float32Array(instanceCount * 16); // 4x4矩阵
        // 填充实例数据...
        
        const instanceBuffer = this.gl.createBuffer();
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, instanceBuffer);
        this.gl.bufferData(this.gl.ARRAY_BUFFER, instanceData, this.gl.STATIC_DRAW);
        
        // 设置实例属性
        for (let i = 0; i < 4; i++) {
            const attributeLocation = this.gl.getAttribLocation(this.shaderProgram!, `aInstanceMatrix${i}`);
            this.gl.enableVertexAttribArray(attributeLocation);
            this.gl.vertexAttribPointer(attributeLocation, 4, this.gl.FLOAT, false, 64, i * 16);
            this.gl.vertexAttribDivisor(attributeLocation, 1); // 每个实例更新一次
        }
    }
}

4.2 内存管理优化

实现高效的内存管理和资源回收:

复制代码
class MemoryOptimizedRenderer extends PerformanceOptimizedRenderer {
    private resourceManager: ResourceManager;
    
    constructor() {
        super();
        this.resourceManager = new ResourceManager();
    }
    
    // 纹理资源管理
    manageTextureResources(): void {
        // 监控纹理内存使用
        const textureMemory = this.calculateTextureMemoryUsage();
        const maxTextureMemory = 256 * 1024 * 1024; // 256MB
        
        if (textureMemory > maxTextureMemory * 0.8) {
            this.freeUnusedTextures();
        }
    }
    
    // 计算纹理内存使用
    private calculateTextureMemoryUsage(): number {
        let totalMemory = 0;
        
        this.textures.forEach((texture, name) => {
            const textureInfo = this.resourceManager.getTextureInfo(name);
            if (textureInfo) {
                totalMemory += textureInfo.width * textureInfo.height * 4; // RGBA
            }
        });
        
        return totalMemory;
    }
    
    // 释放未使用纹理
    private freeUnusedTextures(): void {
        const unusedTextures = this.resourceManager.getUnusedTextures();
        
        unusedTextures.forEach(textureName => {
            const texture = this.textures.get(textureName);
            if (texture && this.gl) {
                this.gl.deleteTexture(texture);
                this.textures.delete(textureName);
                this.resourceManager.removeTexture(textureName);
                console.info(`释放纹理: ${textureName}`);
            }
        });
    }
}

class ResourceManager {
    private textureUsage: Map<string, number> = new Map();
    private lastAccessTime: Map<string, number> = new Map();
    
    // 记录纹理使用
    recordTextureUsage(textureName: string): void {
        const currentTime = Date.now();
        this.textureUsage.set(textureName, (this.textureUsage.get(textureName) || 0) + 1);
        this.lastAccessTime.set(textureName, currentTime);
    }
    
    // 获取未使用纹理
    getUnusedTextures(threshold: number = 30000): string[] { // 30秒阈值
        const currentTime = Date.now();
        const unused: string[] = [];
        
        this.lastAccessTime.forEach((lastTime, textureName) => {
            if (currentTime - lastTime > threshold) {
                unused.push(textureName);
            }
        });
        
        return unused;
    }
}

5. 实战案例:3D模型渲染器

5.1 模型加载与渲染

实现完整的3D模型加载和渲染系统:

复制代码
import { ModelLoader, Mesh, Material } from '@ohos.graphics.model';

class ModelRenderer extends MemoryOptimizedRenderer {
    private modelLoader: ModelLoader;
    private meshes: Mesh[] = [];
    private materials: Material[] = [];
    
    constructor() {
        super();
        this.modelLoader = new ModelLoader();
    }
    
    // 加载3D模型
    async loadModel(modelPath: string): Promise<boolean> {
        try {
            const modelData = await this.modelLoader.loadFromFile(modelPath);
            
            // 解析网格数据
            this.meshes = modelData.meshes.map(mesh => this.processMeshData(mesh));
            
            // 加载材质和纹理
            await this.loadMaterials(modelData.materials);
            
            console.info(`3D模型加载成功: ${modelPath}`);
            return true;
        } catch (error) {
            console.error(`3D模型加载失败: ${modelPath}`, error);
            return false;
        }
    }
    
    // 处理网格数据
    private processMeshData(meshData: any): Mesh {
        const mesh: Mesh = {
            vertices: new Float32Array(meshData.vertices),
            indices: new Uint16Array(meshData.indices),
            normals: new Float32Array(meshData.normals),
            texCoords: new Float32Array(meshData.texCoords),
            vertexBuffer: null,
            indexBuffer: null
        };
        
        // 创建GPU缓冲区
        mesh.vertexBuffer = this.createVertexBuffer(mesh.vertices);
        mesh.indexBuffer = this.createIndexBuffer(mesh.indices);
        
        return mesh;
    }
    
    // 渲染3D模型
    renderModel(): void {
        if (!this.gl) return;
        
        this.meshes.forEach(mesh => {
            // 绑定顶点缓冲区
            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, mesh.vertexBuffer);
            
            // 设置顶点属性指针
            this.setupVertexAttributes();
            
            // 绑定索引缓冲区
            this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, mesh.indexBuffer);
            
            // 绘制网格
            this.gl.drawElements(
                this.gl.TRIANGLES,
                mesh.indices.length,
                this.gl.UNSIGNED_SHORT,
                0
            );
        });
    }
}

5.2 高级渲染特效

实现后处理特效和高级图形功能:

复制代码
class AdvancedEffectsRenderer extends ModelRenderer {
    private frameBuffer: WebGLFramebuffer | null = null;
    private renderTexture: WebGLTexture | null = null;
    private postProcessingShaders: Map<string, WebGLProgram> = new Map();
    
    // 初始化帧缓冲区
    setupFrameBuffer(width: number, height: number): void {
        if (!this.gl) return;
        
        // 创建帧缓冲区
        this.frameBuffer = this.gl.createFramebuffer();
        this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer);
        
        // 创建渲染纹理
        this.renderTexture = this.gl.createTexture();
        this.gl.bindTexture(this.gl.TEXTURE_2D, this.renderTexture);
        this.gl.texImage2D(
            this.gl.TEXTURE_2D, 0, this.gl.RGBA,
            width, height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null
        );
        
        // 设置纹理参数
        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
        
        // 附加纹理到帧缓冲区
        this.gl.framebufferTexture2D(
            this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0,
            this.gl.TEXTURE_2D, this.renderTexture, 0
        );
        
        // 检查帧缓冲区状态
        if (this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER) !== this.gl.FRAMEBUFFER_COMPLETE) {
            console.error('帧缓冲区设置不完整');
        }
        
        this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
    }
    
    // 应用后处理特效
    applyPostProcessing(): void {
        if (!this.gl || !this.renderTexture) return;
        
        // 绑定默认帧缓冲区
        this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
        
        // 使用后处理着色器
        const postProcessShader = this.postProcessingShaders.get('bloom');
        if (postProcessShader) {
            this.gl.useProgram(postProcessShader);
            
            // 绑定渲染纹理
            this.gl.activeTexture(this.gl.TEXTURE0);
            this.gl.bindTexture(this.gl.TEXTURE_2D, this.renderTexture);
            
            // 绘制全屏四边形
            this.drawFullscreenQuad();
        }
    }
    
    // 全屏四边形渲染
    private drawFullscreenQuad(): void {
        if (!this.gl) return;
        
        const vertices = new Float32Array([
            -1, -1, 0, 0,
            1, -1, 1, 0,
            1, 1, 1, 1,
            -1, 1, 0, 1
        ]);
        
        const indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
        
        // 创建缓冲区并绘制...
    }
}

总结

HarmonyOS图形图像处理系统通过多层级优化硬件抽象,为开发者提供了强大的图形渲染能力。关键技术和最佳实践包括:

核心架构优势

  • 统一图形接口:支持2D/3D图形渲染,提供从高级组件到底层API的完整解决方案
  • 硬件加速优化:充分利用GPU和NPU的图形计算能力
  • 跨设备兼容:自适应不同设备的图形处理能力

性能优化关键

  • 合理的资源管理和内存优化策略
  • 动态质量调整确保流畅的渲染体验
  • 使用实例化渲染等高级技术提升性能

高级图形特性

  • 基于物理的渲染(PBR)实现真实感图形
  • 后处理特效增强视觉表现力
  • 多通道渲染支持复杂视觉效果

通过掌握HarmonyOS图形图像处理技术,开发者能够构建出视觉震撼、性能卓越的图形应用,为用户提供极致的视觉体验。

相关推荐
白鹿第一帅3 小时前
【成长纪实】星光不负 码向未来|我的 HarmonyOS 学习之路与社区成长故事
harmonyos·白鹿第一帅·成都ug社区·csdn成都站·鸿蒙开放能力·鸿蒙学习之路·鸿蒙第一课
俩毛豆3 小时前
【页面路由导航】三步实现页面跳转的完整示例
前端·harmonyos
羑悻的小杀马特5 小时前
探秘仓颉:当函数式编程遇见面向对象王国,当协程风暴席卷并发荒原——从基础语法到实战测试联动的多维编程奇遇记
华为·harmonyos·仓颉·仓颉征文·个人感受·标准库源码·语法剖析
LucianaiB6 小时前
【案例实战】基于分布式能力的跨设备任务协同应用开发
harmonyos·鸿蒙·1024程序员节·案例实战
摘星编程19 小时前
【成长纪实】HarmonyOS Next学习地图:新手避坑指南与核心知识点拆解
学习·华为·harmonyos·鸿蒙开发
爱笑的眼睛111 天前
HarmonyOS生物识别认证深度解析:从指纹到人脸的安全实践
华为·harmonyos
流影ng1 天前
【HarmonyOS】动画—转场动效
华为·harmonyos
cooldream20091 天前
项目实战复盘:基于仓颉语言的鸿蒙智能导航助手(HarmonyNav)
华为·harmonyos·仓颉
爱笑的眼睛111 天前
HarmonyOS ScrollBar深度定制:超越系统默认的滚动体验
华为·harmonyos