首页 > 其他分享 >前端使用 Konva 实现可视化设计器(20)- 性能优化、UI 美化

前端使用 Konva 实现可视化设计器(20)- 性能优化、UI 美化

时间:2024-08-08 12:38:13浏览次数:6  
标签:draw Draws name Konva remove UI 20 redraw emitter

这一章主要分享一下使用 Konva 遇到的性能优化问题,并且介绍一下 UI 美化的思路。

至少有 2 位小伙伴积极反馈,发现本示例有明显的性能问题,一是内存溢出问题,二是卡顿的问题,在这里感谢大家的提醒。

请大家动动小手,给我一个免费的 Star 吧~

大家如果发现了 Bug,欢迎来提 Issue 哟~

github源码

gitee源码

示例地址

性能优化

内存溢出

根据官方文档 Konva Class: Node 的说明:

remove(): remove a node from parent, but don't destroy. You can reuse the node later.
destroy(): remove and destroy a node. Kill it and delete forever! You should not reuse node after destroy().
If the node is a container (Group, Stage or Layer) it will destroy all children too.

在本示例之前的版本中,只使用 remove() 是不正确的,只使用 remove,每次 redraw 都产生巨量的实例没有被清除,也就是内存溢出了,导致 JS heap size 随随便便干到几个 GB。

【简单判断内存溢出】
前往:Chrome -> Console 面板 -> 左侧更多 -> Performance monitor -> JS heap size
如果内存只升不降,基本可以认为内存溢出了。

在本示例中,大部分图形实例都是用完即弃的,所以大部分的 remove 都替换为 destory 后,JS heap size 将基本维持在几十上百 MB(根据内容复杂度)。

这里提个醒,除了使用 remove 的时候要注意,还有个容易忽略的 API 要注意,就是 Stage、Layer、Group 的 removeChildren(),如果子节点不再有用,建议先遍历子节点分别 destroy 一下。

初始状态,如下:

image

卡顿

在本示例之前的版本中,只要画面需要变化,都是重新 redraw 所有图形,这导致加载的素材过多的时候,交互会产生明显的卡顿,尤其是加载 gif 的时候,每一帧都会 redraw 一次。

因此,redraw 必须是可以选择性 draw 每一层 layer 的,主要调整如下:

// 重绘(可选择)
  redraw(drawNames?: string[]) {
    const all = [
      Draws.BgDraw.name, // 更新背景
      Draws.LinkDraw.name, // 更新连线
      Draws.AttractDraw.name, // 更新磁贴
      Draws.RulerDraw.name, // 更新比例尺
      Draws.RefLineDraw.name, // 更新参考线
      Draws.PreviewDraw.name, // 更新预览
      Draws.ContextmenuDraw.name // 更新右键菜单
    ]

    if (Array.isArray(drawNames) && !this.debug) {
      // 选择性 draw 也要保持顺序
      for (const name of all) {
        if (drawNames.includes(name)) {
          this.draws[name].draw()
        }
      }
    } else {
      for (const name of all) {
        this.draws[name].draw()
      }
    }
  }

这里有几点细节考虑:
1、传哪些 drawNames 就 redraw 哪些 draw 的 group,除非当时是调试模式。
2、不传 drawNames 就全 redraw。
3、redraw 要按 all 的顺序执行。

举例:

  • 拖动画布的时候:
this.render.redraw([Draws.BgDraw.name, Draws.RulerDraw.name, Draws.PreviewDraw.name])

因为这个交互只影响了 背景、比例尺、预览的 draw。

  • 放大缩小的时候:
            this.render.redraw([
              Draws.BgDraw.name,
              Draws.LinkDraw.name,
              Draws.RulerDraw.name,
              Draws.RefLineDraw.name,
              Draws.PreviewDraw.name
            ])

此时影响的 draw 就比较多了。

根据不同交互的特点,做必要的 redraw 处理,就可以很好的提高交互性能,减少卡顿。

UI 美化

之前的重心都放在画布的交互上,界面得过且过就行了。

现在基础架构基本稳定了,是应该美化一下丑陋的 UI 了,简单美化后:

image

Naive UI

为了快速美化,这里用 Naive UI,比较清爽。

主要美化了一下 头部 和 素材 栏:

  • src/components/main-header
  • src/components/asset-bar

这里就不贴具体代码了,比较简单。

mitt - Emitter

之前是通过配置式,传入一些 方法 当作事件的 handler,没法动态订阅,太不方便了。

这里改造了一下 Render,使用 mitt 给它赋予 Emitter 能力:

