首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

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

编程知识
2024年08月08日 11:35

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

示例地址

From:https://www.cnblogs.com/xachary/p/18348696
本文地址: http://shuzixingkong.net/article/909
0评论
提交 加载更多评论
其他文章 [rCore学习笔记 023]任务切换
导读 还是要先看官方手册. 学过DMA的同志可能比较好理解,一句话, 释放CPU总线 : 如果把应用程序执行的整个过程进行进一步分析,可以看到,当程序访问 I/O 外设或睡眠时,其实是不需要占用处理器的,于是我们可以把应用程序在不同时间段的执行过程分为两类,占用处理器执行有效任务的计算阶段和不必占用
[rCore学习笔记 023]任务切换 [rCore学习笔记 023]任务切换 [rCore学习笔记 023]任务切换
双指针优化
双指针优化 为什么我为OI泪目?因为我菜得离谱...... 引入 双指针是一种简单而又灵活的技巧和思想,单独使用可以轻松解决一些特定问题,和其他算法结合也能发挥多样的用处。 双指针顾名思义,就是同时使用两个指针,在序列、链表结构上指向的是位置,在树、图结构中指向的是节点,通过或同向移动,或相向移动来
双指针优化 双指针优化
总有坏人想爬我网站的数据,看我用这 10 招干他!
大家好,我是程序员鱼皮。前两天模拟面试一位社招两年的老哥,由于他的表现不错,我就临时起意,跟他交流一下我们最近遇到的业务场景问题。问题如下: 最近我们不是做了个 程序员刷题网站 - 面试鸭 嘛,有很多坏人盯上了我们网站,想把我们 4,000 多道面试题、100 多个面试题库的数据都用爬虫抓下来。那我
总有坏人想爬我网站的数据,看我用这 10 招干他! 总有坏人想爬我网站的数据,看我用这 10 招干他! 总有坏人想爬我网站的数据,看我用这 10 招干他!
零基础学习人工智能—Python—Pytorch学习(二)
前言 数学的学习跟数学的计算是要分开的,现在回头再去看大学的高数和线性代数,如果只是学习的话,其实一门课程3天,也就学完了。 学校的课程之所以上那么久,其实是为了考试,也就是为计算准备的。计算有意义的,在有计算机的情况下,计算的意义并不是很大。 所以,如果大学数学没学好,只要花一星期,就能补回来。甚
零基础学习人工智能—Python—Pytorch学习(二) 零基础学习人工智能—Python—Pytorch学习(二) 零基础学习人工智能—Python—Pytorch学习(二)
前后端分离项目,后期前端身份验证的麻烦
软件构成 后端 后端是一个asp.netcore webapi项目,使用jwt进行身份验证和鉴权。 前端 前端是一个基于http协议的asp.netcore RezorPage项目,但实际上完全使用的wwwwroot目录下的静态文件。没有使用RazorPage。 目前只有后端接口鉴权,前端页面任意访
前后端分离项目,后期前端身份验证的麻烦 前后端分离项目,后期前端身份验证的麻烦
vue前端自适应布局,一步到位所有自适应
1,左右布局 - 左侧固定宽带,右侧自适应剩余的宽度。 - 中间一条分割线,可以拖拉,自适应调整左右侧的宽度。 - 左侧的高度超长自动出现横向滚动条,左侧宽度超长,自动出现竖向滚动条。 2,上中下布局 - 最上面的 搜索条件 div 固定占用 100 px 高度,下面的 查询条件 div 固定
vue前端自适应布局,一步到位所有自适应 vue前端自适应布局,一步到位所有自适应
Codeforces Round 964 (Div. 4)
Codeforces Round 964 (Div. 4) A送分 B 大意:两个人两张牌 随机翻 求a翻出来的牌比b大的可能 #include &lt;cstdio&gt; #include &lt;cmath&gt; #include &lt;algorithm&gt; #include &lt
清晰易懂二分查找算法 你确定不看吗?
@目录前言简介一、二分查找算法的原理是什么?1. 确定搜索范围:2. 计算中间位置:3. 比较中间元素:4. 调整搜索范围:5. 重复迭代:二、二分查找算法的优缺点是什么?优点:缺点:三、java 实现二分查找案例总结 前言 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i、 提示:以下是本
清晰易懂二分查找算法 你确定不看吗?