• [方案分享] 开发者技术支持-ArkUI 中吸顶操作嵌套滚动冲突问题
    一、问题说明在鸿蒙 ArkUI 开发中,当页面存在多层滚动容器嵌套(如外层Scroll容器嵌套内层List列表)时,出现滚动交互异常:向上滑动列表时,外层Scroll容器优先响应,导致列表内容无法正常向上滚动,反而整体页面向上移动;向下滑动列表到顶部后,内层List无法触发外层Scroll容器继续向下滚动,需手动切换滑动区域才能继续浏览顶部内容;滚动过程中存在卡顿、滑动方向错乱等问题,严重影响用户体验。 (```Scroll() { // 外层滚动容器  Column({ space: 20 }) {    // 顶部固定内容    Row().width("100%").height(200).backgroundColor(Color.Blue)    Column() {      // 吸顶标题      Row(){        Text("吸顶内容").fontColor(Color.White).fontSize(30)          }.width("100%").height(100) .justifyContent(FlexAlign.Center).backgroundColor(Color.Pink)      // 内层滚动列表      List({ space: 10 }) {        ForEach(Array(20).fill(1), () => {          ListItem().height(80).backgroundColor(Color.Grey)        })      }      // 未正确配置嵌套滚动策略    }  }}.width('100%').height("100%")```)二、原因分析嵌套滚动冲突的核心原因是滚动事件传递优先级未明确配置,具体表现为:事件竞争:外层Scroll和内层List均为滚动容器,默认情况下两者都会监听滚动事件,导致滑动操作被 “分流”,无法确定由哪个容器优先响应;滚动方向适配不足:向上滚动(scrollBackward)和向下滚动(scrollForward)的用户需求不同(例如:向下滚动到列表顶部后需继续滚动外层容器查看顶部内容,向上滚动时需优先滚动列表本身),但默认配置未区分方向优先级;布局高度问题:若外层Scroll或内层List未正确设置高度(如未占满屏幕高度),可能导致滚动区域计算异常,进一步加剧冲突。三、解决思路针对嵌套滚动冲突,需通过明确滚动事件传递规则和优化布局配置实现协调:区分滚动方向优先级:根据用户交互习惯,为向上滚动和向下滚动设置不同的事件响应策略 —— 向下滚动时优先让外层容器响应(便于浏览顶部内容),向上滚动时优先让内层列表响应(便于浏览列表内容);使用嵌套滚动配置 API:鸿蒙 ArkUI 提供nestedScroll属性,可通过该属性配置父容器与子容器的滚动优先级,避免事件竞争;确保布局高度正确:外层Scroll需占满屏幕高度(height: "100%"),内层List需根据内容自适应高度,避免因布局异常导致滚动区域无效。四、解决方案通过配置List组件的nestedScroll属性明确滚动优先级,并优化布局高度设置,具体步骤如下:1. 配置嵌套滚动策略在List组件中添加nestedScroll属性,设置向下滚动(scrollForward)时父容器优先响应,向上滚动(scrollBackward)时子容器优先响应:(```List({ space: 10 }) {  // 列表项内容...}.nestedScroll({  scrollForward: NestedScrollMode.PARENT_FIRST, // 向下滚动:父容器(Scroll)优先 scrollBackward: NestedScrollMode.SELF_FIRST    // 向上滚动:子容器(List)优先})```)2. 优化布局高度设置 确保外层Scroll占满屏幕高度,避免因滚动区域不足导致的交互异常:(```Scroll() {  // 内部内容...}.width('100%').height("100%") // 关键:设置外层滚动容器高度为100%```)
  • [技术干货] 开发者技术支持-权限申请失败解决
    1.1 问题说明在鸿蒙应用开发中,基于Stage模型开发需要访问设备存储(读取本地图片)的功能时,出现权限申请失败的问题。具体表现为:调用权限申请接口后,未弹出权限授权弹窗,日志打印“permission request failed, code: 202”;手动在系统设置中为应用开启存储权限后,应用仍无法读取本地文件,提示“no permission to access storage”;该问题在API 9真机(鸿蒙4.0系统)中稳定复现,模拟器中部分场景可正常申请,且仅存储权限出现异常,其他基础权限(如网络权限)可正常获取。1.2 原因分析结合鸿蒙权限管理机制及Stage模型权限申请规范,从4个核心维度分析原因:权限配置缺失:未在应用配置文件(module.json5)中声明存储权限,或权限声明格式错误、权限等级设置不当,导致系统无法识别应用的权限需求,拒绝权限申请请求。权限申请接口使用错误:混淆了Stage模型与FA模型的权限申请接口,使用了已废弃的FA模型接口(如requestPermissionsFromUser),而Stage模型需使用新的权限申请API,接口不兼容导致申请失败。权限申请时机与用户交互规范不符:未在用户触发相关功能(如点击“选择图片”按钮)时申请权限,而是在应用启动时直接申请,违反鸿蒙权限申请交互规范,系统拦截权限申请请求;同时未处理权限申请的回调结果,无法获取失败详情。特殊权限未做额外处理:存储权限属于危险权限,除常规申请外,未处理用户拒绝后再次申请的场景,也未引导用户手动开启权限;部分设备存在系统权限管控加固,需额外申请临时授权或适配系统权限策略。1.3 解决思路针对上述原因,围绕“完善权限配置、使用规范接口、遵循申请时机、处理特殊场景”四大核心思路展开,逐步解决权限申请及使用异常问题:检查并完善应用配置文件中的权限声明,确保权限名称、等级、格式符合鸿蒙Stage模型规范。替换为Stage模型专用的权限申请接口,遵循官方API使用规范,正确调用接口并处理回调结果。调整权限申请时机,在用户触发相关功能时申请权限,符合鸿蒙权限交互规范,避免系统拦截。处理危险权限的特殊场景,包括用户拒绝后再次申请的引导逻辑、手动开启权限的指引,适配不同设备的权限管控策略。 1.4 解决方案1. 完善module.json5权限配置在module.json5文件的“requestPermissions”数组中,声明存储权限(ohos.permission.READ_MEDIA_IMAGES),设置正确的权限等级(level为2,危险权限)和使用说明(reason),确保系统能识别权限需求。  2. 处理特殊场景与兼容性适配针对用户拒绝权限后再次申请的场景,添加二次引导逻辑,避免重复弹出授权弹窗被系统拦截;对于API 9与API 10的权限差异,添加版本判断,适配不同版本的权限名称(如部分旧版本存储权限为ohos.permission.READ_USER_STORAGE)。   1.5 总结本次存储权限申请失败问题,核心诱因是权限配置缺失、接口使用不规范、申请时机不符合交互规范及特殊场景未处理,属于鸿蒙Stage模型权限开发中的典型问题。解决此类权限问题的关键是:熟练掌握Stage模型权限配置与申请流程,区分新旧模型的接口差异,严格遵循鸿蒙权限交互规范,兼顾不同设备与API版本的兼容性。通过完善module.json5权限配置、使用Stage模型专用接口、在用户交互后申请权限、处理永久拒绝等特殊场景,可彻底解决权限申请及存储访问异常的问题。在日常开发中,建议提前梳理应用所需权限,按等级分类处理,危险权限需添加清晰的申请说明和引导逻辑;同时做好版本适配,避免因接口或权限名称变更导致的兼容性问题,提升应用稳定性。
  • [知识分享] 开发者技术支持-基于 Stack 与手势实现推荐岗位层叠卡片滑动切换动效
    1.1 问题说明在求职招聘应用的推荐岗位场景中,用户需要沉浸式浏览不同岗位信息,传统列表式展示交互性弱、视觉层次感不足,且缺乏便捷的滑动切换、投递 / 标记不感兴趣操作方式。本案例基于鸿蒙 Stack 组件、PanGesture 手势、animateTo 动画,实现推荐岗位的层叠卡片布局,支持左右滑动切换岗位、滑动删除 / 确认操作,提升岗位浏览的交互体验与操作效率,适配招聘类应用的核心使用场景。1.2 原因分析层叠布局层级控制难度大:多卡片叠加需精准管控 zIndex、尺寸、偏移、透明度等参数,参数搭配不合理易出现卡片遮挡、层级混乱、视觉层次感缺失的问题。滑动手势与动画协同复杂:PanGesture 的滑动距离、方向识别需与 animateTo 动画的执行时机、参数变更精准同步,若协同逻辑缺失,会出现滑动无响应、动画卡顿、卡片切换不流畅的情况。卡片状态动态更新易出错:滑动切换、删除操作后,剩余卡片需自动补位并更新布局参数,若参数更新逻辑不闭环,会出现卡片错位、布局错乱的问题。跨设备交互适配要求高:不同设备的屏幕尺寸、触摸灵敏度存在差异,若手势识别阈值、动画时长未做适配,会导致部分设备上滑动操作不灵敏、动画效果不协调。1.3 解决思路结构化参数封装:为每个岗位卡片定义包含 zIndex、size、opacity、offsetX、offsetY 的统一参数模型,通过数组管理所有卡片参数,确保布局状态可追溯、可统一更新。组件与手势动画组合使用:以 Stack 组件为基础实现卡片层叠布局,利用 PanGesture 识别用户滑动方向与距离,触发 animateTo 动画并动态更新卡片布局参数,实现手势与动画的无缝协同。闭环状态更新逻辑:滑动操作完成后,通过数组操作实现卡片的删除 / 切换,并自动重新计算剩余卡片的布局参数,完成补位更新,确保布局始终规整。标准化适配与约束:采用常量管理手势识别阈值、动画时长、布局基准参数,明确支持的鸿蒙 API、SDK 及开发工具版本,确保功能在目标设备上稳定运行。 1.4 解决方案核心布局实现(Stack 层叠卡片)基于 Stack 组件实现多岗位卡片的层叠布局,通过循环渲染卡片数组,为每个卡片绑定独立的布局参数,实现视觉上的层叠效果,核心代码如下:// 定义岗位卡片参数模型interface CardModel {  id: number; // 岗位唯一标识  img: string; // 岗位卡片图片资源  size: number; // 卡片尺寸比例  zIndex: number; // 卡片层级  opacity: number; // 卡片透明度  offsetX: number; // X轴偏移量  offsetY: number; // Y轴偏移量  positionInfo: string; // 岗位基础信息}// 定义卡片基础参数与数组@State arr: CardModel[] = []; // 岗位卡片数组@State cardWidth: number = 320; // 卡片基准宽度private baseSize: number = 1; // 基准尺寸比例private baseZIndex: number = 10; // 基准层级private baseOpacity: number = 1; // 基准透明度// Stack层叠布局核心代码Stack({ alignContent: Alignment.Start }) {  // 循环渲染所有岗位卡片  ForEach(this.arr, (item: CardModel, index: number) => {    Column() {      // 岗位卡片主内容(图片+岗位信息,可按需扩展)      Image(item.img)        .objectFit(ImageFit.Contain)        .width(this.cardWidth * item.size)        .height(569 * item.size)      Text(item.positionInfo)        .fontSize(16)        .margin({ top: 10 })        .width(this.cardWidth * item.size)        .textAlign(TextAlign.Center)    }    .zIndex(item.zIndex) // 控制卡片层级,数值越大越在上层    .opacity(item.opacity) // 控制卡片透明度,实现层叠渐变效果    .offset({ x: item.offsetX, y: item.offsetY }) // 控制卡片偏移量    .gesture(this.buildPanGesture(item, index)) // 绑定滑动手势  }, (item) => item.id); // 以唯一id作为循环标识,提升渲染性能}.width('100%').height('100%').alignItems(HorizontalAlign.Center)滑动手势实现(PanGesture)通过 PanGesture 识别用户的滑动方向(左 / 右)和滑动距离,触发对应的卡片操作(切换 / 删除),核心代码如下:// 构建滑动手势private buildPanGesture(card: CardModel, index: number): PanGesture {  return PanGesture()    .onActionUpdate((event: GestureEvent) => {      // 滑动过程中实时更新卡片X轴偏移量,实现跟随滑动效果      if (index === 0) { // 仅对最上层卡片做滑动跟随        this.arr[0].offsetX = event.offsetX;      }    })    .onActionEnd((event: GestureEvent) => {      // 定义滑动阈值,超过阈值则触发卡片操作      const slideThreshold = 100;      if (Math.abs(event.offsetX) > slideThreshold) {        // 根据滑动方向触发对应操作(左滑/右滑可自定义业务逻辑,如标记不感兴趣/投递)        this.handleCardSlide(event.offsetX > 0 ? 'right' : 'left');      } else {        // 未超过阈值,触发回弹动画,恢复卡片初始位置        this.resetCardPosition();      }    });}动画效果实现(animateTo)通过 animateTo 实现卡片滑动切换、删除、回弹的动画效果,在动画闭包中更新卡片布局参数,实现视觉流畅的动效,核心代码如下:// 处理卡片滑动操作(核心动画逻辑)private handleCardSlide(direction: 'left' | 'right') {  this.getUIContext().animateTo({    duration: 500, // 动画时长500ms    curve: Curve.EaseInOut, // 动画曲线,先慢后快再慢,提升流畅度    iterations: 1, // 动画执行次数    playMode: PlayMode.Normal, // 动画播放模式,正常播放    onFinish: () => {      // 动画结束后,删除最上层卡片,并重新计算剩余卡片布局参数      this.arr.shift();      this.resetCardLayout();    }  }, () => {    // 动画闭包中更新卡片参数,实现滑动离场效果    const offsetDistance = direction === 'left' ? -this.cardWidth * 1.5 : this.cardWidth * 1.5;    this.arr[0].offsetX = offsetDistance; // 卡片向指定方向滑出屏幕    this.arr[0].opacity = 0; // 滑出过程中透明度渐变为0  });}// 卡片回弹动画,恢复初始位置private resetCardPosition() {  this.getUIContext().animateTo({    duration: 300,    curve: Curve.EaseOut  }, () => {    this.arr[0].offsetX = 0; // 恢复X轴偏移量为0  });}// 重置剩余卡片布局参数,实现自动补位private resetCardLayout() {  this.arr.forEach((item, index) => {    // 按索引重新计算参数,实现层叠效果(越往后的卡片尺寸越小、层级越低、透明度越低)    item.size = this.baseSize - index * 0.05;    item.zIndex = this.baseZIndex - index;    item.opacity = this.baseOpacity - index * 0.1;    item.offsetX = 0;    item.offsetY = index * 10; // Y轴轻微偏移,增强层叠视觉效果  });}1.5 总结问题与痛点:招聘类应用传统岗位展示方式交互性弱、视觉层次感不足;缺乏便捷的滑动切换操作;多卡片布局易出现层级混乱;手势与动画协同易卡顿,影响用户浏览体验。技术要点:基于 Stack 组件实现岗位卡片层叠布局,通过统一参数模型管控卡片层级、尺寸、偏移等属性;利用 PanGesture 精准识别滑动方向与距离,实现手势交互;结合 animateTo 动画,在闭包中动态更新卡片参数,完成滑动切换、删除、回弹动效;通过数组操作与参数重计算,实现卡片滑出后的自动补位,保证布局规整。实现效果:实现推荐岗位的层叠式视觉展示,支持左右滑动切换岗位、滑动触发投递 / 标记不感兴趣等操作;手势识别灵敏,动画流畅无卡顿,卡片滑出后自动补位,布局始终规整;交互体验贴合用户使用习惯,大幅提升岗位浏览的沉浸感与操作效率。适用场景:求职招聘类应用的推荐岗位、精准匹配岗位场景;各类资讯类应用的卡片式内容推荐、滑动浏览场景;电商类应用的商品推荐、个性化推荐层叠卡片展示场景。
  • [技术干货] 开发者技术支持-UI组件封装与生命周期管理常见问题及解决方案
    1.1 问题说明在近期鸿蒙原生应用开发过程中,聚焦UI组件封装与页面生命周期管理模块,遇到多个核心技术问题,不仅影响开发效率,还导致应用运行稳定性不足、用户体验不佳。一是自定义UI组件封装不规范,组件复用性差,多个页面需要使用同类组件时,需重复编写代码,后续修改维护成本高,且不同页面的同类组件样式、交互不一致,影响应用整体统一性;二是组件通信异常,父组件与子组件、兄弟组件之间数据传递延迟、数据错乱,部分场景下子组件无法接收父组件传递的参数,或参数更新后子组件未及时响应;三是页面生命周期管理不当,页面跳转、退回到后台时,未及时释放组件资源,导致内存泄漏,长期运行后出现应用卡顿、闪退现象;此外,组件与生命周期联动异常,如页面销毁时组件仍在执行异步操作,引发空指针异常,影响应用稳定性。1.2 原因分析针对上述UI组件封装与生命周期管理的问题,经过反复调试、日志排查及鸿蒙原生开发规范梳理,明确核心原因如下:自定义组件封装问题原因:未遵循鸿蒙原生组件封装规范,组件内部耦合度高,将UI渲染、数据处理、事件响应逻辑混写在一起,未实现职责分离;未设计通用组件接口,组件参数传递无统一标准,导致组件复用困难;组件样式未采用鸿蒙原生样式管理机制,直接在组件内部硬编码设置样式,无法实现全局样式统一,且修改样式时需逐一修改每个组件实例。组件通信异常原因:未合理选择鸿蒙组件通信方式,父传子未正确使用@Component的参数传递机制,或未监听参数变化;子传父未正确使用事件回调(EventEmitter),存在回调函数注册失败、触发时机错误的问题;兄弟组件通信未借助公共状态管理或父组件中转,直接尝试跨层级通信,导致数据传递失败;数据传递时未做类型校验,参数类型不匹配导致数据错乱,且未处理空参数场景。生命周期与资源管理问题原因:对鸿蒙页面(AbilitySlice)、组件(Component)的生命周期回调方法理解不透彻,未在合适的生命周期阶段执行资源释放操作(如在onStop而非onDestroy阶段释放资源);组件异步操作(如网络请求、数据解析)未与页面生命周期联动,页面销毁时未取消异步任务,导致任务完成后尝试更新已销毁的组件,引发空指针异常;未使用鸿蒙原生的资源管理工具,组件占用的图片、音频等资源未及时回收,长期积累导致内存泄漏。1.3 解决思路核心解决思路是遵循鸿蒙原生开发规范,聚焦“组件高复用、通信高可靠、生命周期高适配、资源高回收”四大目标,针对性解决组件封装、通信、生命周期管理中的核心问题,兼顾开发效率、应用稳定性与用户体验,具体思路如下:针对组件封装不规范:遵循“单一职责”原则,拆分组件内部逻辑,将UI渲染、数据处理、事件响应分离,封装通用组件接口,统一参数传递标准;采用鸿蒙原生样式管理机制,提取全局公共样式,组件样式继承全局样式,实现样式统一;设计可配置化组件,支持通过参数自定义组件样式、交互逻辑,提升组件复用性。针对组件通信异常:根据组件层级关系选择合适的通信方式,父传子使用@Component参数传递+@Link/@Observed监听参数变化,子传父使用EventEmitter事件回调,兄弟组件通过父组件中转或公共状态管理实现通信;添加数据类型校验与空值处理,确保传递的参数类型正确、非空,避免数据错乱;封装通信工具类,统一管理组件间通信逻辑,降低通信异常概率。针对生命周期与资源管理问题:熟练掌握鸿蒙页面、组件的生命周期回调方法,明确每个生命周期阶段的职责,在合适的阶段(如onDestroy)释放组件资源、取消异步任务;实现组件异步操作与生命周期的联动,监听页面生命周期变化,页面销毁时及时终止异步操作;使用鸿蒙原生资源管理工具,对组件占用的资源进行统一管理,及时回收无用资源,避免内存泄漏。1.4解决方案结合上述解决思路,落地具体可执行的技术解决方案,确保每个问题都有明确的实现路径、可落地的操作步骤,兼顾实操性与规范性,具体如下:规范自定义UI组件封装,提升复用性拆分组件逻辑,将组件拆分为UI渲染层、数据处理层、事件响应层,UI渲染层负责组件界面展示,数据处理层负责数据解析与处理,事件响应层负责处理用户交互事件,实现职责分离;封装通用组件接口,定义统一的参数传递标准,明确参数名称、类型、默认值,组件通过接口接收参数,支持参数动态更新;统一样式管理,在ability_main.xml中提取全局公共样式(如字体大小、颜色、边距),组件样式通过style属性继承全局样式,如需自定义样式,可通过参数覆盖全局样式,实现应用整体样式统一;四是设计可配置化组件,例如封装通用按钮组件,支持通过参数配置按钮文本、颜色、尺寸、点击事件,适配不同页面的使用场景,无需重复编写按钮组件代码,提升开发效率。解决组件通信异常,保障通信可靠父传子通信优化,父组件通过@Component的build方法向子组件传递参数,子组件使用@Link注解监听参数变化,当父组件参数更新时,子组件自动刷新;同时添加参数类型校验,使用typeof判断参数类型,若类型不匹配,弹出日志提示并使用默认参数,避免数据错乱;子传父通信优化,子组件通过EventEmitter创建事件,在用户交互时触发事件并传递数据,父组件在引用子组件时,注册事件回调函数,接收子组件传递的数据并处理,确保事件回调注册成功、触发时机正确;三是兄弟组件通信优化,通过父组件中转实现通信,兄弟组件将需要传递的数据发送给父组件,父组件接收后转发给目标兄弟组件,或使用鸿蒙原生公共状态管理API,创建全局公共状态,兄弟组件共同监听、修改公共状态,实现数据同步;四是封装通信工具类,统一管理组件间通信逻辑,包含参数校验、事件注册、数据传递等方法,降低通信异常概率,便于后续维护。优化生命周期管理,避免内存泄漏明确生命周期职责,熟练掌握AbilitySlice的onStart、onActive、onInactive、onStop、onDestroy及Component的onAttachedToWindow、onDetachedFromWindow等生命周期方法,在onDestroy方法中释放组件占用的资源(如关闭数据库连接、释放图片资源),在onStop方法中暂停组件异步操作;(2)实现异步操作与生命周期联动,封装异步任务管理类,每个异步任务(如网络请求、数据解析)创建时,绑定页面生命周期,监听页面onDestroy事件,当页面销毁时,自动取消异步任务,避免任务完成后更新已销毁的组件,引发空指针异常;资源回收优化,使用鸿蒙原生的ResourceManager资源管理工具,组件使用图片、音频等资源时,通过ResourceManager获取资源,组件销毁时,调用resourceManager.release()方法释放资源;同时使用鸿蒙Profiler工具监测内存使用情况,排查内存泄漏问题,及时优化资源回收逻辑。通用优化(1)封装组件模板,针对高频使用的组件(如按钮、输入框、列表项),创建组件模板,后续开发直接复用模板,减少重复编码;(2)添加组件异常处理,在组件初始化、参数接收、事件响应过程中,添加try-catch异常捕获,避免组件异常导致整个页面崩溃,同时记录异常日志,便于后续排查;(3)规范组件命名与注释,组件命名遵循“功能+Component”格式,添加详细注释,说明组件功能、参数含义、使用场景,提升代码可读性与可维护性。1.5总结本次鸿蒙原生开发中,核心围绕UI组件封装与生命周期管理的三大核心问题(组件封装不规范、组件通信异常、生命周期与资源管理不当)展开排查与解决,通过规范组件封装、优化组件通信方式、完善生命周期管理、强化资源回收等一系列技术手段,成功解决了组件复用性差、通信异常、内存泄漏、应用卡顿闪退等问题,确保应用在不同版本、不同类型的鸿蒙设备上稳定运行,提升了开发效率与用户体验,符合鸿蒙原生开发规范。通过本次开发实践,总结出鸿蒙原生UI组件封装与生命周期管理的核心经验:一是必须遵循鸿蒙原生开发规范,尤其是组件封装、生命周期的相关规范,避免自定义实现与系统特性冲突;二是坚持“单一职责”原则,拆分组件逻辑、规范接口设计,是提升组件复用性、降低维护成本的关键;三是合理选择组件通信方式,做好参数校验与空值处理,才能保障组件间通信的可靠性;四是重视生命周期管理与资源回收,熟练掌握每个生命周期阶段的职责,及时释放资源、取消异步任务,是避免内存泄漏、提升应用稳定性的核心。后续开发中,将进一步优化组件封装的灵活性与可扩展性,沉淀可复用的组件库,覆盖更多UI场景;同时持续优化生命周期管理与资源回收逻辑,结合鸿蒙原生新特性,提升应用运行性能;此外,加强团队开发规范培训,确保所有开发人员遵循统一的组件封装、生命周期管理标准,规避同类问题重复出现,提升鸿蒙原生应用的开发质量与效率。
  • [互动交流] 什么是云渲染?3 分钟读懂高效渲染新范式!
     云渲染的核心逻辑,是借助远端大规模服务器集群的算力,替代本地设备完成高负载的渲染计算。这种模式能实现多任务并行加速,让影视动画、建筑设计等对渲染效率要求极高的行业,彻底摆脱算力瓶颈。以 Renderbus 瑞云渲染为代表的专业平台,不仅提供全版本软件兼容与技术支持,还采用灵活的按需付费机制。在 5G 与云计算技术的双重驱动下,云渲染的应用场景与性能表现仍在持续进化。 在 5G、人工智能与云服务技术日趋成熟的今天,云渲染已从专业领域走向大众视野。通俗而言,它是一种 “算力租赁” 模式:用户将本地制作的渲染任务上传至云端,由远程超级计算机集群完成复杂的光影、材质运算,最终将成品画面回传至本地供下载使用。在此过程中,本地终端将彻底释放,用户无需保持软件开启或设备开机,可同步开展建模、绘图等其他工作。这种模式的核心优势,在于突破了单台设备的性能限制,能够并行处理数十个子任务,将原本需要数天的渲染周期,压缩至数小时,极大地提升了项目交付效率。一、云渲染的四大核心优势1. 并行算力加持,效率指数级提升云渲染平台的算力储备,是普通本地电脑无法企及的。相较于本地单设备渲染,云端可调动 10 台、20 台甚至更多节点同时工作,单集群最高可支持 10000 个节点的弹性调度。这种高弹性算力的核心价值,在于并行处理能力。面对包含数十个子任务的大型项目,本地设备往往需要逐个渲染,耗时漫长;而云渲染可一次性启动所有任务,大幅缩短交付周期。尤其在紧急出图、客户临时改稿等场景下,云渲染能有效规避因效率不足导致的项目风险。2. 全栈技术兼容,专业服务兜底云渲染已形成成熟的产业生态,深度适配影视动画、建筑可视化等领域的复杂需求。针对行业内软件版本迭代快、插件兼容性复杂的痛点,专业平台会持续完成技术适配与容错测试。 以主流工具为例,从 3ds Max 2022、Maya 到 V-Ray 5.0、Corona 6.0,云渲染平台已实现全流程兼容。无论是软件操作难题,还是渲染参数(如伽马值)设置问题,均有专业技术团队提供解决方案。目前,平台已支持 Maya、Cinema 4d、Blender、Redshift、Arnold 等几乎所有主流软件与插件,同时开放自定义插件上传通道,满足个性化创作需求。3. 释放本地资源,降低设备损耗本地渲染往往会耗尽设备算力,导致系统卡顿,更会加速硬件老化 —— 长期高负载运行可能引发散热故障,甚至损坏硬件,无形中增加了设备维护成本。而云渲染将计算任务转移至云端后,本地设备的压力将大幅降低。用户提交任务后,可直接关闭渲染软件甚至设备,既减少了硬件损耗,又能将本地算力用于创意设计工作,实现 “创作与渲染” 双线并行。                                                                       4. 弹性计费模式,成本可控灵活云渲染的收费机制完全基于实际使用量,即根据算力规格与使用时长计费。算力规格越高,渲染速度越快,对应的费用也会相应增加。平台提供多档位线程选择,兼顾不同用户的速度需求与预算限制。虽然云渲染需要支付一定的算力费用,但这笔显性成本对应的是专业的算力服务、运维保障与时间效率。相较于本地设备的升级成本与隐性损耗,云渲染的性价比优势十分显著。四、总结作为数字化时代的重要服务形态,云渲染正为越来越多行业赋能。付费使用算力服务的模式,本质上是用成本换取效率,符合行业高质量发展的趋势。随着 5G、云计算、云存储技术的不断突破,云渲染将在算力调度、实时渲染等领域实现更多创新,持续推动视觉创作行业的效率革命。
  • [技术干货] 求助,aarch64 上的麒麟系统 + Ascend310P 如何使用 VTK?
    很显然无法直接 pip install,自己找源码编译,需要依赖 OpenGL 而 Ascend 计算卡又不支持。如果安装 mesa 又报错各种依赖装不上。论坛上有朋友成功搞定过的嘛?
  • [技术干货] 浏览器渲染机制
    浏览器渲染机制浏览器采用流式布局模型(Flow Based Layout)浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tree)。有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。2. 重绘由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outline, visibility, color、background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。3. 回流回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。<body> <div class="error">     <h4>我的组件</h4>     <p><strong>错误:</strong>错误的描述…</p>     <h5>错误纠正</h5>     <ol>         <li>第一步</li>         <li>第二步</li>     </ol> </div> </body>在上面的HTML片段中,对该段落(标签)回流将会引发强烈的回流,因为它是一个子节点。这也导致了祖先的回流(div.error和body – 视浏览器而定)。此外,和也会有简单的回流,因为其在DOM中在回流元素之后。大部分的回流将导致页面的重新渲染。回流必定会发生重绘,重绘不一定会引发回流。4. 浏览器优化现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。主要包括以下属性或方法:offsetTop、offsetLeft、offsetWidth、offsetHeightscrollTop、scrollLeft、scrollWidth、scrollHeightclientTop、clientLeft、clientWidth、clientHeightwidth、heightgetComputedStyle()getBoundingClientRect()所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。5. 减少重绘与回流CSS使用 transform 替代 top使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。<div>   <a> <span></span> </a> </div> <style>   span {     color: red;   }   div > a > span {     color: red;   } </style>对于第一种设置样式的方式来说,浏览器只需要找到页面中所有的 span 标签然后设置颜色,但是对于第二种设置样式的方式来说,浏览器首先需要找到所有的 span 标签,然后找到 span 标签上的 a 标签,最后再去找到 div 标签,然后给符合这种条件的 span 标签设置颜色,这样的递归过程就很复杂。所以我们应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame。避免使用CSS表达式,可能会引发回流。将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会自动将该节点变为图层。CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。JavaScript避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
  • [技术干货] 浏览器渲染机制
    浏览器渲染机制浏览器采用流式布局模型(Flow Based Layout)浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tree)。有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。2. 重绘由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outline, visibility, color、background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。3. 回流回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。<body> <div class="error">     <h4>我的组件</h4>     <p><strong>错误:</strong>错误的描述…</p>     <h5>错误纠正</h5>     <ol>         <li>第一步</li>         <li>第二步</li>     </ol> </div> </body>在上面的HTML片段中,对该段落(标签)回流将会引发强烈的回流,因为它是一个子节点。这也导致了祖先的回流(div.error和body – 视浏览器而定)。此外,和也会有简单的回流,因为其在DOM中在回流元素之后。大部分的回流将导致页面的重新渲染。回流必定会发生重绘,重绘不一定会引发回流。4. 浏览器优化现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。主要包括以下属性或方法:offsetTop、offsetLeft、offsetWidth、offsetHeightscrollTop、scrollLeft、scrollWidth、scrollHeightclientTop、clientLeft、clientWidth、clientHeightwidth、heightgetComputedStyle()getBoundingClientRect()所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。5. 减少重绘与回流CSS使用 transform 替代 top使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。<div>   <a> <span></span> </a> </div> <style>   span {     color: red;   }   div > a > span {     color: red;   } </style>对于第一种设置样式的方式来说,浏览器只需要找到页面中所有的 span 标签然后设置颜色,但是对于第二种设置样式的方式来说,浏览器首先需要找到所有的 span 标签,然后找到 span 标签上的 a 标签,最后再去找到 div 标签,然后给符合这种条件的 span 标签设置颜色,这样的递归过程就很复杂。所以我们应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame。避免使用CSS表达式,可能会引发回流。将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会自动将该节点变为图层。CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。JavaScript避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
  • [技术干货] 助你上手Vue3全家桶之Vue3教程[转载]
    前言这些内容是博主在学习过程中记录下来的,有一些不重要的点就跳过了,需要时自行查询文档。其实V2到V3的学习成本不高,熟悉V2的话,看完这篇文章就可以上手V3。Vue3官网在线源码编译地址1,setupsetup是所有Composition API的容器,值为一个函数。组件中所用到的数据、方法等等,均要配置在setup中,它会在beforeCreate之前执行一次,注意:V3里this不再是指向Vue实例,访问this会是undefined1.1,返回值若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。若返回一个渲染函数:则可以自定义渲染内容。1.2,注意点尽量不要与V2配置混用V2配置(data、methos、computed…)中可以访问到setup中的属性、方法。但在setup中不能访问到V2配置(data、methods、computed…)。如果有重名, setup优先。setup不能是一个async函数因为返回值不再return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)1.3,语法<script>import { ref, reactive } from 'vue'export default {    name: 'Home',    setup(props, context) {        const title = ref('标题')        const data = reactive({            value: '哈哈哈'        })        return {          title,          data        }    }}</script>1.4,setup的参数props:值为对象,包含组件外部传递过来,且组件内部声明接收了的属性context:上下文对象attrs: 值为对象,包含组件外部传递过来,但没有在props配置中声明的属性, 相当于this.$attrsslots: 收到的插槽内容, 相当于this.$slotsemit: 分发自定义事件的函数, 相当于this.$emit2,ref 创建响应式数据使用ref可以创建一个包含响应式数据的引用对象(reference对象,简称ref对象),可以是基本类型、也可以是对象。语法// 创建const xxx = ref(value)// 使用xxx.value// 在模板中<div>{{xxx}}</div>3,reactive 创建响应式数据定义一个对象类型的响应式数据,内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作语法// 创建const xxx = reactive({    xxx: ''})// 使用xxx.xxx4,computed 计算属性与V2中computed配置功能一致语法import { computed } from 'vue'setup(){    // 简写语法    let fullName = computed(() => {        return person.firstName + '-' + person.lastName    })        // 完整语法    let fullName = computed({        get(){            return person.firstName + '-' + person.lastName        },        set(value){            const nameArr = value.split('-')            person.firstName = nameArr[0]            person.lastName = nameArr[1]        }    })        return fullName5,watch 监听与V2中watch配置功能一致,语法有点改动语法情况一:监视ref定义的响应式数据watch(sum, (newValue, oldValue) => {    console.log('sum变化了', newValue, oldValue)}, {immediate:true})情况二:监视多个ref定义的响应式数据watch([sum, msg], (newValue,oldValue) => {    console.log('sum或msg变化了', newValue,oldValue)}) 情况三:监视reactive定义的响应式数据// 若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue// 若watch监视的是reactive定义的响应式数据,则强制开启了深度监视watch(person, (newValue, oldValue) => {    console.log('person变化了', newValue, oldValue)}, { immediate:true, deep:false }) // 此处的deep配置不再奏效情况四:监视reactive定义的响应式数据中的某个属性watch(() => person.job, (newValue, oldValue) => {    console.log('person的job变化了', newValue, oldValue)}, { immediate:true, deep:true }) 情况五:监视reactive定义的响应式数据中的某些属性watch([() => person.job, () => person.name], (newValue, oldValue) => {    console.log('person的job变化了', newValue, oldValue)}, { immediate:true, deep:true })特殊情况:此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效watch(() => person.job, (newValue, oldValue) => {    console.log('person的job变化了', newValue, oldValue)}, { deep:true })6,watchEffect 监听回调和watch的区别是,watch既要指明监视的属性,也要指明监视的回调。而watchEffect,不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性,不用写返回值。语法// 回调中用到的数据只要发生变化,则直接重新执行回调watchEffect(() => {    const x1 = sum.value    const x2 = person.age    console.log('watchEffect配置的回调执行了')})7,生命周期生命周期全都写在setup中7.1,改变beforeDestroy 改名为 beforeUnmountdestroyed 改名为 unmountedbeforeCreate => setupcreated => setupbeforeMount => onBeforeMountmounted => onMountedbeforeUpdate => onBeforeUpdateupdated => onUpdatedbeforeUnmount => onBeforeUnmountunmounted => onUnmounted7.2,语法setup() {    onMounted(() => {      console.log('mounted')    })}8,toRef 创建ref创建一个ref对象,其value值指向另一个对象中的某个属性语法const state = reactive({  foo: 1,  bar: 2})const fooRef = toRef(state, 'foo')// 传递propsexport default {  setup(props) {    useSomeFeature(toRef(props, 'foo'))  }}9,toRefs 响应式转换将响应式对象转换为普通对象,其中结果对象的每个property都是指向原始对象相应property的ref语法const state = reactive({  foo: 1,  bar: 2})const stateAsRefs = toRefs(state)// 此时state和stateAsRefs是关联的10,shallowReactive 响应式外层转换只处理对象最外层属性的响应式(浅响应式)。适用于:一个对象数据,结构比较深, 但变化时只是外层属性变化语法const state = shallowReactive({  foo: 1,  nested: {    bar: 2  }})11,shallowRef 基本数据响应式只处理基本数据类型的响应式, 不进行对象的响应式处理。适用于:一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换语法const shallow = shallowRef({  greet: 'Hello, world'})12,readonly 响应式变只读让一个响应式数据变为只读的(深只读),应用于不希望数据被修改时语法const shallow = shallowRef({  greet: 'Hello, world', // 只读  nested: {    bar: 2 // 只读  }})13,shallowReadonly 响应式变只读让一个响应式数据变为只读的(浅只读),应用于不希望数据被修改时语法const shallow = shallowReadonly({  foo: 1, // 只读  nested: {    bar: 2 // 非只读  }})14,toRaw 响应式变非响应式将一个由reactive生成的响应式对象转为普通对象,对这个普通对象的所有操作,不会引起页面更新。语法const foo = {}const Foo = reactive(foo)console.log(toRaw(Foo) === foo) // true15,markRaw 标记永远不响应式标记一个对象,使其永远不会再成为响应式对象,有些值不应被设置为响应式的,例如复杂的第三方类库等,当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。语法const foo = markRaw({})console.log(isReactive(reactive(foo))) // false// 嵌套在其他响应式对象中时也可以使用const bar = reactive({ foo })console.log(isReactive(bar.foo)) // false16,customRef 依赖更新控制创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收track和trigger函数作为参数,并且应该返回一个带有get和set的对象。语法<script>import { customRef } from 'vue'export default {    name: 'Home',    setup() {        // 实现防抖函数        const fn = function(value, delay = 500) {            let timeout            return customRef((track, trigger) => {                return {                    get() {                        track()                        return value                    },                    set(newValue) {                        clearInterval(timeout)                        timeout = setTimeout(() => {                            console.log(newValue)                            value = newValue                            trigger()                        }, delay)                    }                }            })        }        const keyword = fn('', 500)        return {            keyword        }    }}</script>17,provide & inject 通信实现祖与后代组件间通信,父组件有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据语法// 祖组件setup(){    let car = reactive({ name:'奔驰', price:'40万' })    provide('car', car)}// 后代组件setup(props, context){    const car = inject('car')    return { car }}18,响应式数据的判断18.1,isRef检查一个值是否为一个ref对象语法const val = ref('xxx')isRef(val) // true18.2,isReactive检查一个值是否为一个isReactive对象语法const val = isReactive({})isRef(val) // true18.3,isReadonly检查一个对象是否是由readonly创建的只读代理语法const state = reactive({  name: 'John'})console.log(isReactive(state)) // true18.4,isProxy检查对象是否是由reactive或readonly创建的proxy语法const state = reactive({  name: 'John'})console.log(isProxy(state)) // true19,teleport 移动dom组件Teleport提供了一种干净的方法,允许我们控制在DOM中哪个父节点下渲染了HTML,而不必求助于全局状态或将其拆分为两个组件。语法<teleport to="移动位置">    <div v-if="isShow" class="mask">        <div class="dialog">            <h3>我是一个弹窗</h3>            <button @click="isShow = false">关闭弹窗</button>        </div>    </div></teleport>// to的格式<teleport to="#some-id" /><teleport to=".some-class" /><teleport to="[data-teleport]" />// disabled的格式<teleport to="#popup" :disabled="displayVideoInline">  <video src="./my-movie.mp4"></teleport>20,Suspense 异步渲染组件等待异步组件时先渲染一些额外内容,让应用有更好的用户体验语法<template>    <div class="app">        <h3>我是App组件</h3>        <Suspense>            <template #default>                <Child/>            </template>            <template #fallback>                <h3>加载中.....</h3>            </template>        </Suspense>    </div></template>import { defineAsyncComponent } from 'vue'const Child = defineAsyncComponent(() => import('./components/Child.vue'))components: {    Child}21,全局API调整将全局的API,即:Vue.xxx调整到应用实例(app)上V2的api    V3的apiVue.config.xxxx    app.config.xxxxVue.component    app.componentVue.directive    app.directiveVue.mixin    app.mixinVue.use    app.useVue.prototype    app.config.globalProperties22,移除api名称    现状Vue.config.productionTip    已移除config.keyCodes    已移除$children    已移除$listeners    已移除$on    已移除$off    已移除$once    已移除filters    已移除.native    已移除23,Ref 获取DOM由于V3中不在存在this,所以ref的获取调整了23.1,单个ref语法<div ref="Qrcode" class="qr_codeode_url" />import { ref } from 'vue'export default {  setup() {    const Qrcode = ref(null)    // 挂载后    onMounted(() => {        console.log(Qrcode.value)    })    return {      Qrcode    }  }}23.2,循环中的refV3中在for循环元素上绑定ref将不再自动创建$ref数组。要从单个绑定获取多个ref,请将ref绑定到一个更灵活的函数上语法<div v-for="item in list" :ref="setItemRef"></div>import { onBeforeUpdate, onUpdated } from 'vue'export default {  setup() {    let itemRefs = []    const setItemRef = el => {      if (el) {        itemRefs.push(el)      }    }    onBeforeUpdate(() => {      itemRefs = []    })    onUpdated(() => {      console.log(itemRefs)    })    return {      setItemRef    }  }}itemRefs不必是数组:它也可以是一个对象,其ref可以通过迭代的key被设置如有需要,itemRef也可以是响应式的,且可以被侦听24,emits 自定义事件定义一个组件可以向其父组件触发的事件// 在子组件中<h1 @click="father">{{ msg }}</h1>export default {    name: 'HelloWorld',    props: {        msg: {            type: String,            default: ''        }    },    emits: ['close'],    setup(props, { emit }) {        const father = function() {            emit('close', 'child')        }        return {            father        }    }}// 在父组件中<HelloWorld :msg="msg" @click="fn" @close="fn2" />25,$nextTick 异步更新使用方式修改import { nextTick } from 'vue'nextTick(() => {  // ...})26,hook 生命周期事件通过事件来监听组件生命周期中的关键阶段语法// V2的语法<template>  <child-component @hook:updated="onUpdated"></template>// V3的语法<template>  <child-component @vnode-updated="onUpdated"></template>// 驼峰写法<template>  <child-component @vnodeUpdated="onUpdated"></template————————————————版权声明:本文为CSDN博主「鹏多多i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/pdd11997110103/article/details/121035412
  • [技术干货] 浏览器渲染机制
    浏览器渲染机制浏览器采用流式布局模型(Flow Based Layout)浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tree)。有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。2. 重绘由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outline, visibility, color、background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。3. 回流回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。<body> <div class="error">     <h4>我的组件</h4>     <p><strong>错误:</strong>错误的描述…</p>     <h5>错误纠正</h5>     <ol>         <li>第一步</li>         <li>第二步</li>     </ol> </div> </body>在上面的HTML片段中,对该段落(标签)回流将会引发强烈的回流,因为它是一个子节点。这也导致了祖先的回流(div.error和body – 视浏览器而定)。此外,和也会有简单的回流,因为其在DOM中在回流元素之后。大部分的回流将导致页面的重新渲染。回流必定会发生重绘,重绘不一定会引发回流。4. 浏览器优化现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。主要包括以下属性或方法:offsetTop、offsetLeft、offsetWidth、offsetHeightscrollTop、scrollLeft、scrollWidth、scrollHeightclientTop、clientLeft、clientWidth、clientHeightwidth、heightgetComputedStyle()getBoundingClientRect()所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。5. 减少重绘与回流CSS使用 transform 替代 top使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。<div>   <a> <span></span> </a> </div> <style>   span {     color: red;   }   div > a > span {     color: red;   } </style>对于第一种设置样式的方式来说,浏览器只需要找到页面中所有的 span 标签然后设置颜色,但是对于第二种设置样式的方式来说,浏览器首先需要找到所有的 span 标签,然后找到 span 标签上的 a 标签,最后再去找到 div 标签,然后给符合这种条件的 span 标签设置颜色,这样的递归过程就很复杂。所以我们应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame。避免使用CSS表达式,可能会引发回流。将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会自动将该节点变为图层。CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。JavaScript避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
  • [问题求助] 【kunpeng920服务器】【AMDGPU功能】android通过mesa调用AMD wx5100渲染出现异常
    【功能模块】kunpeng920服务器通过AMDGPU渲染【操作步骤&问题现象】1、在鲲鹏920,上带AMD wx5100 GPU,android asop 调用 mesa-22.0.0 and mesa-21.1.6进行渲染。都出现异常。2、【截图信息】【日志信息】(可选,上传日志内容或者附件)03-18 11:55:52.415 14435 14435 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 03-18 11:55:52.415 14435 14435 F DEBUG : Build fingerprint: 'redroid/redroid_arm64_only/redroid_arm64_only:12/SQ1D.220205.004/eng.frank.20220305.064003:userdebug/test-keys' 03-18 11:55:52.415 14435 14435 F DEBUG : Revision: '0' 03-18 11:55:52.415 14435 14435 F DEBUG : ABI: 'arm64' 03-18 11:55:52.415 14435 14435 F DEBUG : Timestamp: 2022-03-18 11:55:52.156479216+0000 03-18 11:55:52.415 14435 14435 F DEBUG : Process uptime: 0s 03-18 11:55:52.415 14435 14435 F DEBUG : Cmdline: com.android.systemui 03-18 11:55:52.415 14435 14435 F DEBUG : pid: 14118, tid: 14429, name: GrallocUploadTh >>> com.android.systemui <<< 03-18 11:55:52.415 14435 14435 F DEBUG : uid: 10062 03-18 11:55:52.415 14435 14435 F DEBUG : signal 7 (SIGBUS), code 2 (BUS_ADRERR), fault addr 0xefc1a6277000 03-18 11:55:52.415 14435 14435 F DEBUG : x0 0000efc1a6277000 x1 b400efc0af1ec250 x2 00000000000000e8 x3 0000efc1a6277000 03-18 11:55:52.415 14435 14435 F DEBUG : x4 b400efc0af1ec338 x5 0000efc1a62770e8 x6 0000000000000000 x7 0000000000000000 03-18 11:55:52.415 14435 14435 F DEBUG : x8 0000000000000001 x9 0000000000000000 x10 0000000000000004 x11 000000000000003e 03-18 11:55:52.415 14435 14435 F DEBUG : x12 0000000000000000 x13 0000000000000000 x14 b400efc0af1ec250 x15 0000000000000000 03-18 11:55:52.415 14435 14435 F DEBUG : x16 0000efbe6c198580 x17 0000efc190dd9c20 x18 0000efbe1d5d0000 x19 0000000000000100 03-18 11:55:52.415 14435 14435 F DEBUG : x20 0000efc1a6277000 x21 b400efc0af1ec250 x22 00000000000000e8 x23 000000000000003e 03-18 11:55:52.415 14435 14435 F DEBUG : x24 0000000000000001 x25 00000000000000e8 x26 00000000000000e8 x27 0000efc1a6277000 03-18 11:55:52.415 14435 14435 F DEBUG : x28 000000000000003a x29 0000efbe1e343420 03-18 11:55:52.415 14435 14435 F DEBUG : lr 0000efbe6b77d200 sp 0000efbe1e343410 pc 0000efc190dd9ba8 pst 0000000020000000 03-18 11:55:52.415 14435 14435 F DEBUG : backtrace: 03-18 11:55:52.415 14435 14435 F DEBUG : #00 pc 000000000004bba8 /apex/com.android.runtime/lib64/bionic/libc.so (__memcpy+248) (BuildId: ba489d4985c0cf173209da67405662f9) 03-18 11:55:52.415 14435 14435 F DEBUG : #01 pc 00000000004c51fc /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #02 pc 00000000009d7dc4 /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #03 pc 0000000000a8bfc8 /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #04 pc 0000000000716e94 /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #05 pc 0000000000698a9c /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #06 pc 0000000000697f80 /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #07 pc 0000000000698138 /vendor/lib64/dri/libgallium_dri.so (BuildId: 836ba0e12074242913f46921674e5afb) 03-18 11:55:52.415 14435 14435 F DEBUG : #08 pc 0000000000505238 /system/lib64/libhwui.so (std::__1::__packaged_task_func<android::uirenderer::EGLUploader::onUploadHardwareBitmap(SkBitmap const&, android::uirenderer::FormatInfo const&, AHardwareBuffer*)::'lambda'(), std::__1::allocator<android::uirenderer::EGLUploader::onUploadHardwareBitmap(SkBitmap const&, android::uirenderer::FormatInfo const&, AHardwareBuffer*)::'lambda'()>, void* ()>::operator()()+120) (BuildId: 3d3592fb15b099f3bc3663e5c01ad8af) 03-18 11:55:52.415 14435 14435 F DEBUG : #09 pc 000000000020ef68 /system/lib64/libhwui.so (std::__1::__function::__func<decltype(fp()) android::uirenderer::WorkQueue::runSync<android::uirenderer::EGLUploader::onUploadHardwareBitmap(SkBitmap const&, android::uirenderer::FormatInfo const&, AHardwareBuffer*)::'lambda'()>(android::uirenderer::EGLUploader::onUploadHardwareBitmap(SkBitmap const&, android::uirenderer::FormatInfo const&, AHardwareBuffer*)::'lambda'()&&)::'lambda'(), std::__1::allocator<decltype(fp()) android::uirenderer::WorkQueue::runSync<android::uirenderer::EGLUploader::onUploadHardwareBitmap(SkBitmap const&, android::uirenderer::FormatInfo const&, AHardwareBuffer*)::'lambda'()>(android::uirenderer::EGLUploader::onUploadHardwareBitmap(SkBitmap const&, android::uirenderer::FormatInfo const&, AHardwareBuffer*)::'lambda'()&&)::'lambda'()>, void ()>::operator()()+88) (BuildId: 3d3592fb15b099f3bc3663e5c01ad8af) 03-18 11:55:52.415 14435 14435 F DEBUG : #10 pc 00000000003c62c8 /system/lib64/libhwui.so (android::uirenderer::WorkQueue::process()+156) (BuildId: 3d3592fb15b099f3bc3663e5c01ad8af) 03-18 11:55:52.415 14435 14435 F DEBUG : #11 pc 00000000004ebc7c /system/lib64/libhwui.so (android::uirenderer::ThreadBase::threadLoop()+72) (BuildId: 3d3592fb15b099f3bc3663e5c01ad8af) 03-18 11:55:52.415 14435 14435 F DEBUG : #12 pc 00000000000120ac /system/lib64/libutils.so (android::Thread::_threadLoop(void*)+260) (BuildId: d5dfcc2a0782d6e050d6cf3448f6af45) 03-18 11:55:52.415 14435 14435 F DEBUG : #13 pc 0000000000011964 /system/lib64/libutils.so (thread_data_t::trampoline(thread_data_t const*)+404) (BuildId: d5dfcc2a0782d6e050d6cf3448f6af45) 03-18 11:55:52.415 14435 14435 F DEBUG : #14 pc 00000000000b1910 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+264) (BuildId: ba489d4985c0cf173209da67405662f9) 03-18 11:55:52.415 14435 14435 F DEBUG : #15 pc 00000000000513f0 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: ba489d4985c0cf173209da67405662f9)
  • [ARM原生] 【转】Cuttlefish:GPU 图形加速
    Cuttlefish 的加速图形模式会使用主机的物理图形处理器 (GPU) 进行渲染,具体方法是将客户机渲染命令传递给主机,在主机上运行渲染命令调用,然后将渲染后的结果传递回客户机。默认情况下,Cuttlefish 设备中的客户机端渲染(例如界面和视频播放)由 SwiftShader 处理。SwiftShader 是对 OpenGL API 和 Vulkan API 的软件实现。由于 SwiftShader 是一种软件实现,因此它为 Cuttlefish 提供了一种可在任何主机上运行的通用渲染解决方案。不过,使用 SwiftShader 的性能不及使用正常设备。渲染是一种可大规模并行处理的并行问题,因为像素值是可以单独计算的。图形处理器 (GPU) 是通过加速渲染解决此问题的硬件单元。要求加速图形模式要求主机具有以下驱动程序:支持 EGL 的驱动程序(支持 GL_KHR_surfaceless_context 扩展程序)支持 OpenGL ES 的驱动程序支持 Vulkan 的驱动程序使用加速图形模式GfxStream若要使用 GfxStream 加速图形模式,请使用 --gpu_mode=gfxstream 标记启动本地 Cuttlefish 设备。使用此模式时,OpenGL 和 Vulkan API 调用会直接转到主机。$launch_cvd --gpu_mode=gfxstreamVirgl若要使用 Virgl 加速图形模式,请使用 --gpu_mode=drm_virgl 标记启动本地 Cuttlefish 设备。$launch_cvd --gpu_mode=drm_virgl使用 Virgl 加速图形模式时,OpenGL API 调用会转换为中间表示形式(请参阅 Gallium3D)。系统会将相应中间表示形式传递给主机,并且主机上的 virglrenderer 库会将此中间表示形式重新转换为 OpenGL API 调用。注意:此模式不支持 Vulkan。 声明:        本文转自:https://source.android.google.cn/setup/create/cuttlefish-ref-gpu,仅供学习与交流,非商业用途,版权归原作者所有,如有侵权,请联系删除。
  • [交流讨论] 【转载】Jinja2 语法简介
    一.Jinja2语法基本语法看过之前模板的例子就知道,Jinja2构成的模板文件中,文本内容大致可以分三种。1  变量取值或者宏调用 {{ }}2  控制结构 {% %}3  注释 {# #}  1      jinja2变量jinja2模板中使用 {{ }} 语法表示一个变量,它是一种特殊的占位符。当利用jinja2进行渲染的时候,它会把这些特殊的占位符进行填充/替换,jinja2支持python中所有的Python数据类型比如列表、字段、对象等。2      jinja2结构控制if语句jinja2中的if语句类似与Python的if语句,它也具有单分支,多分支等多种结构,不同的是,条件语句不需要使用冒号结尾,而结束控制语句,需要使用endif关键字For循环jinja2中的for循环用于迭代Python的数据类型,包括列表,元组和字典。在jinja2中不存在while循环 在for循环中,jinja2还提供了一些特殊的变量,用以来获取当前的遍历状态:变量描述loop.index当前迭代的索引(从1开始)loop.index0当前迭代的索引(从0开始)loop.first是否是第一次迭代,返回boolloop.last是否是最后一次迭代,返回boolloop.length序列中的项目数量loop.revindex到循环结束的次数(从1开始)loop.revindex0到循环结束的次数(从0开始)3      jinja2注释{{# 这是注释 #}}4  Set语句模板中变量的值似乎只有一个来源,就是来自于后端的提供。但是实际上我们可以在模板这个层面对变量进行赋值,就是通过了{% set variable_name="value" %}的形式。这赋予了模板在内部进行变量赋值的能力,提高了灵活性。也可以set一个变量的值为某个函数的返回值二.jinja2中的过滤器  变量可以通过“过滤器”进行修改,过滤器可以理解为是jinja2里面的内置函数和字符串处理函数。  常用的过滤器有:过滤器名称    说明    safe 渲染时值不转义capitialize 把值的首字母转换成大写,其他子母转换为小写 lower 把值转换成小写形式  upper 把值转换成大写形式  title 把值中每个单词的首字母都转换成大写 trim 把值的首尾空格去掉 striptags 渲染之前把值中所有的HTML标签都删掉join  拼接多个值为字符串 replace 替换字符串的值 round 默认对数字进行四舍五入,也可以用参数进行控制int  把值转换成整型   那么如何使用这些过滤器呢? 只需要在变量后面使用管道(|)分割,多个过滤器可以链式调用,前一个过滤器的输出会作为后一个过滤器的输入。   三.jinja2的宏  宏类似于Python中的函数,我们在宏中定义行为,还可以进行传递参数,就像Python中的函数  在宏中定义一个宏的关键字是macro,后面跟其 宏的名称和参数等四.jinja2的继承和Super函数jinja2中最强大的部分就是模板继承。模板继承允许我们创建一个基本(骨架)文件,其他文件从该骨架文件继承,然后针对自己需要的地方进行修改。jinja2的骨架文件中,利用block关键字表示其包涵的内容可以进行修改。以下面的骨架文件base.html为例:  这里定义了四处 block,即:head,title,content,footer。如何继承修改注意看下面的文件   其他没修改的地方则继承PS: super()函数 表示获取block块中原来定义的内容。
  • [热门活动] 直播回顾-CG行业上云,不烧钱也能做大片
    随着人们生活水平的提高,人们对娱乐的需求也越来越高,影视需求就是其中之一。近些年来,我国的影视动画产业发展势头迅猛,《西游记之大圣归来》、《哪吒之魔童降世》、《白蛇·缘起》、《捉妖记》等优秀影视作品比比皆是。然而这些影视作品精彩之一就是特效,具有美感的特效场景才能带给用户极致的观感体验。说到特效,那么渲染行业发展至今,是什么样的趋势呢?未来又将如何?影视动画行业已然进入发展快车道,由此,对软件、硬件要求更高,对公有云更依赖;数字多媒体行业随着大尺寸普及,8K-10K增多,对精度要求更高;其他行业也对云服务要求也逐步增多;用户定制化需求量逐渐递增, 需匹配用户本地环境及需求。挑战和机遇并存,渲云与华为云深入合作,laas层基于成熟的华为云公有云平台模式,基于公有云传输协议,提升传输效率,加强传输安全,保障硬核储存资源,适应企业云时代的发展变化。渲云云桌面渲染上云价值:渲云云桌面渲染方案上云价值:渲云客户案例:《唐人街探案2》累计票房突破33亿,整部影片一共500多个特技镜头,涉及复杂的三维镜头有200多个。渲云在电影后期制作过程中提供了高效的渲染解决方案与技术服务,为其调配了大规模高端渲染服务器,为电影的项目周期提供了充分保障。《捉妖记2》不仅是第一部在剧情上的延续,还有全面升级的特效制作,从第一部的1200个特效镜头升级到为1800个特效镜头。渲云配合制作方的要求,以专业化的服务团队、大规模高性能渲染数据中心来确保项目按期按质完成,高速的渲染能力应对后期庞大的渲染量,游刃有余。当然,渲云云渲染不仅可以运用在影视动画领域,还可以运用在建筑设计、VR/AR、互动游戏、工业设计等多种领域,帮助用户快速完成三维内容、动画及效果图的渲染计算。未来,期望渲云继续与华为云深耕云渲染领域,为大众提供更多优秀的渲染场景!直播回放:《CG行业上云,不烧钱也能做特效大片》渲云云桌面渲染服务:https://marketplace.huaweicloud.com/contents/4e9ec5b4-06c7-438b-8e79-725b92195674?marketplace_live_20210629 
  • [热门活动] “渲云”你的得力好助手
    关于“渲云”我的了解有如下:渲云客户端是一款面向三维设计师的自助式云渲染工具,轻松调动海量服务器资源,帮您快速完成渲染。渲云现已支持corona渲染器、vray渲染器,支持通道渲染、多镜头提交、光子渲染、分享结果文件等功能,可完全满足用户使用需求。渲云与多家全球知名公有云平台达成深度合作,实现海量节点拓展,提供全球性极速渲染服务, 用户遍及亚洲,欧美,中东等区域,为全球用户带来极致非凡的云渲染解决方案服务。下面有几个问题需要解答:渲云平台支持各种元素输出以及V-Ray Frame buffer校色吗?如何判断渲染文件是否在正常渲染?C4D渲染丢帧怎么办
总条数:67 到第
上滑加载中