如何在famo.us表面中计算包装文本高度?

时间:2015-04-17 17:58:42

标签: famo.us

在famo.us中,我想在顶部附近放置一个可变长度的包装标题,然后跟随图像等。所有项目必须是他们自己的表面,因为有些项目有点击事件和动画,但所有定位必须超级快速计算和放置基于文本高度,当然必须避免60fps的DOM访问。这必须发生在一系列迷你帖子,实时流媒体和无限滚动。

到目前为止,我提出了一种方法,如果尚未在localStorage中使用ascii字符映射到init上的像素宽度加载屏幕。它使用jquery为每个字符进行大小调整,然后通过检查破解字和该框的高度来确定行高。之后,我使用此地图进行动态计算,因此我不再触摸DOM。它似乎工作正常但完全依赖于知道将以非常特定的方式使用的字体样式。对于每种新风格,我都必须使用不同的映射。

还有另一种内置于famo.us的方法吗?

1 个答案:

答案 0 :(得分:0)

我正在回答我自己的问题,因为它坦率地说是一段时间了,新的框架将在本月的6月22日(在撰写本文时)出现。我现在就说我正在做的这就是我上面描述的方式。

以下是Famou.us的0.3.5方式。

这是在文件“utils / lines.js”中我掀起的。哈克,是的。工作,是的。

    define(function(require) {
      'use strict';

      var $ = require('jquery');
      var cache = require('utils/cache');

      function getLineInfo(id) {
        var cacheKey = 'lineInfo_' + id;
        var savedLineInfo = cache.get(cacheKey);
        if (savedLineInfo)
          return savedLineInfo;

        var charStart = 32; // space
        var charEnd = 126; // ~
        var $charDump = $('<div>', { id: id });
        $('body').append($charDump);

        for (var i = charStart; i <= charEnd; i++)
          $charDump.append($('<div>', { class: 'char', css: { top: (i-32) * 20 } }).html('&#' + i));

        var charMap = {};
        $charDump.find('.char').each(function() {
          var $this = $(this);
          var char = $this.text().charCodeAt(0);
          var w = $this.width();
          charMap[char] = w;
        });
        $charDump.html('<div class="line">abc<br>123<br>456</div>');
        var lineHeight = $charDump.height() / 3;
        $charDump.remove();
        savedLineInfo = {
          lineHeight: lineHeight,
          charMap: charMap
        };
        cache.set(cacheKey, savedLineInfo);
        return savedLineInfo;
      }

      function getLines(text, width, id, maxLines) {
        var lineInfo = getLineInfo(id);
        var cleaned = $.trim(text.replace(/\s+/gm, ' '));
        var words = cleaned.split(' ');
        var lines = 1;
        var lineWidth = 0;
        var spaceLength = lineInfo.charMap[32];
        var allLines = '';
        words.forEach(function(word) {
          var wordLength = 0;
          word.split('').forEach(function(char) {
            var charLength = lineInfo.charMap[char.charCodeAt(0)];
            if (!charLength)
              charLength = spaceLength;
            wordLength += charLength;
          });
          if (lineWidth + wordLength + spaceLength <= width) {
            lineWidth += wordLength + spaceLength;
            if (maxLines)
              allLines += word + ' ';
          }
          else {
            lineWidth = wordLength;
            if (maxLines && lines <= maxLines)
              allLines += word + ' ';
            else if (maxLines)
              return {text: allLines.substr(0, allLines.length - 3) + '...', lines: lines};
            lines++;
          }
        });
        if (maxLines)
          return {text: allLines, lines: lines};
        return lines;
      }

      function getTextHeight(text, width, id, maxLines) {
        var lineInfo = getLineInfo(id);
        var info;
        if (maxLines) {
          info = getLines(text, width, id, maxLines);
          info.height = lineInfo.lineHeight * info.lines;
          return info;
        }
        return lineInfo.lineHeight * getLines(text, width, id);
      }

      return {
        getLines: getLines,
        getLineInfo: getLineInfo,
        getTextHeight: getTextHeight
      };
});