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

news/2024/11/18 23:43:01/文章来源:https://www.cnblogs.com/xachary/p/18348696

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

示例地址

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

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

相关文章

【日记】感觉自己越来越摆了(546 字)

正文今天想了很多乱七八糟的事情,但最后都没有什么结论。这种情况一般称为:内耗。擦药的地方有些好点了,又有一些新的地方冒了出来。参加工作一年多了,现在却才开始越发受不了这种生活。好想要什么时候参加一次正规的半程马拉松比赛。只要完赛就好了。两次旅行的行程依然没…

二叉树的递归套路

对于二叉树的经典递归套路的理解二叉树的递归套路 二叉树结构 二叉树是一个将数据组织成头尾相连的特殊链表,每一个数据单元与链表一样有一个指向其的指针,但与链表不同的是其可以有两个指向其他单元的指针,分别是其左孩子与右孩子。采用该这种结构,最终数据的呈现形式会与…

[rCore学习笔记 023]任务切换

导读 还是要先看官方手册. 学过DMA的同志可能比较好理解,一句话, 释放CPU总线 : 如果把应用程序执行的整个过程进行进一步分析,可以看到,当程序访问 I/O 外设或睡眠时,其实是不需要占用处理器的,于是我们可以把应用程序在不同时间段的执行过程分为两类,占用处理器执行有效…

鸿蒙(Harmony) NEXT - AlphabetIndexer实现联系人字母索引

鸿蒙(Harmony) NEXT 9月份就要正式上架了,并且不会再兼容安卓平台,于是我也赶紧给App开发鸿蒙版本,接下来会写一系列的Harmony开发教程。 今天使用AlphabetIndexer实现联系人字母索引,AlphabetIndexer是官方封装好的组件 咱们实现后的效果图:代码实现 首先在aboutToAppear…

window下redis的安装

下载地址:https://github.com/tporadowski/redis/releases Windows下的.msi安装和.zip格式区别:.msi是Windows installer开发出来的程序安装文件,它可以让你安装,修改,卸载你所安装的程序。说白了.msi就是Windows installer的数据包,把所有和安装文件相关的内容封装在一…

最全vue面试题,vue知识点

1、MVC 和 MVVM 区别 MVC MVC全名是 Model View Controller,时模型 - 视图 - 控制器的缩写,一种软件设计典范。Model(模型):是用于处理应用程序数据逻辑部分。通常模型对象负责在数据库中存取数据。 View(视图):是应用程序中处理数据显示的本分。通常视图是依据模型数据创建…

生猪

近期将迎来回调

使用xshell连接阿里云远程服务器(图文教程)

1. 参考资料:阿里云官方帮助资料: https://help.aliyun.com/document_detail/71529.html?spm=a2c4g.11186623.6.616.JqUSgl2. 准备条件:1). 登录阿里云官网,申请阿里云ECS服务器请参考网上其他教程,或者自己申请一下就好。2). 下载Xshell客户端推荐Xshell软件链接:http:…

AI自动化应用开发,让创意与效率并驾齐驱!

在这个日新月异的时代,人工智能(AI)与自动化技术的融合正以前所未有的速度重塑着各行各业。你是否梦想过,在信息的海洋中自动筛选出精华,用创意点亮每一篇内容,同时让繁琐的工作流程变得轻松高效?现在,机会来了!我们诚邀您参加即将开启的“AI自动化应用开发”公开课,…

【AI+安全】态势感知之数据可视化技术分析与实现

一、可视化的设计原则1.1 可视化设计流程1.2 交互式设计原则1.3 场景化设计二、可视化前端实现的关键技术2.1 图表库的选择2.2 Canvas2.3 WebGL三、通用数据可视化平台的搭建四、新华三态势感知的可视化实现4.1 3D 整网威胁态势呈现4.2 资产态势呈现4.3 脆弱性态势结束语可视化…

K8S云原生-高可用集群部署V1.28.2

一、环境准备K8S集群角色 IP 主机名 安装相关组件master 10.1.16.160 hqiotmaster07l apiserver、controller-manager、scheduler、kubelet、etcd、docker、kube-proxy、keepalived、nginx、calicomaster 10.1.16.161 hqiotmaster08l apiserver、controller-manager、scheduler…

CF708C Centroids

题意 来自洛谷:思路 记录每个点 \(u\) 所在子树可以删去的最大的部分 \(part1\) 和次大的部分 \(part2\) 和除了 \(u\) 的子树以外的部分可以删去的最大的部分 \(up\),这个部分必须要求小于等于 \(\dfrac{n}{2}\),和找树的中心(注意不是重心)的思路差不多。 注意:\(part1…