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

devtools/2024/12/23 17:48:50/

这一章主要分享一下使用 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 一下。

初始状态,如下:

在这里插入图片描述

卡顿

在本示例之前的版本中,只要画面需要变化,都是重新 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 了,简单美化后:

在这里插入图片描述

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源码

示例地址


http://www.ppmy.cn/devtools/144753.html

相关文章

入门网络安全工程师要学习哪些内容【2025年寒假最新学习计划】

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 大家都知道网络安全行业很火&#xff0c;这个行业因为国家政策趋势正在大力发展&#xff0c;大有可为!但很多人对网络安全工程师还是不了解&#xff0c;不知道网…

小白入门 · 腾讯云轻量服务器部署 Hadoop 3.3.6

1. 安装JDK1.8 官网下载安装包&#xff0c;上传至服务器&#xff0c;解压tar包 http://planetone.online/downloads/java/jdk/jdk-8u221-linux-x64.tar.gz上传安装包至服务器并解压到指定目录&#xff1a; tar -zxvf jdk-8u221-linux-x64.tar.gz -C /opt/module/2. 配置java…

【数据库】Redis—Java 客户端

一、常见的几种 Java 客户端 Jedis&#xff1a;以 Redis 命令作为方法的名称&#xff0c;便于学习&#xff0c;简单实用&#xff0c;但其实例是线程不安全的&#xff0c;多线程下需要基于连接池来使用。lettce&#xff1a;基于 Netty 实现&#xff0c;支持同步、异步和响应式编…

《学数学会上瘾》读书笔记1-香龙公式的学习(关于信息熵)

最近开始读《学数学会上瘾》这个书&#xff0c;相当不错&#xff0c;笔记之&#xff1a; 中文是最有效率的语言吗&#xff1f; 1948年&#xff0c;美国数学家克劳德香农提出了一个表征符号系统中单位符 号平均信息量的指标——信息熵&#xff0c;还给出了一个计算信息熵的公 式…

CNN分类-卷积神经网络(Convolutional Neural Network)

CNN分类-卷积神经网络&#xff08;Convolutional Neural Network&#xff09; 源代码 CNN分类的用途介绍 什么是卷积神经网络&#xff08;CNN&#xff09;&#xff1f; 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;是一种深度学习…

Jenkins搭建并与Harbor集成上传镜像

Jenkins介绍 Jenkins 是一个开源的自动化服务器&#xff0c;广泛用于持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;的实践中。它帮助开发人员自动化构建、测试和部署过程&#xff0c;从而提高开发效率、代码质量和项目交付速度。通过丰富的插件支持…

四、使用langchain搭建RAG:金融问答机器人--构建web应用,问答链,带记忆功能

经过前面3节完成金融问答机器人基本流程&#xff0c;这章将使用Gradio构建web应用&#xff0c;同时加入memory令提示模板带有记忆的&#xff0c;使用LCEL构建问答链。 加载向量数据库 from langchain.vectorstores import Chroma from langchain_huggingface import HuggingF…

OpenSSL 心脏滴血漏洞(CVE-2014-0160)

OpenSSL 心脏滴血漏洞(CVE-2014-0160) Openssl简介: 该漏洞在国内被译为"OpenSSL心脏出血漏洞”&#xff0c;因其破坏性之大和影响的范围之广&#xff0c;堪称网络安全里程碑事件。 OpenSSL心脏滴血漏洞的大概原理是OpenSSL在2年前引入了心跳(hearbea0机制来维特TS链接的…