当前位置: 移动技术网 > IT编程>开发语言>JavaScript > wordcloud2.js

wordcloud2.js

2019年01月19日  | 移动技术网IT编程  | 我要评论

https://blogs.msdn.microsoft.com/dotnet/2019/01/10/announcing-ml-net-0-9-machine-learning-for-net/

https://marketplace.visualstudio.com/items?itemname=mlnet.07

https://dotnet.microsoft.com/learn/machinelearning-ai/ml-dotnet-get-started-tutorial

https://docs.microsoft.com/en-us/dotnet/machine-learning/

https://github.com/dotnet/machinelearning

wordcloud2.js:

/*!
 * wordcloud2.js
 * http://timdream.org/wordcloud2.js/
 *https://github.com/timdream/wordcloud2.js/ 
 * copyright 2011 - 2013 tim chien
 * released under the mit license
 */

'use strict';

// setimmediate
if (!window.setimmediate) {
  window.setimmediate = (function setupsetimmediate() {
    return window.mssetimmediate ||
    window.webkitsetimmediate ||
    window.mozsetimmediate ||
    window.osetimmediate ||
    (function setupsetzerotimeout() {
      if (!window.postmessage || !window.addeventlistener) {
        return null;
      }

      var callbacks = [undefined];
      var message = 'zero-timeout-message';

      // like settimeout, but only takes a function argument.  there's
      // no time argument (always zero) and no arguments (you have to
      // use a closure).
      var setzerotimeout = function setzerotimeout(callback) {
        var id = callbacks.length;
        callbacks.push(callback);
        window.postmessage(message + id.tostring(36), '*');

        return id;
      };

      window.addeventlistener('message', function setzerotimeoutmessage(evt) {
        // skipping checking event source, retarded ie confused this window
        // object with another in the presence of iframe
        if (typeof evt.data !== 'string' ||
            evt.data.substr(0, message.length) !== message/* ||
            evt.source !== window */) {
          return;
        }

        evt.stopimmediatepropagation();

        var id = parseint(evt.data.substr(message.length), 36);
        if (!callbacks[id]) {
          return;
        }

        callbacks[id]();
        callbacks[id] = undefined;
      }, true);

      /* specify clearimmediate() here since we need the scope */
      window.clearimmediate = function clearzerotimeout(id) {
        if (!callbacks[id]) {
          return;
        }

        callbacks[id] = undefined;
      };

      return setzerotimeout;
    })() ||
    // fallback
    function setimmediatefallback(fn) {
      window.settimeout(fn, 0);
    };
  })();
}

if (!window.clearimmediate) {
  window.clearimmediate = (function setupclearimmediate() {
    return window.msclearimmediate ||
    window.webkitclearimmediate ||
    window.mozclearimmediate ||
    window.oclearimmediate ||
    // "clearzerotimeout" is implement on the previous block ||
    // fallback
    function clearimmediatefallback(timer) {
      window.cleartimeout(timer);
    };
  })();
}

