zoukankan      html  css  js  c++  java
  • TreeSaver 模板 Grid匹配算法

    简单来说,TreeSaver有个函数:treesaver.layout.Grid.best = function(content, grids, breakRecord) {  这个函数根据内容,选择最合适的模板。

    这个函数的逻辑就是TreeSaver的模板匹配算法。

    下面是对这个函数以及调用他的分析:

    对于一篇文章来说,分页运算的逻辑在下面文件的 treesaver.ui.Article.prototype.paginateAsync 函数中。

    https://github.com/Treesaver/treesaver/blob/master/src/ui/article.js

    treesaver.ui.Article.prototype.paginateAsync 函数延迟2秒后使用调度程序对文章解析分页。

    在TreeSaver中,Grid的定义就是模板的定义。(其他部分每个分页,每篇文章都是一样的。)

    在TreeSaver的资源定义中,我们可以看到有很多个Grid定义,那个Grid适合我们的模板,是根据下面逻辑进行判断的。

    https://github.com/Treesaver/treesaver/blob/master/src/layout/grid.js

    一、知道浏览器可以显示区域的大小。

    这里的区域不是浏览器的内容区域,而是资源定义中viewer的区域,viewer区域显示的内容会同一篇文章每个页面都不一样。

    二、根据浏览器特征,对候选模板Grid进行过滤,排序

    这部分的代码如下:

    /**
    
     * Stretch the grids into appropriate heights, and filter out any grids
    
     * which do not fit. Return the stretched subset of grids in an array
    
     * @param {{ w: number, h: number }} size
    
     * @return {Array.<treesaver.layout.Grid>}
    
     */
    
    treesaver.ui.Article.prototype.stretchGrids = function(size) {
    
      this.eligible_grids = this.grids.filter(function(grid) {
    
        return grid.capabilityFilter() && grid.sizeFilter(size);
    
      }).map(function(grid) {
    
        // Now stretch to the space
    
        return grid.stretch(size.h);
    
      });
    
      // Are there any grids?
    
      if (!this.eligible_grids.length) {
    
        treesaver.debug.error('No eligible grids at ' + size.w + 'x' + size.h);
    
      }
    
      // Sort by highest text height (helps with shortcutting in scoring)
    
      this.eligible_grids.sort(treesaver.layout.Grid.sort);
    
    };

    过滤策略:

    1. 如果内容对 data-requires 有限制,对应的Grid是否适合这种数据约束,比如内容是Flash的,模板Grid中也应该是能用来显示这种data-requires的模板。data-requires有哪些枚举,是自己配置的,只需要你保证模板和内容上都有你新增的数据约束即可。
      treesaver.layout.Grid.prototype.capabilityFilter = function() { 函数就是做这个判断逻辑的。
    2. View区域大小限制了只能用那些模板。
      这个逻辑判断在下面函数中:treesaver.layout.Grid.prototype.sizeFilter = function(size) {, 输入参数为View区域的大小。
    3. 对通过上面两个过滤的模板Grid数组进行排序,根据Grid的column和container格式降序排列。

    三、遍历文章内容,产生分页,下面就是这个逻辑的主要框架部分代码。

    遍历逻辑的核心代码如下,即依次建立每一个Page对象。

    /**
    

     * Paginate the article asynchronously
    
     * @param {boolean} bg Paginate remainder of article in background.
    
     * @param {number} index Paginate synchronously until this index.
    
     * @param {?treesaver.layout.ContentPosition|number} pos Paginate synchronously until this position.
    
     * @private
    
     */
    
    treesaver.ui.Article.prototype.paginate = function(bg, index, pos) {
    
      //.......
    
      var page;
    
      index = index || 0;
    
      while (!this.br.finished) {
    
        page = new treesaver.layout.Page(
    
          /** @type {!treesaver.layout.Content } */ (this.content),
    
          this.eligible_grids,
    
          /** @type {!treesaver.layout.BreakRecord} */ (this.br)
    
        );
    
      //.......
    
      }
    
    //.......
    
    }

    Page对象的构造函数中,第一句就是挑选合适的模板Grid,然后根据挑选的模板组织页面,代码如下:

    https://github.com/Treesaver/treesaver/blob/master/src/layout/page.js

    /**
    
      * Page class
    
      * @constructor
    
      * @param {!treesaver.layout.Content} content
    
      * @param {!Array.<treesaver.layout.Grid>} grids
    
      * @param {!treesaver.layout.BreakRecord} br The current breakRecord.
    
      */
    
    treesaver.layout.Page = function(content, grids, br) {
    
      var best = treesaver.layout.Grid.best(content, grids, br),
    
          host = document.createElement('div'),
    
          originalBr = br.clone(),
    
          containerFilled = false;
    
      // ........
    
    }

    计算最佳模板,就涉及到了模板权重评分计算。

    对于一个模板,它的权重计算逻辑如下:

    • Column 文本显示的分栏,一栏一个Column。计算模板权重时,一个Column,权重多加50分。模板中有几个Column,权重分数就增加几倍的50。
    • 如果模板Grid的lineHeight和内容的lineHeight不一样,则权重分数扣除2000分。
    • 如果模板Grid的colWidth和内容的colWidth不一致,则权重分数扣除无限大(Infinity)。
    • 如果模板中标识了onlypage(用于文章的封面,只能用于唯一且第一页),如果当前页面是第一页,权重加4000,否则权重减无穷大。
    • 如果模板强制指定了适合那一页,发现当前是该页时,权重增加3000,如果定义了,但是不是该页则权重减无穷大。
      模板定义页面的匹配正则是:treesaver.layout.Grid.pageFlagRegex = /^(no-)?page-(\d+)$/;
    • 如果模板定义了不适合于那一页,发现不适合时,权重减无穷大;不适合的模板class 是 no-page- 开头的。
    • 如果模板定义了适合偶数页(even),则在偶数页时权重增加2000,奇数页时权重减无穷大。
    • 如果模板定义了适合奇数页(odd),则在奇数页时权重增加2000,偶数时权重减无穷大。

    以上模板权重评分分数计算在 treesaver.layout.Grid.prototype.score = function(content, breakRecord) { 函数中实现。注意以上只算了 模板的 Column 信息,没有计算模板的 Container 信息。
    下一步我们遍历模板中每一个container,看内容中定义的的figure是否适合它。
    这个算法在下面几个函数中实现:
    treesaver.layout.Grid.prototype.mapContainers = function(content, br) {

    • 如果模板中定义了固定部分(container),则模板权重增加 2000+最小高度×5 .优先使用有图片的模板。
    • 如果内容页,figure是可选择的图片的,则权重增加 4000. 图片具有自适应,优先出现。
    • 如果模板中定义没有使用了fixed,( !container.flexible) 权重增加 5000.

    Grid模板描述语言中的子元素:

    • Container, 图片及非自动填充的内容。For positioning images and other non-flowing content,
      在内容中,figure控件对应的就是Container。
    • Column   需要自动填充的内容。For flowing content
    • runningtitle ?

    内容集合

    https://github.com/Treesaver/treesaver/blob/master/src/layout/content.js

    • figures 集合(不能自动填充的内容的集合,图片,引用等)
    • blocks 集合(分段的文本)
  • 相关阅读:
    fastcgi与cgi的区别
    oracle启动脚本
    oracle表空间大小的限制和DB_BLOCK_SIZE的概念
    静默安装Oracle11G
    ls 指令的介绍
    cronolog日志切割catalina.out
    oracle expdp自动备份脚本
    tomcat开启自启动
    oracle listener.ora文件配置
    CentOS 7.0 上安装和配置 VNC 服务器
  • 原文地址:https://www.cnblogs.com/ghj1976/p/2123520.html
Copyright © 2011-2022 走看看