D3 word-cloud:如何自动调整字体大小,使单词不会用完,并将单词缩放到整个屏幕?

Har*_*bel 2 javascript css word-cloud d3.js angularjs

我正在使用 Jason Davies d3-cloud.js 来实现我的词云,这里

1.只要初始 窗口大小太小,单词就会用完。所以为此我有计算单词大小所需像素的函数,但我使用的 if else 条件并不总是有效:

_.forEach(data, function (word) {
  pixNeeded += that.wordService.calcFontSize(word.id) * word.text.length;
});

that.divideBy = pixNeeded < 7000 ? 2.5
  : pixNeeded < 9000 ? 2
  : pixNeeded < 12000 ? 1.7
  : pixNeeded < 13000 ? 1.6
  : pixNeeded < 15000 ? 1.5
  : pixNeeded < 16000 ? 1.4
  : pixNeeded < 17000 ? 1.3
  : 1;

if (that.h<600 ||that.w<500) // little window handling
{
  that.divideBy=1;
  that.scale=0.8;
  if(pixNeeded>15000) { //small window+lots of words handling by shrink font
    that.wordService.fontMax = 24;
    that.wordService.fontMin = 8;
  }
Run Code Online (Sandbox Code Playgroud)

我在this.divideBy这里使用布局大小:

 this.layout = d3.layout.cloud().size([that.w / that.divideBy, that.h /        that.divideBy])
Run Code Online (Sandbox Code Playgroud)

有没有更聪明的算法?或将 g 元素适合外部 div 的方法?

  1. 设置字体大小后,单词不会用完,我希望单词会覆盖所有 div,我可以在云出现在屏幕上后通过(SVG 宽度)/(g 宽度)= 宽度比例和然后将宽度比例手动应用于 g 元素。但是如何在 javascript 中做到这一点?

小智 5

要计算字体大小,您必须创建此比例:

var fontSizeScale = d3.scale.pow().exponent(5).domain([0,1]).range([ minFont, maxFont]);
Run Code Online (Sandbox Code Playgroud)

并在 fontSize 函数中调用它:

var maxSize = d3.max(that.data, function (d) {return d.size;});

// on the d3.layout.cloud()
  .fontSize(function (d) {
        return fontSizeScale(d.size/maxSize);
      })
Run Code Online (Sandbox Code Playgroud)

要使边界适合您的屏幕/div:

在 .on("end", drawCloud) 函数中,调用这个函数:

function zoomToFitBounds() {

      var X0 = d3.min( words, function (d) {
        return d.x - (d.width/2);
      }),
        X1 = d3.max( words, function (d) {
          return d.x + (d.width/2);
        });

      var Y0 = d3.min( words, function (d) {
          return d.y - (d.height/2);
        }),
        Y1 = d3.max( words, function (d) {
          return d.y + (d.height/2);
        });

      var scaleX = (X1 - X0) / (width);
      var scaleY = (Y1 - Y0) / (height);

      var scale = 1 / Math.max(scaleX, scaleY);

      var translateX = Math.abs(X0) * scale;
      var translateY = Math.abs(Y0) * scale;

      cloud.attr("transform", "translate(" +
        translateX + "," + translateY + ")" +
        " scale(" + scale + ")");
}
Run Code Online (Sandbox Code Playgroud)