(function(global) {

  // check if wordcloud can run on this browser
  var issupported = (function issupported() {
    var canvas = document.createelement('canvas');
    if (!canvas || !canvas.getcontext) {
      return false;
    }

    var ctx = canvas.getcontext('2d');
    if (!ctx.getimagedata) {
      return false;
    }
    if (!ctx.filltext) {
      return false;
    }

    if (!array.prototype.some) {
      return false;
    }
    if (!array.prototype.push) {
      return false;
    }

    return true;
  }());

  // find out if the browser impose minium font size by
  // drawing small texts on a canvas and measure it's width.
  var miniumfontsize = (function getminiumfontsize() {
    if (!issupported) {
      return;
    }

    var ctx = document.createelement('canvas').getcontext('2d');

    // start from 20
    var size = 20;

    // two sizes to measure
    var hanwidth, mwidth;

    while (size) {
      ctx.font = size.tostring(10) + 'px sans-serif';
      if ((ctx.measuretext('\uff37').width === hanwidth) &&
          (ctx.measuretext('m').width) === mwidth) {
        return (size + 1);
      }

      hanwidth = ctx.measuretext('\uff37').width;
      mwidth = ctx.measuretext('m').width;

      size--;
    }

    return 0;
  })();

  // based on http://jsfromhell.com/array/shuffle
  var shufflearray = function shufflearray(arr) {
    for (var j, x, i = arr.length; i;
      j = math.floor(math.random() * i),
      x = arr[--i], arr[i] = arr[j],
      arr[j] = x) {}
    return arr;
  };

  var wordcloud = function wordcloud(elements, options) {
    if (!issupported) {
      return;
    }

    if (!array.isarray(elements)) {
      elements = [elements];
    }

    elements.foreach(function(el, i) {
      if (typeof el === 'string') {
        elements[i] = document.getelementbyid(el);
        if (!elements[i]) {
          throw 'the element id specified is not found.';
        }
      } else if (!el.tagname && !el.appendchild) {
        throw 'you must pass valid html elements, or id of the element.';
      }
    });

    /* default values to be overwritten by options object */
    var settings = {
      list: [],
      fontfamily: '"trebuchet ms", "heiti tc", "å¾®è»ÿ正黑體", ' +
                  '"arial unicode ms", "droid fallback sans", sans-serif',
      fontweight: 'normal',
      color: 'random-dark',
      minsize: 0, // 0 to disable
      weightfactor: 1,
      clearcanvas: true,
      backgroundcolor: '#fff',  // opaque white = rgba(255, 255, 255, 1)

      gridsize: 8,
      origin: null,

      drawmask: false,
      maskcolor: 'rgba(255,0,0,0.3)',
      maskgapwidth: 0.3,

      wait: 0,
      abortthreshold: 0, // disabled
      abort: function noop() {},

      minrotation: - math.pi / 2,
      maxrotation: math.pi / 2,

      shuffle: true,
      rotateratio: 0.1,

      shape: 'circle',
      ellipticity: 0.65,

      hover: null,
      click: null
    };

    if (options) {
      for (var key in options) {
        if (key in settings) {
          settings[key] = options[key];
        }
      }
    }

    /* convert weightfactor into a function */
    if (typeof settings.weightfactor !== 'function') {
      var factor = settings.weightfactor;
      settings.weightfactor = function weightfactor(pt) {
        return pt * factor; //in px
      };
    }

    /* convert shape into a function */
    if (typeof settings.shape !== 'function') {
      switch (settings.shape) {
        case 'circle':
        /* falls through */
        default:
          // 'circle' is the default and a shortcut in the code loop.
          settings.shape = 'circle';
          break;

        case 'cardioid':
          settings.shape = function shapecardioid(theta) {
            return 1 - math.sin(theta);
          };
          break;

        /*

        to work out an x-gon, one has to calculate "m",
        where 1/(cos(2*pi/x)+m*sin(2*pi/x)) = 1/(cos(0)+m*sin(0))
        http://www.wolframalpha.com/input/?i=1%2f%28cos%282*pi%2fx%29%2bm*sin%28
        2*pi%2fx%29%29+%3d+1%2f%28cos%280%29%2bm*sin%280%29%29

        copy the solution into polar equation r = 1/(cos(t') + m*sin(t'))
        where t' equals to mod(t, 2pi/x);

        */

        case 'diamond':
        case 'square':
          // http://www.wolframalpha.com/input/?i=plot+r+%3d+1%2f%28cos%28mod+
          // %28t%2c+pi%2f2%29%29%2bsin%28mod+%28t%2c+pi%2f2%29%29%29%2c+t+%3d
          // +0+..+2*pi
          settings.shape = function shapesquare(theta) {
            var thetaprime = theta % (2 * math.pi / 4);
            return 1 / (math.cos(thetaprime) + math.sin(thetaprime));
          };
          break;

        case 'triangle-forward':
          // http://www.wolframalpha.com/input/?i=plot+r+%3d+1%2f%28cos%28mod+
          // %28t%2c+2*pi%2f3%29%29%2bsqrt%283%29sin%28mod+%28t%2c+2*pi%2f3%29
          // %29%29%2c+t+%3d+0+..+2*pi
          settings.shape = function shapetriangle(theta) {
            var thetaprime = theta % (2 * math.pi / 3);
            return 1 / (math.cos(thetaprime) +
                        math.sqrt(3) * math.sin(thetaprime));
          };
          break;

        case 'triangle':
        case 'triangle-upright':
          settings.shape = function shapetriangle(theta) {
            var thetaprime = (theta + math.pi * 3 / 2) % (2 * math.pi / 3);
            return 1 / (math.cos(thetaprime) +
                        math.sqrt(3) * math.sin(thetaprime));
          };
          break;

        case 'pentagon':
          settings.shape = function shapepentagon(theta) {
            var thetaprime = (theta + 0.955) % (2 * math.pi / 5);
            return 1 / (math.cos(thetaprime) +
                        0.726543 * math.sin(thetaprime));
          };
          break;

        case 'star':
          settings.shape = function shapestar(theta) {
            var thetaprime = (theta + 0.955) % (2 * math.pi / 10);
            if ((theta + 0.955) % (2 * math.pi / 5) - (2 * math.pi / 10) >= 0) {
              return 1 / (math.cos((2 * math.pi / 10) - thetaprime) +
                          3.07768 * math.sin((2 * math.pi / 10) - thetaprime));
            } else {
              return 1 / (math.cos(thetaprime) +
                          3.07768 * math.sin(thetaprime));
            }
          };
          break;
      }
    }

    /* make sure gridsize is a whole number and is not smaller than 4px */
    settings.gridsize = math.max(math.floor(settings.gridsize), 4);

    /* shorthand */
    var g = settings.gridsize;
    var maskrectwidth = g - settings.maskgapwidth;

    /* normalize rotation settings */
    var rotationrange = math.abs(settings.maxrotation - settings.minrotation);
    var minrotation = math.min(settings.maxrotation, settings.minrotation);

    /* information/object available to all functions, set when start() */
    var grid, // 2d array containing filling information
      ngx, ngy, // width and height of the grid
      center, // position of the center of the cloud
      maxradius;

    /* timestamp for measuring each putword() action */
    var escapetime;

    /* function for getting the color of the text */
    var gettextcolor;
    switch (settings.color) {
      case 'random-dark':
        gettextcolor = function getrandomdarkcolor() {
          return 'rgb(' +
            math.floor(math.random() * 128).tostring(10) + ',' +
            math.floor(math.random() * 128).tostring(10) + ',' +
            math.floor(math.random() * 128).tostring(10) + ')';
        };
        break;

      case 'random-light':
        gettextcolor = function getrandomlightcolor() {
          return 'rgb(' +
            math.floor(math.random() * 128 + 128).tostring(10) + ',' +
            math.floor(math.random() * 128 + 128).tostring(10) + ',' +
            math.floor(math.random() * 128 + 128).tostring(10) + ')';
        };
        break;

      default:
        if (typeof settings.color === 'function') {
          gettextcolor = settings.color;
        }
        break;
    }

    /* interactive */
    var interactive = false;
    var infogrid = [];
    var hovered;

    var getinfogridfrommouseevent = function getinfogridfrommouseevent(evt) {
      var canvas = evt.currenttarget;
      var rect = canvas.getboundingclientrect();
      var eventx = evt.clientx - rect.left;
      var eventy = evt.clienty - rect.top;

      var x = math.floor(eventx * ((canvas.width / rect.width) || 1) / g);
      var y = math.floor(eventy * ((canvas.height / rect.height) || 1) / g);

      return infogrid[x][y];
    };

    var wordcloudhover = function wordcloudhover(evt) {
      var info = getinfogridfrommouseevent(evt);

      if (hovered === info) {
        return;
      }

      hovered = info;
      if (!info) {
        settings.hover(undefined, undefined, evt);

        return;
      }

      settings.hover(info.item, info.dimension, evt);

    };

    var wordcloudclick = function wordcloudclick(evt) {
      var info = getinfogridfrommouseevent(evt);
      if (!info) {
        return;
      }

      settings.click(info.item, info.dimension, evt);
    };

    /* get points on the grid for a given radius away from the center */
    var pointsatradius = [];
    var getpointsatradius = function getpointsatradius(radius) {
      if (pointsatradius[radius]) {
        return pointsatradius[radius];
      }

      // look for these number of points on each radius
      var t = radius * 8;

      // getting all the points at this radius
      var t = t;
      var points = [];

      if (radius === 0) {
        points.push([center[0], center[1], 0]);
      }

      while (t--) {
        // distort the radius to put the cloud in shape
        var rx = 1;
        if (settings.shape !== 'circle') {
          rx = settings.shape(t / t * 2 * math.pi); // 0 to 1
        }

        // push [x, y, t]; t is used solely for gettextcolor()
        points.push([
          center[0] + radius * rx * math.cos(-t / t * 2 * math.pi),
          center[1] + radius * rx * math.sin(-t / t * 2 * math.pi) *
            settings.ellipticity,
          t / t * 2 * math.pi]);
      }

      pointsatradius[radius] = points;
      return points;
    };

    /* return true if we had spent too much time */
    var exceedtime = function exceedtime() {
      return ((settings.abortthreshold > 0) &&
        ((new date()).gettime() - escapetime > settings.abortthreshold));
    };

    /* get the deg of rotation according to settings, and luck. */
    var getrotatedeg = function getrotatedeg() {
      if (settings.rotateratio === 0) {
        return 0;
      }

      if (math.random() > settings.rotateratio) {
        return 0;
      }

      if (rotationrange === 0) {
        return minrotation;
      }

      return minrotation + math.random() * rotationrange;
    };

    var gettextinfo = function gettextinfo(word, weight, rotatedeg) {
      // calculate the acutal font size
      // fontsize === 0 means weightfactor function wants the text skipped,
      // and size < minsize means we cannot draw the text.
      var debug = false;
      var fontsize = settings.weightfactor(weight);
      if (fontsize <= settings.minsize) {
        return false;
      }

      // scale factor here is to make sure filltext is not limited by
      // the minium font size set by browser.
      // it will always be 1 or 2n.
      var mu = 1;
      if (fontsize < miniumfontsize) {
        mu = (function calculatescalefactor() {
          var mu = 2;
          while (mu * fontsize < miniumfontsize) {
            mu += 2;
          }
          return mu;
        })();
      }

      var fcanvas = document.createelement('canvas');
      var fctx = fcanvas.getcontext('2d', { willreadfrequently: true });

      fctx.font = settings.fontweight + ' ' +
        (fontsize * mu).tostring(10) + 'px ' + settings.fontfamily;

      // estimate the dimension of the text with measuretext().
      var fw = fctx.measuretext(word).width / mu;
      var fh = math.max(fontsize * mu,
                        fctx.measuretext('m').width,
                        fctx.measuretext('\uff37').width) / mu;

      // create a boundary box that is larger than our estimates,
      // so text don't get cut of (it sill might)
      var boxwidth = fw + fh * 2;
      var boxheight = fh * 3;
      var fgw = math.ceil(boxwidth / g);
      var fgh = math.ceil(boxheight / g);
      boxwidth = fgw * g;
      boxheight = fgh * g;

      // calculate the proper offsets to make the text centered at
      // the preferred position.

      // this is simply half of the width.
      var filltextoffsetx = - fw / 2;
      // instead of moving the box to the exact middle of the preferred
      // position, for y-offset we move 0.4 instead, so latin alphabets look
      // vertical centered.
      var filltextoffsety = - fh * 0.4;

      // calculate the actual dimension of the canvas, considering the rotation.
      var cgh = math.ceil((boxwidth * math.abs(math.sin(rotatedeg)) +
                           boxheight * math.abs(math.cos(rotatedeg))) / g);
      var cgw = math.ceil((boxwidth * math.abs(math.cos(rotatedeg)) +
                           boxheight * math.abs(math.sin(rotatedeg))) / g);
      var width = cgw * g;
      var height = cgh * g;

      fcanvas.setattribute('width', width);
      fcanvas.setattribute('height', height);

      if (debug) {
        // attach fcanvas to the dom
        document.body.appendchild(fcanvas);
        // save it's state so that we could restore and draw the grid correctly.
        fctx.save();
      }

      // scale the canvas with |mu|.
      fctx.scale(1 / mu, 1 / mu);
      fctx.translate(width * mu / 2, height * mu / 2);
      fctx.rotate(- rotatedeg);

      // once the width/height is set, ctx info will be reset.
      // set it again here.
      fctx.font = settings.fontweight + ' ' +
        (fontsize * mu).tostring(10) + 'px ' + settings.fontfamily;

      // fill the text into the fcanvas.
      // xxx: we cannot because textbaseline = 'top' here because
      // firefox and chrome uses different default line-height for canvas.
      // please read https://bugzil.la/737852#c6.
      // here, we use textbaseline = 'middle' and draw the text at exactly
      // 0.5 * fontsize lower.
      fctx.fillstyle = '#000';
      fctx.textbaseline = 'middle';
      fctx.filltext(word, filltextoffsetx * mu,
                    (filltextoffsety + fontsize * 0.5) * mu);

      // get the pixels of the text
      var imagedata = fctx.getimagedata(0, 0, width, height).data;

      if (exceedtime()) {
        return false;
      }

      if (debug) {
        // draw the box of the original estimation
        fctx.strokerect(filltextoffsetx * mu,
                        filltextoffsety, fw * mu, fh * mu);
        fctx.restore();
      }

      // read the pixels and save the information to the occupied array
      var occupied = [];
      var gx = cgw, gy, x, y;
      var bounds = [cgh / 2, cgw / 2, cgh / 2, cgw / 2];
      while (gx--) {
        gy = cgh;
        while (gy--) {
          y = g;
          singlegridloop: {
            while (y--) {
              x = g;
              while (x--) {
                if (imagedata[((gy * g + y) * width +
                               (gx * g + x)) * 4 + 3]) {
                  occupied.push([gx, gy]);

                  if (gx < bounds[3]) {
                    bounds[3] = gx;
                  }
                  if (gx > bounds[1]) {
                    bounds[1] = gx;
                  }
                  if (gy < bounds[0]) {
                    bounds[0] = gy;
                  }
                  if (gy > bounds[2]) {
                    bounds[2] = gy;
                  }

                  if (debug) {
                    fctx.fillstyle = 'rgba(255, 0, 0, 0.5)';
                    fctx.fillrect(gx * g, gy * g, g - 0.5, g - 0.5);
                  }
                  break singlegridloop;
                }
              }
            }
            if (debug) {
              fctx.fillstyle = 'rgba(0, 0, 255, 0.5)';
              fctx.fillrect(gx * g, gy * g, g - 0.5, g - 0.5);
            }
          }
        }
      }

      if (debug) {
        fctx.fillstyle = 'rgba(0, 255, 0, 0.5)';
        fctx.fillrect(bounds[3] * g,
                      bounds[0] * g,
                      (bounds[1] - bounds[3] + 1) * g,
                      (bounds[2] - bounds[0] + 1) * g);
      }

      // return information needed to create the text on the real canvas
      return {
        mu: mu,
        occupied: occupied,
        bounds: bounds,
        gw: cgw,
        gh: cgh,
        filltextoffsetx: filltextoffsetx,
        filltextoffsety: filltextoffsety,
        filltextwidth: fw,
        filltextheight: fh,
        fontsize: fontsize
      };
    };

    /* determine if there is room available in the given dimension */
    var canfittext = function canfittext(gx, gy, gw, gh, occupied) {
      // go through the occupied points,
      // return false if the space is not available.
      var i = occupied.length;
      while (i--) {
        var px = gx + occupied[i][0];
        var py = gy + occupied[i][1];

        if (px >= ngx || py >= ngy || px < 0 || py < 0 || !grid[px][py]) {
          return false;
        }
      }
      return true;
    };

    /* actually draw the text on the grid */
    var drawtext = function drawtext(gx, gy, info, word, weight,
                                     distance, theta, rotatedeg, attributes) {

      var fontsize = info.fontsize;
      var color;
      if (gettextcolor) {
        color = gettextcolor(word, weight, fontsize, distance, theta);
      } else {
        color = settings.color;
      }

      var dimension;
      var bounds = info.bounds;
      dimension = {
        x: (gx + bounds[3]) * g,
        y: (gy + bounds[0]) * g,
        w: (bounds[1] - bounds[3] + 1) * g,
        h: (bounds[2] - bounds[0] + 1) * g
      };

      elements.foreach(function(el) {
        if (el.getcontext) {
          var ctx = el.getcontext('2d');
          var mu = info.mu;

          // save the current state before messing it
          ctx.save();
          ctx.scale(1 / mu, 1 / mu);

          ctx.font = settings.fontweight + ' ' +
                     (fontsize * mu).tostring(10) + 'px ' + settings.fontfamily;
          ctx.fillstyle = color;

          // translate the canvas position to the origin coordinate of where
          // the text should be put.
          ctx.translate((gx + info.gw / 2) * g * mu,
                        (gy + info.gh / 2) * g * mu);

          if (rotatedeg !== 0) {
            ctx.rotate(- rotatedeg);
          }

          // finally, fill the text.

          // xxx: we cannot because textbaseline = 'top' here because
          // firefox and chrome uses different default line-height for canvas.
          // please read https://bugzil.la/737852#c6.
          // here, we use textbaseline = 'middle' and draw the text at exactly
          // 0.5 * fontsize lower.
          ctx.textbaseline = 'middle';
          ctx.filltext(word, info.filltextoffsetx * mu,
                             (info.filltextoffsety + fontsize * 0.5) * mu);

          // the below box is always matches how <span>s are positioned
          /* ctx.strokerect(info.filltextoffsetx, info.filltextoffsety,
            info.filltextwidth, info.filltextheight); */

          // restore the state.
          ctx.restore();
        } else {
          // drawtext on div element
          var span = document.createelement('span');
          var transformrule = '';
          transformrule = 'rotate(' + (- rotatedeg / math.pi * 180) + 'deg) ';
          if (info.mu !== 1) {
            transformrule +=
              'translatex(-' + (info.filltextwidth / 4) + 'px) ' +
              'scale(' + (1 / info.mu) + ')';
          }
          var stylerules = {
            'position': 'absolute',
            'display': 'block',
            'font': settings.fontweight + ' ' +
                    (fontsize * info.mu) + 'px ' + settings.fontfamily,
            'left': ((gx + info.gw / 2) * g + info.filltextoffsetx) + 'px',
            'top': ((gy + info.gh / 2) * g + info.filltextoffsety) + 'px',
            'width': info.filltextwidth + 'px',
            'height': info.filltextheight + 'px',
            'color': color,
            'lineheight': fontsize + 'px',
            'whitespace': 'nowrap',
            'transform': transformrule,
            'webkittransform': transformrule,
            'mstransform': transformrule,
            'transformorigin': '50% 40%',
            'webkittransformorigin': '50% 40%',
            'mstransformorigin': '50% 40%'
          };
          span.textcontent = word;
          for (var cssprop in stylerules) {
            span.style[cssprop] = stylerules[cssprop];
          }
          if (attributes) {
            for (var attribute in attributes) {
              span.setattribute(attribute, attributes[attribute]);
            }
          }
          el.appendchild(span);
        }
      });
    };

    /* help function to updategrid */
    var fillgridat = function fillgridat(x, y, drawmask, dimension, item) {
      if (x >= ngx || y >= ngy || x < 0 || y < 0) {
        return;
      }

      grid[x][y] = false;

      if (drawmask) {
        var ctx = elements[0].getcontext('2d');
        ctx.fillrect(x * g, y * g, maskrectwidth, maskrectwidth);
      }

      if (interactive) {
        infogrid[x][y] = { item: item, dimension: dimension };
      }
    };

    /* update the filling information of the given space with occupied points.
       draw the mask on the canvas if necessary. */
    var updategrid = function updategrid(gx, gy, gw, gh, info, item) {
      var occupied = info.occupied;
      var drawmask = settings.drawmask;
      var ctx;
      if (drawmask) {
        ctx = elements[0].getcontext('2d');
        ctx.save();
        ctx.fillstyle = settings.maskcolor;
      }

      var dimension;
      if (interactive) {
        var bounds = info.bounds;
        dimension = {
          x: (gx + bounds[3]) * g,
          y: (gy + bounds[0]) * g,
          w: (bounds[1] - bounds[3] + 1) * g,
          h: (bounds[2] - bounds[0] + 1) * g
        };
      }

      var i = occupied.length;
      while (i--) {
        fillgridat(gx + occupied[i][0], gy + occupied[i][1],
                   drawmask, dimension, item);
      }

      if (drawmask) {
        ctx.restore();
      }
    };

    /* putword() processes each item on the list,
       calculate it's size and determine it's position, and actually
       put it on the canvas. */
    var putword = function putword(item) {
      var word, weight, attributes;
      if (array.isarray(item)) {
        word = item[0];
        weight = item[1];
      } else {
        word = item.word;
        weight = item.weight;
        attributes = item.attributes;
      }
      var rotatedeg = getrotatedeg();

      // get info needed to put the text onto the canvas
      var info = gettextinfo(word, weight, rotatedeg);

      // not getting the info means we shouldn't be drawing this one.
      if (!info) {
        return false;
      }

      if (exceedtime()) {
        return false;
      }

      // skip the loop if we have already know the bounding box of
      // word is larger than the canvas.
      var bounds = info.bounds;
      if ((bounds[1] - bounds[3] + 1) > ngx ||
        (bounds[2] - bounds[0] + 1) > ngy) {
        return false;
      }

      // determine the position to put the text by
      // start looking for the nearest points
      var r = maxradius + 1;

      var trytoputwordatpoint = function(gxy) {
        var gx = math.floor(gxy[0] - info.gw / 2);
        var gy = math.floor(gxy[1] - info.gh / 2);
        var gw = info.gw;
        var gh = info.gh;

        // if we cannot fit the text at this position, return false
        // and go to the next position.
        if (!canfittext(gx, gy, gw, gh, info.occupied)) {
          return false;
        }

        // actually put the text on the canvas
        drawtext(gx, gy, info, word, weight,
                 (maxradius - r), gxy[2], rotatedeg, attributes);

        // mark the spaces on the grid as filled
        updategrid(gx, gy, gw, gh, info, item);

        // return true so some() will stop and also return true.
        return true;
      };

      while (r--) {
        var points = getpointsatradius(maxradius - r);

        if (settings.shuffle) {
          points = [].concat(points);
          shufflearray(points);
        }

        // try to fit the words by looking at each point.
        // array.some() will stop and return true
        // when putwordatpoint() returns true.
        // if all the points returns false, array.some() returns false.
        var drawn = points.some(trytoputwordatpoint);

        if (drawn) {
          // leave putword() and return true
          return true;
        }
      }
      // we tried all distances but text won't fit, return false
      return false;
    };

    /* send dom event to all elements. will stop sending event and return
       if the previous one is canceled (for cancelable events). */
    var sendevent = function sendevent(type, cancelable, detail) {
      if (cancelable) {
        return !elements.some(function(el) {
          var evt = document.createevent('customevent');
          evt.initcustomevent(type, true, cancelable, detail || {});
          return !el.dispatchevent(evt);
        }, this);
      } else {
        elements.foreach(function(el) {
          var evt = document.createevent('customevent');
          evt.initcustomevent(type, true, cancelable, detail || {});
          el.dispatchevent(evt);
        }, this);
      }
    };

    /* start drawing on a canvas */
    var start = function start() {
      // for dimensions, clearcanvas etc.,
      // we only care about the first element.
      var canvas = elements[0];

      if (canvas.getcontext) {
        ngx = math.floor(canvas.width / g);
        ngy = math.floor(canvas.height / g);
      } else {
        var rect = canvas.getboundingclientrect();
        ngx = math.floor(rect.width / g);
        ngy = math.floor(rect.height / g);
      }

      // sending a wordcloudstart event which cause the previous loop to stop.
      // do nothing if the event is canceled.
      if (!sendevent('wordcloudstart', true)) {
        return;
      }

      // determine the center of the word cloud
      center = (settings.origin) ?
        [settings.origin[0]/g, settings.origin[1]/g] :
        [ngx / 2, ngy / 2];

      // maxium radius to look for space
      maxradius = math.floor(math.sqrt(ngx * ngx + ngy * ngy));

      /* clear the canvas only if the clearcanvas is set,
         if not, update the grid to the current canvas state */
      grid = [];

      var gx, gy, i;
      if (!canvas.getcontext || settings.clearcanvas) {
        elements.foreach(function(el) {
          if (el.getcontext) {
            var ctx = el.getcontext('2d');
            ctx.fillstyle = settings.backgroundcolor;
            ctx.clearrect(0, 0, ngx * (g + 1), ngy * (g + 1));
            ctx.fillrect(0, 0, ngx * (g + 1), ngy * (g + 1));
          } else {
            el.textcontent = '';
            el.style.backgroundcolor = settings.backgroundcolor;
          }
        });

        /* fill the grid with empty state */
        gx = ngx;
        while (gx--) {
          grid[gx] = [];
          gy = ngy;
          while (gy--) {
            grid[gx][gy] = true;
          }
        }
      } else {
        /* determine bgpixel by creating
           another canvas and fill the specified background color. */
        var bctx = document.createelement('canvas').getcontext('2d');

        bctx.fillstyle = settings.backgroundcolor;
        bctx.fillrect(0, 0, 1, 1);
        var bgpixel = bctx.getimagedata(0, 0, 1, 1).data;

        /* read back the pixels of the canvas we got to tell which part of the
           canvas is empty.
           (no clearcanvas only works with a canvas, not divs) */
        var imagedata =
          canvas.getcontext('2d').getimagedata(0, 0, ngx * g, ngy * g).data;

        gx = ngx;
        var x, y;
        while (gx--) {
          grid[gx] = [];
          gy = ngy;
          while (gy--) {
            y = g;
            singlegridloop: while (y--) {
              x = g;
              while (x--) {
                i = 4;
                while (i--) {
                  if (imagedata[((gy * g + y) * ngx * g +
                                 (gx * g + x)) * 4 + i] !== bgpixel[i]) {
                    grid[gx][gy] = false;
                    break singlegridloop;
                  }
                }
              }
            }
            if (grid[gx][gy] !== false) {
              grid[gx][gy] = true;
            }
          }
        }

        imagedata = bctx = bgpixel = undefined;
      }

      // fill the infogrid with empty state if we need it
      if (settings.hover || settings.click) {

        interactive = true;

        /* fill the grid with empty state */
        gx = ngx + 1;
        while (gx--) {
          infogrid[gx] = [];
        }

        if (settings.hover) {
          canvas.addeventlistener('mousemove', wordcloudhover);
        }

        if (settings.click) {
          canvas.addeventlistener('click', wordcloudclick);
        }

        canvas.addeventlistener('wordcloudstart', function stopinteraction() {
          canvas.removeeventlistener('wordcloudstart', stopinteraction);

          canvas.removeeventlistener('mousemove', wordcloudhover);
          canvas.removeeventlistener('click', wordcloudclick);
          hovered = undefined;
        });
      }

      i = 0;
      var loopingfunction, stoppingfunction;
      if (settings.wait !== 0) {
        loopingfunction = window.settimeout;
        stoppingfunction = window.cleartimeout;
      } else {
        loopingfunction = window.setimmediate;
        stoppingfunction = window.clearimmediate;
      }

      var addeventlistener = function addeventlistener(type, listener) {
        elements.foreach(function(el) {
          el.addeventlistener(type, listener);
        }, this);
      };

      var removeeventlistener = function removeeventlistener(type, listener) {
        elements.foreach(function(el) {
          el.removeeventlistener(type, listener);
        }, this);
      };

      var anotherwordcloudstart = function anotherwordcloudstart() {
        removeeventlistener('wordcloudstart', anotherwordcloudstart);
        stoppingfunction(timer);
      };

      addeventlistener('wordcloudstart', anotherwordcloudstart);

      var timer = loopingfunction(function loop() {
        if (i >= settings.list.length) {
          stoppingfunction(timer);
          sendevent('wordcloudstop', false);
          removeeventlistener('wordcloudstart', anotherwordcloudstart);

          return;
        }
        escapetime = (new date()).gettime();
        var drawn = putword(settings.list[i]);
        var canceled = !sendevent('wordclouddrawn', true, {
          item: settings.list[i], drawn: drawn });
        if (exceedtime() || canceled) {
          stoppingfunction(timer);
          settings.abort();
          sendevent('wordcloudabort', false);
          sendevent('wordcloudstop', false);
          removeeventlistener('wordcloudstart', anotherwordcloudstart);
          return;
        }
        i++;
        timer = loopingfunction(loop, settings.wait);
      }, settings.wait);
    };

    // all set, start the drawing
    start();
  };

  wordcloud.issupported = issupported;
  wordcloud.miniumfontsize = miniumfontsize;

  // expose the library as an amd module
  if (typeof global.define === 'function' && global.define.amd) {
    global.define('wordcloud', [], function() { return wordcloud; });
  } else {
    global.wordcloud = wordcloud;
  }

})(window);

  

