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

news2024/12/28 19:39:31

这一章主要分享一下使用 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.coloradmin.cn/o/1991547.html

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

相关文章

【Bug记录】C2662:不能将this指针从const转换为非const

项目场景&#xff1a; 今天在模拟list时候&#xff0c;写到下面代码&#xff0c;出现了语法报错。 这个地方我自己的_iterator是私有的&#xff0c;所以提供了GetIterator接口去获取_iterator&#xff0c;但是不知道为什么就报出了下面的错误。 语法报错&#xff1a; 问题…

Element学习(表格组件、分页组件)(2)

1、表格&#xff08;table&#xff09;组件 &#xff08;1&#xff09;去element官网查看寻找想要的&#xff0c;然后复制修改就行了 &#xff08;2&#xff09;注意在组件文件中标签<template>中时注意&#xff0c;里面只能有一个根标签 &#xff08;3&#xff09;格式化…

【AI大模型】Ollama+OpenWebUI+llama3本地大模型

本地部署大模型 0.引言1.部署安装1.1部署工具1.2 概念介绍1.3 ollama安装后的基本使用1.4 大模型权重下载1.4.1 ollama在线下载1.4.2 huggingFace下载大模型权重及如何使用ollama进行调用 2.带有UI界面的使用3.参考 0.引言 &#xff08;1&#xff09;目的 本教程主要关于开源A…

数据科学和临床数据科学的发展​​​​​​​

内容来自&#xff1a;专栏《R探索临床数据科学&#xff1a;1章1节&#xff1a;数据科学与临床数据科学的发展历程&#xff1a;为何 R 备受青睐及我们专栏的独特之处》的部分 为帮助大家更出色地掌握临床统计、数据挖掘以及人工智能建模的入门知识和应用&#xff0c;由于众多同学…

Thinkphp框架漏洞(附修复方法)

ThinkPHP是为了简化企业级应用开发和敏捷WEB应用开发而诞生的&#xff0c;是一个快速、兼容而且简单的轻量级国产PHP开发框架&#xff0c;诞生于2006年初&#xff0c;原名FCS&#xff0c;2007年元旦正式更名为ThinkPHP&#xff0c;遵循Apache2开源协议发布&#xff0c;从Struts…

27集28集 ESP32 AIchat cmake编译解密-《MCU嵌入式AI开发笔记》

27-28集 ESP32 AIchat cmake编译解密-《MCU嵌入式AI开发笔记》 我们这集讲解学习cmake编译流程。 为了更好的理解&#xff0c; 我们要先了解几个cmake的内部变量&#xff1a; CMAKE_SOURCE_DIR&#xff1a;整个CMake工程最顶层的CMakeLists.txt文件所在路径。 CMAKE_CURRENT…

MyBatis:Maven,Git,TortoiseGit,Gradle

1&#xff0c;Maven Maven是一个非常优秀的项目管理工具&#xff0c;采用一种“约定优于配置&#xff08;CoC&#xff09;”的策略来管理项目。使用Maven不仅可以把源代码构建成可发布的项目&#xff08;包括编译、打包、测试和分发&#xff09;&#xff0c;还可以生成报告、生…

Find My Device技术|谷歌Find My Device网络支持的功能

谷歌新的" Find My Device " 网络覆盖了全球超过数十亿台活跃设备&#xff0c;谷歌 " Find My Device " 也和苹果 " Find My " 一样&#xff0c;支持防追踪功能&#xff0c;当检测到身边有未知蓝牙防丢器跟随移动时&#xff0c;会进行警报提醒。…

【C++题解】1084. 因子求和

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1084. 因子求和 类型&#xff1a;sqrt函数入门 题目描述&#xff1a; 已知一个正整数 N&#xff08; 20≤N≤800000000 &#xff09;&#xff0c;请你编写程序求出该数的全部因子&…

论文解读(15)-UrbanGPT

