文档章节

学习 kityminder 笔记(九)

刘军兴
 刘军兴
发布于 2015/11/24 16:00
字数 1550
阅读 82
收藏 0
点赞 0
评论 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)

 

 

 

 

 

© 著作权归作者所有

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

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

06/04
0
0
学习 kityminder 笔记(五)

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

刘军兴
2015/11/19
0
0
学习 kityminder 笔记(六)

接上篇, 接着学习 kityminder. == core/keyreceiver.js == extend class Minder { init-hook(): 构造时设置选项, 侦听 'paperrender' 事件, 以调用 _initKeyReceiver() _initKeyReceiver():......

刘军兴
2015/11/19
0
0
学习 kityminder 笔记(七)

接上篇继续学习. 本段都是 seajs require(module/*.js) 的, 看起来是按照字母顺序 a-z 排列的, 所以应没什么互相依赖性. 考虑到前面有很多细节都略过, 或不懂, 在学习过程中可能还要不断回顾...

刘军兴
2015/11/20
0
0
再学习 Kity 笔记(五) 初步

在过去两周左右, 一直在学习 kity, kityminder, nodejs, seajs 等一系列项目. 有些认识经过一段时间学习, 已经发生了 变化, 使得原有笔记过时. 兹为深入学习, 有必要回顾复习重新看一遍. Kit...

刘军兴
2015/12/04
68
0
学习 kityminder 笔记(十)

今天学习 layout 下的各个 js. 在此之前, 需要回顾一下 core/layout. 注意在 core 下面有 layout.js, module 下面也有 layout.js, 我是被混淆了, 不能换个名字么? === 布局基类 Layout 位于 ...

刘军兴
2015/11/25
56
0
学习 kityminder 笔记(八)

继续接上篇(文本多了似乎容易丢)... == module/image.js == // 为选中的节点添加图片.class ImageCommand : Command {execute(): for-each node.data += {.image=, ...} }这里小结一下 Comm...

刘军兴
2015/11/24
90
0
KityMinder 1.2.0 发布,脑图工具

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

战毅
2014/07/10
8.2K
12
学习 kityminder & angular (十四) event 和 scope.$apply

回顾 event 机制 先回顾一下以前看的 core/event.js, 其提供了 minder 的事件机制 (event) 支持: // 表示一个脑图中发生的事件class MinderEvent {ctor(type, parms, canstop): 构造一个脑图...

刘军兴
2015/12/14
188
0
学习 kityminder & angular (十三)

今天继续学习 kityminder-editor 以及所用及的 angular. 已知在页面中使用 angular, 整个 editor 部分界面由 directive <kityminder-editor /> 产生, 于是我们 进一步进入到该 directive 里面...

刘军兴
2015/12/11
295
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

用 Python 实现打飞机,让子弹飞吧!

所用技术和软件 python 2.7 pygame 1.9.3 pyCharm 准备工作 安装好 pygame 在第一次使用 pygame 的时候,pyCharm 会自动 install pygame。 下载好使用的素材。 技术实现 初始化 pygame 首先要...

猫咪编程
3分钟前
0
0
MySQL的行锁和表锁

简单总结一下行锁和表锁。 行锁 每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 表锁 每次操作锁住整张表。开销小,加锁快;不会出...

to_ln
6分钟前
0
0
Java IO类库之字节数组输入流ByteArrayInputStream

一、ByteArrayInputStream字节数组输入流介绍 ByteArrayInputStream是字节数组输入流,继承自InputStream。它的内部包含一个缓冲区,是一个字节数组,缓冲数组用于保存从流中读取的字节数据,...

老韭菜
7分钟前
0
0
iOS安全应该做哪些事情

1. 尽量使用HTTPS协议。 2. 密码提交的时候,密码使用SHA256加密后传输,MD5等经过哈希碰撞已经可以推算出原文。 3. 密码提交的时候,可以加盐。 4. 密码保存在本地的时候,尽量使用钥匙串保...

HOrange
14分钟前
0
0
react native 注意事项

1. 环境参考官网 android studio 必装 java jdk安装 1.8版本(环境建议自己一步一步配置,切记不要 apt ) 2.有改变编译内容发现 会白屏,然后APP消失,请卸载原来的测试 appinfo (连续两次...

304158
20分钟前
0
0
FOMO游戏代码解析

源代码在此处

怎当她临去时秋波那一转
25分钟前
1
0
EOS智能合约与DApp开发入门

EOS的是Block.One主导研发的一个区块链底层公链系统,它专门为支撑商业去中心化 应用(Decentralized Application)而设计,其代码开源。 比特币被称为区块链1.0,因为它开辟了数字加密货币的...

笔阁
37分钟前
1
0
编译cjson到dll

https://blog.csdn.net/mengzhisuoliu/article/details/52203724 编译完成后 是纯lua实现的json decode 的10倍以上...

梦想游戏人
47分钟前
0
0
JS基础- Date 对象

Date 对象 Date 对象用于处理日期和时间。 创建 Date 对象的语法: var myDate=new Date() 注释:Date 对象会自动把当前日期和时间保存为其初始值。 Date 对象属性 属性 描述 constructor 返...

ZHAO_JH
49分钟前
0
0
Python数据分析numpy(1)

Python开源的科学计算基础库 1.表示N维数组对象ndarray 2.线性代数、傅里叶变换、随机数生成 3.广播函数,整合c++、c 一.数据的维度 1.数据 2.数据维度 3.一维数据 (1)特点 (2)Python中的...

十年磨一剑3344
52分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部