文档章节

学习 kityminder 笔记(九)

刘军兴
 刘军兴
发布于 2015/11/24 16:00
字数 1550
阅读 111
收藏 0

继续学习 kityminder.

=== module/style.js === 

 

// 拷贝选中节点的当前样式,包括字体、字号、粗体、斜体、背景色、字体色
// 对应为 styleNames = ['font-size', 'font-family', 'font-weight', 'font-style', 'background', 'color']
class CopyStyleCommand : public Command {
   execute(): 将被选中 node 的 data 与 style 有关的部分复制内部 clipboard
}

// 粘贴已拷贝的样式到选中的节点上
class PasteStyleCommand : public Command {
   execute(): 将 clipboard 中 style 复制到被选中 node 上. 然后布局.
}

// 移除选中节点的样式
class ClearStyleCommand : public Command {
   execute(): 清除被选 node data 中 style, 重新渲染和布局.
}

register module StyleModule {
   commands: copystyle->CopyStyleCommand etc.
}

 

=== module/text.js ===

FONT_ADJUST 用于针对不同系统,浏览器,字体 做居中兼容性处理......

class TextRenderer : public Renderer {
   create(): 为 text 创建 kity.Group 对象, 应是 <g> 元素.
   update(): 得到/计算文本, 样式, 浏览器兼容性调整等数据.
      创建/修改 kity.Text() 对象/元素在 <g> 中. 这里代码较多, 需稍后细看.
   setTextStyle(): 遍历 _styleHooks[] 钩子进行回调.
}

class TextCommand : public Command {
   execute(): 为选中节点设置文本.
}

extend class TextRenderer {
   static _styleHooks: []  // 一种可以扩展 style 的机制...
   static registerStyleHook(): 添加钩子到 _styleHooks[] 中.
}

extend class MinderNode {
   getTextGroup(): ?
}

register module text {
   commands: text->TextCommand,
   renderers: center->TextRenderer
}
这里的问题是, 对于一个 node 的一组 renderers[], 是如何使用的? 前面已经看到很多种不同 renderer 了.


前面看 font.js 时跳过以等待看 text.js, 则现在补看.

=== module/font.js ===

register StyleHook in TextRenderer {
   看起来是得到 node 的字体(font)样式然后渲染到 svg 元素上.
}

// 设置选中节点的字体颜色. 对于 queryValue(), 如果只有一个节点被选中
//   则返回节点颜色; 如果有多个则返回 'mixed', 如果计算是否公共的更好吗?
class fontcolorCommand : public Command {
   execute(): node.data.color = val; 然后 render().
}

// 设置选中节点的背景颜色
class backgroundCommand : public Command {
   execute(): node.data.background = color
}

// 下面 fontfamilyCommand, fontsizeCommand 类似, 略去.
// 很多命令都要求有节点被选中才能使用, 为什么不 mixin 这个函数或属性进去呢?

register module fontmodule {
   commands: forecolor->fontcolorCommand, etc.
}

 

=== 回顾 basestyle.js  ===

// 加粗选中的节点
class boldCommand : public Command {
   execute(): node.data.font-weight = 'bold' or ''
}

class italicCommand : public Command {
   execute(): node.data.font-style = 'italic' or ''
}

register StyleHook[] of TextRenderer {
   根据节点的 font-weight, font-style 属性设置 svg 元素的字体属性.
   这里 hook 弄得有点过复杂, 还有 style-hash 的构成和计算也很麻烦...
}

register module basestylemodule {
   commands: bold->boldCommand, italic->italicCommand.
   shortcutKeys: ctrl+b->bold, ctrl+i->italic
}


=== module/view.js ===

// 当前主要是不知道这个类对应界面什么东西?
class ViewDragger {
   timeline(): ?
   move(),moveTo(): ? 见下面 CameraCommand.
}

// 切换抓手状态,抓手状态下,鼠标拖动将拖动视野,而不是创建选区
// 这个应是对应界面上 '允许拖拽' 按钮(左下部分)
class ToggleHandCommand : Command {
   execute(): status='hand'
}

// 设置当前视野的中心位置到某个节点上. 看起来对应 '定位根节点' 按钮功能?
class CameraCommand : Command {
   execute(): 使用 ViewDragger.move() 来实现.
}