加油&#xff0c;这一篇也是感受一下大语言模型的力量&#xff01; 原文&#xff1a; UrbanGPT: Spatio-Temporal Large Language Models UrbanGPT: Spatio-Temporal Large Language Models (arxiv.org) 参考&#xff1a; 时空预测与大语言模型的奇妙碰撞&#xff01;UrbanG…

网卡与Linux网络结构(上)

原本是想借着之前学习的中断进一步拓展到网卡与中断的&#xff0c;标题都写好了&#xff0c;结果低估了其中的知识面和难度。。。。。于是调整为了网卡与Linux网络结构&#xff08;上&#xff09;&#xff0c; 没错&#xff0c;仅仅只是上。。。我还是进一步低估了学习需要花费…

Zookeeper的监听机制及原理解析

系列文章目录 手把手教你安装Zookeeper 及可视化插件ZooInspector、ZKUI Zookeeper入门篇&#xff0c;了解ZK存储特点 使用Zookeeper的监听及原理解析 系列文章目录前言一、监听机制的基本概念二、Zookeeper监听原理1. 事件类型2. 监听模式与监听器类型&#xff08;1&#xff…

深入理解计算机系统 CSAPP lab:bomb

实验资源下载地址&#xff1a;csapp.cs.cmu.edu/3e/labs.html 请先查看writeup 解压后 当我们运行bomb时,发现该程序要求我们输入行,如果输入错误,程序就会返回BOOM!!!提示我们失败了. 所以我们的目标是输入正确的行.以解开bomb程序. 实验前先详细阅读bomb.c //bomb.c /*****…

6.1 模块的导入与使用:Python的秘密武器

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

Java语言程序设计基础篇_编程练习题*16.12(演示TextArea的属性)

目录 题目&#xff1a;*16.12&#xff08;演示TextArea的属性&#xff09; 习题思路&#xff1a; 代码示例 结果展示 题目&#xff1a;*16.12&#xff08;演示TextArea的属性&#xff09; 编写一个程序&#xff0c;演示文本域的属性。程序使用复选框表明文本是否换行&#xf…

Java面试题--JVM大厂篇之JVM监控与GC日志分析:优化Parallel GC性能的重要工具

目录 引言&#xff1a; 正文&#xff1a; 1. 理解GC日志的重要性 2. 启用GC日志 3. GC日志解析 4. JVM监控工具 5. 调优Parallel GC的实战技巧 痛点一&#xff1a;长时间停顿 痛点二&#xff1a;频繁的GC 痛点三&#xff1a;内存溢出 6. 实战案例分享 结束语&#…

linux进程----匿名管道和命名管道

linux进程----匿名管道和命名管道 在Linux中&#xff0c;管道是用于进程间通信的一种机制&#xff0c;可以分为两种类型&#xff1a;匿名管道&#xff08;也称为匿名fifo&#xff09;和命名管道&#xff08;也称为命名fifo或named pipe&#xff09;。 匿名管道&#xff08;An…

如何解决整数溢出问题?

1、问题解析 当以整数数据类型&#xff08;包括字节、短、长和其他类型&#xff09;存储的值过大&#xff08;大于变量可容纳的最大值&#xff09;的值时&#xff0c;将发生整数溢出&#xff08;或环 绕&#xff09;。整数的最高有效位丢失&#xff0c;而其余值则相对于最小值…

Centos安装OpenSearch

Centos安装OpenSearch 下载并安装OpenSearch下载OpenSearch RPM包导入公共GNU Privacy Guard&#xff08;GPG&#xff09;密钥。此密钥验证您的OpenSearch实例是否已签名安装RPM包安装完设置开机自启动OpenSearch启动OpenSearch验证OpenSearch是否正确启动 测试OpenSearch向服务…

【lvs】超干货,包含理论+实验(详细步骤)

lvs理论部分 LVS&#xff08;Linux Virtual Server&#xff09;是Linux虚拟服务器的简称&#xff0c;是一个基于Linux操作系统的虚拟服务器集群系统。LVS主要用于实现负载均衡和高可用性&#xff0c;通过将客户端的请求分发到多台后端服务器上&#xff0c;从而提高整体服务的处…