// 略
import mitt, { type Emitter } from 'mitt'
// 略
export class Render {
  // 略
  protected emitter: Emitter<Types.RenderEvents> = mitt()
  on: Emitter<Types.RenderEvents>['on']
  off: Emitter<Types.RenderEvents>['off']
  emit: Emitter<Types.RenderEvents>['emit']
  // 略
  constructor(stageEle: HTMLDivElement, config: Types.RenderConfig) {
    // 略
    this.on = this.emitter.on.bind(this.emitter)
    this.off = this.emitter.off.bind(this.emitter)
    this.emit = this.emitter.emit.bind(this.emitter)
    // 略
  }
}

在外面的组件里,通过 render 实例,就可以方便订阅事件,例如:

        props.render?.on('selection-change', (nodes: Konva.Node[]) => {
            selection.value = nodes
        })

Thanks watching~

More Stars please!勾勾手指~

源码

gitee源码

示例地址

标签:draw,Draws,name,Konva,remove,UI,20,redraw,emitter
From: https://www.cnblogs.com/xachary/p/18348696

相关文章

  • [[email protected]].eking和[[email protected]].faust扩展名勒索病毒数
    联系:手机/微信(+8617813235971)QQ(107644445)标题:[[email protected]].eking和[[email protected]].faust扩展名勒索病毒数据库可以完美恢复作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]最近接到两个由于操作系统文件......
  • CTS2024
    Day1T1水镜WC赛时做法考虑对于相邻的两个位置\(i\)和\(i+1\),他们之间的连通性可以用一个\(2\times2\)的矩阵描述,即\(i\)对应的两个位置是否和\(i+1\)对应的位置可以连接。发现这个\(2\times2\)的矩阵只会变化一次,且变化的时刻就是\(\dfrac{h_i+h_{i+1}}{2}\)......
  • [EC Final 2021] Vision Test
    挺牛题,没做出来,但是参考了Rainbow博客之后发现这些套路自己其实都会啊QwQ。我提交的翻译:给定一个长度为\(n\)的数组\(x\),接下来你有\(q\)次询问。第\(i\)次询问给出一个区间\(l,r\),设\(k=r-l+1\),你提取出\(x\)数组下标在\(l,r\)之间的区间\(y_i=x_{i+l}(0\le......
  • Flink 1.20 最新版本 Windows本地运行
    ApacheFlink1.20是Flink的一个较新版本,它带来了许多改进和新功能,如物化表、统一的检查点文件合并机制等。然而,关于Flink1.20在Windows本地运行的具体步骤,虽然Flink本身是跨平台的,但官方文档和社区资源可能更多地关注于Linux环境下的部署和配置。不过,基于Flin......
  • 声明式UI语法
    一、ArkTS的基本组成@Entry//装饰器@Component//装饰器structHello{//自定义组件@StatemyText:string='World';build(){//UI描述Column(){//系统组件Text('Hello${this.myText}').fontSize(50)Divider()......
  • 界面组件Kendo UI for Vue 2024 Q2亮点 - 发布一系列新组件
    随着最新的2024年第二季度发布,KendoUIforVue为应用程序开发设定了标准,包括生成式AI集成、增强的设计系统功能和可访问的数据可视化。新的2024年第二季度版本为应用程序界面提供了人工智能(AI)提示,从设计到代码的生产力增强、可访问性改进、一系列新的UI组件等。KendoUI致力于......
  • .NET 与 LayUI 实现高效敏捷开发框架
    前言WaterCloud是一个集成了LayUI的高效敏捷开发框架,专为.NET开发者设计。它不仅支持多种.NET版本(.NET4.5、.NETCore3.1、.NET5、.NET6),还内置了丰富的功能,如权限管理、流程表单设计以及多数据库支持下的多租户架构。使用了ORM(SqlSugar和Chloe)能够轻松应对复杂......
  • 【ACM出版,高录用,快检索!】第二届物联网与云计算技术国际学术会议 (IoTCCT 2024,9月27-29
    第二届物联网与云计算技术国际学术会议(IoTCCT2024)将围绕“物联网与云计算技术”领域,为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提供一个分享专业经验,扩大专业网络,面对面交流新思想以及展示研究成果的国际平台,探讨本领域发展所面临的关......
  • windows平台中使用vscode远程连接linux进行c++开发配置教程(内容详细适合小白)-2021-3-3
    文章目录一、简要介绍二、软件安装步骤1.linux系统安装2.vscode安装3.ssh安装4.配置Remote-SSH5.安装远程插件6.简单小测试三、配置vscode开发环境1.默认设置、用户设置、远程设置和工作区设置2.c++开发设置a).c_cpp_properties.jsonb).tasks.jsonc).launc......
  • 洛谷 P1125 [NOIP2008 提高组] 笨小猴
    [NOIP2008提高组]笨小猴题目描述笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!这种方法的具体描述如下:假设maxn......