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

这一章主要分享一下使用 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.mzph.cn/diannao/64651.shtml

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

相关文章

BlueLM:以2.6万亿token铸就7B参数超大规模语言模型

一、介绍 BlueLM 是由 vivo AI 全球研究院自主研发的大规模预训练语言模型&#xff0c;本次发布包含 7B 基础 (base) 模型和 7B 对话 (chat) 模型&#xff0c;同时我们开源了支持 32K 的长文本基础 (base) 模型和对话 (chat) 模型。 更大量的优质数据 &#xff1a;高质量语料…

C语言基础16(文件IO)

文章目录 构造类型枚举类型typedef 文件操作(文件IO)概述文件的操作文件的打开与关闭打开文件关闭文件文件打开与关闭案例 文件的顺序读写单字符读取多字符读取单字符写入多字符写入 综合案例&#xff1a;文件拷贝判别文件结束 数据块的读写(二进制)数据块的读取数据块的写入 文…

【Unity/HFSM】使用UnityHFSM实现输入缓冲(预输入)和打断机制

文章目录 前言预输入Animancer的InputBuffer&#xff1a;在UnityHFSM中实现InputBuffer&#xff1a; 打断机制 前言 参考Animancer在状态机中的InputBuffer&#xff0c;在UnityHFSM中实现类似的InputBuffer机制&#xff0c;同时扩展一个状态打断机制 插件介绍&#xff1a; A…

运维日记

运维 内容分发网络(CDN):使用CDN将图片分发到离用户更近的服务器,减少传输时间sudo的权限配置是通过/etc/sudoers文件管理的,这个文件定义了哪些用户在哪种条件下执行什么命令。直接编辑这个文件是有风险的,因为错误的语法可能导致系统无法正常使用sudo功能,因此使用vi…

前端需要学什么

作为前端开发者&#xff0c;学习的内容不仅仅局限于 HTML、CSS 和 JavaScript。前端技术栈发展迅速&#xff0c;想要在职业生涯中不断进步&#xff0c;可以从以下几个方面规划学习路径&#xff1a; 1. 核心前端技能 掌握前端开发的基础和进阶知识&#xff1a; HTML/CSS/JavaS…

用python+YOLOV8图片车辆车距

1. 检测车辆&#xff1a; 使用深度学习模型&#xff08;例如 YOLO、Mask R-CNN&#xff09;来检测照片中的车辆&#xff0c;并得到每辆车的边界框&#xff08;Bounding Box&#xff09;。 工具与技术&#xff1a; YOLOv5/YOLOv8&#xff1a;高效的实时目标检测模型。OpenCV&…

【数理统计】参数估计

文章目录 点估计矩估计法最大似然估计法 区间估计单个正态总体参数的区间估计均值 μ \mu μ 的区间估计方差 σ 2 \sigma^2 σ2 的区间估计 两个正态总体参数的区间估计&#xff08;略&#xff09;补充&#xff1a;单侧置信区间 点估计 矩估计法 【定义】设 X X X 是随机…

冯诺依曼架构与哈佛架构的对比与应用

冯诺依曼架构&#xff08;Von Neumann Architecture&#xff09;&#xff0c;也称为 冯诺依曼模型&#xff0c;是由著名数学家和计算机科学家约翰冯诺依曼&#xff08;John von Neumann&#xff09;在1945年提出的。冯诺依曼架构为现代计算机奠定了基础&#xff0c;几乎所有现代…

linux不同发行版中的主要差异

一、初始化系统 Linux不同发行版中的系统初始化系统&#xff08;如 System V init、Upstart 或 systemd&#xff09; System V init&#xff1a; 历史&#xff1a;System V init 是最传统的 Linux 系统初始化系统&#xff0c;起源于 Unix System V 操作系统。运行级别&#xff…

3D造型软件solvespace在windows下的编译

3D造型软件solvespace在windows下的编译 在逛开源社区的时候发现了几款开源CAD建模软件&#xff0c;一直囿于没有合适的建模软件&#xff0c;虽然了解了很多的模拟分析软件&#xff0c;却不能使之成为整体的解决方案&#xff0c;从而无法产生价值。opencascad之流虽然可行&…