html5:

<!doctype html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
    <meta charset='utf-8'>
    <title>wordcloud2</title>
    <style>
        #cloud { border-radius:3px;border:1px solid #d0d0d0; }
        #cloud span { cursor: pointer; }
    </style>
</head>
<body>
    <div id='cloud' style="width:640px;height:450px;position:relative;"></div>
    <div id="details" style="width:640px;text-align:center;line-height:2em;margin-top:0.5em"></div>
    <script src='wordcloud2.js'></script>
    <script>
//https://github.com/timdream/wordcloud2.js/
        var tags = [
         ["c#", 601251],
         ["java", 585413],
         ["javascript", 557407],
         ["php", 534590],
         ["android", 466436],
         ["jquery", 438303],
         ["python", 274216],
         ["c++", 269570],
         ["html", 259946],
         ["mysql", 226906],
         ["ios", 216765],
         ["asp.net", 209653],
         ["css", 199932],
         ["sql", 192739],
         ["iphone", 190382],
         [".net", 179522],
         ["objective-c", 172609],
         ["ruby-on-rails", 152860],
         ["c", 129998],
         ["ruby", 97414],
         ["sql-server", 91050],
         ["ajax", 85036],
         ["xml", 84295],
         ["regex", 81991],
         ["arrays", 80728],
         ["wpf", 80062],
         ["asp.net-mvc", 79697],
         ["database", 70777],
         ["linux", 70772],
         ["json", 70396],
         ["django", 68893],
         ["vb.net", 63061],
         ["windows", 62042],
         ["xcode", 60950],
         ["eclipse", 60512],
         ["string", 54249],
         ["facebook", 53745],
         ["html5", 51015],
         ["ruby-on-rails-3", 50109],
         ["r", 49842],
         ["multithreading", 49806],
         ["winforms", 46643],
         ["wordpress", 46632],
         ["image", 45910],
         ["forms", 41984],
         ["performance", 40607],
         ["osx", 40401],
         ["visual-studio-2010", 40228],
         ["spring", 40207],
         ["node.js", 40041],
         ["excel", 39973],
         ["algorithm", 38661],
         ["oracle", 38565],
         ["swing", 38255],
         ["git", 37842],
         ["linq", 37489],
         ["asp.net-mvc-3", 36902],
         ["apache", 35533],
         ["web-services", 35385],
         ["wcf", 35242],
         ["perl", 35138],
         ["entity-framework", 34139],
         ["sql-server-2008", 33827],
         ["visual-studio", 33664],
         ["bash", 33139],
         ["hibernate", 32263],
         ["actionscript-3", 31760],
         ["ipad", 29476],
         ["matlab", 29210],
         ["qt", 28918],
         ["cocoa-touch", 28753],
         ["list", 28556],
         ["cocoa", 28385],
         ["file", 28200],
         ["sqlite", 28114],
         [".htaccess", 28006],
         ["flash", 27908],
         ["api", 27480],
         ["angularjs", 27042],
         ["jquery-ui", 26906],
         ["function", 26485],
         ["codeigniter", 26426],
         ["mongodb", 26223],
         ["class", 25925],
         ["silverlight", 25878],
         ["tsql", 25706],
         ["css3", 25535],
         ["delphi", 25421],
         ["security", 25325],
         ["google-maps", 24919],
         ["vba", 24301],
         ["internet-explorer", 24270],
         ["postgresql", 24236],
         ["jsp", 24224],
         ["shell", 24184],
         ["google-app-engine", 23892],
         ["oop", 23634],
         ["sockets", 23464],
         ["validation", 23429],
         ["unit-testing", 23249]
        ];
        
        wordcloud(document.getelementbyid('cloud'), {
          list : tags.map(function(word) { return [word[0], math.round(word[1]/5500)]; })
        });
        
        var clicked = function(ev) {
          if (ev.target.nodename === "span") {
            var tag = ev.target.textcontent;
            var tagelem;
            if (tags.some(function(el) { if (el[0] === tag) {tagelem = el; return true;} return false; })) {
            document.getelementbyid("details").innerhtml = "there were " + tagelem[1] + " <a href='http://www.dusystem.com/query?tag=" + tag + "&sum=" + tagelem[1] + "'>stack overflow questions tagged '" + tag + "'</a>"; //innertext 
            }
          } else {
            document.getelementbyid("details").innerhtml = "";
          }
        }
        document.getelementbyid("cloud").addeventlistener("click", clicked)

    </script>
</body>
</html>

  

随机样式效果:

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网