// 指定方向移动当前视野, 在四个方向上可移动一半视野...
class MoveCommand : Command {
   execute(): 使用 ViewDragger.move() 实现, 给出移动距离和时间.
}

register module View {
   commands: hand->ToggleHandCommand etc.
   events: 几个事件的注册及处理, 暂时略.
}

 

=== module/zoom.js ===

// 缩放当前的视野到一定的比例(百分比)
class Zoom : Command {
  execute(): 使用动画(相关词有 animator, timeline, 暂时不熟悉)放大 view.
     发布 viewchange, zoom 事件.
}

class ZoomInCommand/ZoomOutCommand : Command {
   execute(): 缩小/放大, 实现类似于 Zoom.
}

register module Zoom {
   init: 设置缩放比例的数组 [10,20,50,100,200] 可以自定义.
   commands: zoom,zoomin,zoomout
   events: 似乎可以用 mousewheel 来缩放. 未实验成功.
   shortcutKeys: ctrl+=, ctrl+- 对应缩放.
}

 

=== 以上完成了第一遍对 module/*.js 的遍览, 现在可以回顾一下比较重要的 render 部分.

已知在 render.js 中扩展了方法 Minder.renderNode(node), 伪代码及解释如下:

function Minder::renderNode(node) {
  // 1. 如果此节点还未创建 renderers[] 则现在创建.
  if (!node._renderers)
     createRenderersForNode(node);
  
  // 2. 发布 before-render 事件
  fire_event(before-render, ...)
  
  // 3. 遍历所有 render in node._renderers[]. 
  //  此处按照的顺序, 是创建 ._renderers[] 的顺序, 按照程序是
  //     center,left,right,top,bottom,outline,outside.
  node._contentBox = new Box();  // 初始化计算盒子(矩形).
  for-each (renderer) {
    // 3.1 判断(根据上下文) 是否应该渲染.
    if (renderer.should_render?) {
      // 3.1.1 此时需要渲染, 如果渲染图形(元素 <g>)未创建, 则现在创建.
      if (!renderer.<g>)
        renderer.<g> = renderer.create() --> append-to(<g>)
      // 3.1.2 显示该元素
      .<g>.visible = true
      // 3.1.3 更新(update) 渲染图形, 这里我们知道 create() 只调用一次,
      //    update() 每次渲染(改变)时都会被调用. 可能结果存于 box 中.
       last_box = renderer.update(..., .box)
      // 3.1.4 合并渲染区域(符号 += 解释为 merge 方法).
      renderer.content_box += last_box 
    }
    // 3.2 如果不需渲染, 但是已经创建了 svg 图形元素, 则把它们隐藏起来. 
    else if (renderer.<g>) {
      .<g>.visible = false;
    } 
    // 3.3 否则什么都不需要做.
  }

  // 4. 发布 node-render 事件.
  fire-event(node-render, ...)
}


回顾一下最基本的 TextRenderer:

// text 是 'center' 型 renderer, 渲染过程中一般第一个被调用.
class TextRenderer : public Renderer {
  create(): {
    new kity.Group() // 产生一个 <g> 元素, id 为 node_textN, N 为数字.
  }
  update(): {
    // 略去一些 browser 相关兼容代码.
    box = new kity.Box()
    // 遍历 style_hooks[] 让各个模块设置 text-style (简略一些)
    for-each (style_hooks) --> hook(...)
    // 为每行文本创建一个 svg <text> 元素.
    for-each (line) --> new kity.Text(...) add-to(<g>)
    // 再次遍历 style_hooks[] ... 这里不知道为什么遍历第二次? 也许应该先创建 <text> 再设置 style 才对.
    for-each (style_hooks) --> hook(...)
    // 计算一个 textHash, 可能用于比较与上次是否发生了变化.
    text_hash = ....join('/')
    // 返回一个函数, 函数在调用 update() 的 render 中判断和调用.
    // 可能某些地方会延迟调用?
    return function() {
      // 计算 box 并返回的代码.
    }
  }
}

// 回顾一个 style_hook:
FontModule.style_hook = function(node, <g>) {
  color = node.color | node.style.color | ...
  font-family = node.font-family | ...
  font-size = node.font-size | ...
  // 将这些字体相关属性设置到 svg 元素上.
  <g>.fill = color  // color 属性设置到 <g>
  <g>.for-each(<text>)
    <text>.font-family=..., .font-size=...
}

// 另一个 style_hook
BaseStyleModule.style_hook = function(node, <g>) {
  <g>.for-each (<text>)
    <text>.weight = node.font-weight
    <text>.style = node.font-style
}


这样大致理解了 render 过程. 表述为将一个 node(可认为是一个 json object, 含一组属性)对应到画布元素(一个或
多个)的过程. 通过扩展机制1(注册到 _rendererClass[]) 的方法为每个节点产生 renderers[], 再通过扩展机制2
(注册到 style_hooks[]) 来支持节点的 TextRenderer 的各种 style 扩展. 其它类型的 Renderer 没有扩展机制2.

(END)

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
刘军兴
粉丝 56
博文 189
码字总数 231687
作品 0
昌平
私信 提问
百度脑图解析:如何进行web复杂应用的渐进式开发

内容来源:2017 年 4 月 8 日,张博在“HTML5梦工场 & 微软开发者沙龙第05期—持续集成”进行《Web复杂应用的 「渐进式」开发》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方...

06/04
0
0
KityMinder 1.2.0 发布,脑图工具

脑图工具 KityMinder 出新版本啦! 功能增加,体验提升:) 自从KityMinder1.x版本正式上线以来,得到了广大同学的热情关注。同学们为KityMinder提出了各种好的建议。我们整个小组受到了很大...

战毅
2014/07/10
9.1K
12
Kity Minder 1.1.0 发布更新

KityMinder思维脑图,正式线上使用地址已经开放 naotu.baidu.com KityMinder Change Log v1.1.0 功能更新 添加了剪贴板操作的支持 添加了本地自动保存草稿的功能 优化了文字选中效果 改进了文...

战毅
2014/03/19
1K
5
学习 kityminder 笔记(五)

接着学习 kityminder, 前面其实没看完 kity, 大致了解之后, 我们先看看 minder 部分, 两者结合起来学更好些. 下载 kityminder-core (按文档说只含核心部分), 从 git-hub, 建立起开发/构造环境...

刘军兴
2015/11/19
0
0
Kity Minder —— 来自百度的在线思维导图工具

KityMinder 是百度FEX团队的f-cube小组(原UEditor小组)的又一力作。作为一款在线的脑图编辑工具,它有着不输给Native编辑工具(如 xMind,MindManager等)的最佳用户体验。同时,它充分发挥...

oschina
2014/03/04
4
0

没有更多内容

加载失败,请刷新页面

加载更多

走上真正的教育之路——《中国最美的语文》读后感3100字

走上真正的教育之路——《中国最美的语文》读后感3100字: 文:张平。《中国最美的语文》,乍一听,你可能会觉得这个作者或者编辑有些大言不惭,竟然起这么大而狂的名字,可能名不副实。我没...

原创小博客
16分钟前
0
0
tomcat线程模型

Connector结构 BIO模式 NIO模式

grace_233
36分钟前
2
0
Javascript

变量定义 以$,_,字母开头 大小写敏感 var 关键字声明变量 声明未赋值undefined 数据类型 字符串,数字,布尔,数组,NULL,undefined 变量均为对象 函数 无默认值 var声明的是局部变量 函数外声明...

关元
38分钟前
1
0
文件系统、服务、防火墙、SELINUX——安全四大金刚

一提到安全,大家都会想到防火墙,和文件系统权限。而实际工作环境中,我们在Linux的安全配置,会涉及到四个级别。我们思考一个场景,你要在百度盘中存放一个文件,这个动作需要考虑下面四个...

Linux就该这么学
39分钟前
1
0
从源码角度理解Java设计模式——门面模式

一、门面模式介绍 门面模式定义:也叫外观模式,定义了一个访问子系统的接口,除了这个接口以外,不允许其他访问子系统的行为发生。 适用场景:子系统很复杂时,增加一个接口供外部访问。 优...

我叫刘半仙
48分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部