机器学习04-为什么Relu函数

机器学习0-为什么Relu函数 文章目录 机器学习0-为什么Relu函数 [toc]1-手搓神经网络步骤总结2-为什么要用Relu函数3-进行L1正则化修改后的代码解释 4-进行L2正则化解释注意事项 5-Relu激活函数多有夸张1-细数Relu函数的5宗罪2-Relu函数5宗罪详述 6-那为什么要用这个Relu函数7-文…

Redis篇-21--运维篇3-集群(分片,水平扩展,高可用,集群配置案例,扩展哨兵案例)

1、概述 Redis集群&#xff08;Cluster&#xff09;通过分片&#xff08;sharding&#xff09;实现了水平扩展&#xff0c;允许数据分布在多个节点上&#xff0c;从而提升性能和存储容量。 在Redis集群中&#xff0c;数据被分割成16384个哈希槽&#xff08;hash slots&#x…

QScreen在Qt5.15与Qt6.8版本下的区别

简述 QScreen主要用于提供与屏幕相关的信息。它可以获取有关显示设备的分辨率、尺寸、DPI&#xff08;每英寸点数&#xff09;等信息。本文主要是介绍Qt5.15与Qt6环境下&#xff0c;QScreen的差异&#xff0c;以及如何判断高DPI设备。 属性说明 logicalDotsPerInch&#xff1…

[HNCTF 2022 Week1]你想学密码吗?

下载附件用记事本打开 把这些代码放在pytho中 # encode utf-8 # python3 # pycryptodemo 3.12.0import Crypto.PublicKey as pk from hashlib import md5 from functools import reducea sum([len(str(i)) for i in pk.__dict__]) funcs list(pk.__dict__.keys()) b reduc…

shell8

until循环(条件为假的时候一直循环和while相反) i0 until [ ! $i -lt 10 ] doecho $i((i)) done分析 初始化变量&#xff1a; i0&#xff1a;将变量i初始化为0。 条件判断 (until 循环)&#xff1a; until [ ! $i -lt 10 ]&#xff1a;这里的逻辑有些复杂。它使用了until循环…

【游戏中orika完成一个Entity的复制及其Entity异步落地的实现】 1.ctrl+shift+a是飞书下的截图 2.落地实现

一、orika工具使用 1)工具类 package com.xinyue.game.utils;import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.DefaultMapperFactory;/*** author 王广帅* since 2022/2/8 22:37*/ public class XyBeanCopyUtil {private static MapperFactory mappe…

frp内网穿透笔记

文章目录 一、环境介绍二、配置过程2.1 下载文件2.3 服务器A的配置2.3 目标机B的配置2.4 电脑C怎么用 三、问题汇总 一、环境介绍 带公网的vps服务器A&#xff0c;需要穿透到的无公网目标电脑B&#xff0c;以及一台需要通过公网访问B的电脑C。frp 0.47.0&#xff1a;frp_0.47.…

PostgreSQL的交互式终端使用一系列命令来获取有关文本搜索配置对象的信息

在 psql&#xff08;PostgreSQL 的交互式终端&#xff09;中&#xff0c;你可以使用一系列命令来获取有关文本搜索配置对象的信息。这些命令主要围绕 \dF 系列&#xff0c;以及使用 SQL 查询 pg_ts_config 系统视图。以下是你可以使用的一些方法&#xff1a; 使用 \dF 系列命令…

写定制程序容易遇见的问题(FLASH不够时)

做了一个关于定制两条串口协议的活&#xff0c;主要是要在源代码基础上进行修改。源代码只剩了200多字节flash。本来最初我的想法很奇特&#xff0c;用结构体来模仿寄存器的写法。当我写完几行代码后&#xff0c;编译链接&#xff0c;立马就报CODE内存超了。 然后最终还是选择…

【Leetcode 热题 100 - 扩展】303. 区域和检索 - 数组不可变

问题背景 给定一个整数数组 n u m s nums nums&#xff0c;处理以下类型的多个查询&#xff1a; 计算索引 l e f t left left 和 r i g h t right right&#xff08;包含 l e f t left left 和 r i g h t right right&#xff09;之间的 n u m s nums nums 元素的 和 &a…