vega-wordcloud
Advanced tools
Comparing version 4.1.3 to 4.1.4
@@ -5,3 +5,3 @@ (function (global, factory) { | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.vega = global.vega || {}, global.vega.transforms = {}), global.vega, global.vega, global.vega, global.vega, global.vega)); | ||
}(this, (function (exports, vegaCanvas, vegaDataflow, vegaUtil, vegaScale, vegaStatistics) { 'use strict'; | ||
})(this, (function (exports, vegaCanvas, vegaDataflow, vegaUtil, vegaScale, vegaStatistics) { 'use strict'; | ||
@@ -36,2 +36,3 @@ /* | ||
*/ | ||
// Word cloud layout by Jason Davies, https://www.jasondavies.com/wordcloud/ | ||
@@ -41,44 +42,42 @@ // Algorithm due to Jonathan Feinberg, http://static.mrfeinberg.com/bv_ch03.pdf | ||
var cloudRadians = Math.PI / 180, | ||
cw = 1 << 11 >> 5, | ||
ch = 1 << 11; | ||
cw = 1 << 11 >> 5, | ||
ch = 1 << 11; | ||
function cloud () { | ||
var size = [256, 256], | ||
text, | ||
font, | ||
fontSize, | ||
fontStyle, | ||
fontWeight, | ||
rotate, | ||
padding, | ||
spiral = archimedeanSpiral, | ||
words = [], | ||
random = Math.random, | ||
cloud = {}; | ||
text, | ||
font, | ||
fontSize, | ||
fontStyle, | ||
fontWeight, | ||
rotate, | ||
padding, | ||
spiral = archimedeanSpiral, | ||
words = [], | ||
random = Math.random, | ||
cloud = {}; | ||
cloud.layout = function () { | ||
var contextAndRatio = getContext(vegaCanvas.canvas()), | ||
board = zeroArray((size[0] >> 5) * size[1]), | ||
bounds = null, | ||
n = words.length, | ||
i = -1, | ||
tags = [], | ||
data = words.map(d => ({ | ||
text: text(d), | ||
font: font(d), | ||
style: fontStyle(d), | ||
weight: fontWeight(d), | ||
rotate: rotate(d), | ||
size: ~~(fontSize(d) + 1e-14), | ||
padding: padding(d), | ||
xoff: 0, | ||
yoff: 0, | ||
x1: 0, | ||
y1: 0, | ||
x0: 0, | ||
y0: 0, | ||
hasText: false, | ||
sprite: null, | ||
datum: d | ||
})).sort((a, b) => b.size - a.size); | ||
board = zeroArray((size[0] >> 5) * size[1]), | ||
bounds = null, | ||
n = words.length, | ||
i = -1, | ||
tags = [], | ||
data = words.map(d => ({ | ||
text: text(d), | ||
font: font(d), | ||
style: fontStyle(d), | ||
weight: fontWeight(d), | ||
rotate: rotate(d), | ||
size: ~~(fontSize(d) + 1e-14), | ||
padding: padding(d), | ||
xoff: 0, | ||
yoff: 0, | ||
x1: 0, | ||
y1: 0, | ||
x0: 0, | ||
y0: 0, | ||
hasText: false, | ||
sprite: null, | ||
datum: d | ||
})).sort((a, b) => b.size - a.size); | ||
while (++i < n) { | ||
@@ -89,3 +88,2 @@ var d = data[i]; | ||
cloudSprite(contextAndRatio, d, data, i); | ||
if (d.hasText && place(board, d, bounds)) { | ||
@@ -99,4 +97,4 @@ tags.push(d); | ||
y: d.y + d.y1 | ||
}]; // Temporary hack | ||
}]; | ||
// Temporary hack | ||
d.x -= size[0] >> 1; | ||
@@ -106,6 +104,4 @@ d.y -= size[1] >> 1; | ||
} | ||
return tags; | ||
}; | ||
function getContext(canvas) { | ||
@@ -124,14 +120,12 @@ canvas.width = canvas.height = 1; | ||
} | ||
function place(board, tag, bounds) { | ||
var startX = tag.x, | ||
startY = tag.y, | ||
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), | ||
s = spiral(size), | ||
dt = random() < .5 ? 1 : -1, | ||
t = -dt, | ||
dxdy, | ||
dx, | ||
dy; | ||
startY = tag.y, | ||
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), | ||
s = spiral(size), | ||
dt = random() < .5 ? 1 : -1, | ||
t = -dt, | ||
dxdy, | ||
dx, | ||
dy; | ||
while (dxdy = s(t += dt)) { | ||
@@ -143,26 +137,22 @@ dx = ~~dxdy[0]; | ||
tag.y = startY + dy; | ||
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; // TODO only check for collisions within current bounds. | ||
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; | ||
// TODO only check for collisions within current bounds. | ||
if (!bounds || !cloudCollide(tag, board, size[0])) { | ||
if (!bounds || collideRects(tag, bounds)) { | ||
var sprite = tag.sprite, | ||
w = tag.width >> 5, | ||
sw = size[0] >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
w = tag.width >> 5, | ||
sw = size[0] >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
for (var j = 0; j < h; j++) { | ||
last = 0; | ||
for (var i = 0; i <= w; i++) { | ||
board[x + i] |= last << msx | (i < w ? (last = sprite[j * w + i]) >>> sx : 0); | ||
} | ||
x += sw; | ||
} | ||
tag.sprite = null; | ||
@@ -173,6 +163,4 @@ return true; | ||
} | ||
return false; | ||
} | ||
cloud.words = function (_) { | ||
@@ -186,3 +174,2 @@ if (arguments.length) { | ||
}; | ||
cloud.size = function (_) { | ||
@@ -196,3 +183,2 @@ if (arguments.length) { | ||
}; | ||
cloud.font = function (_) { | ||
@@ -206,3 +192,2 @@ if (arguments.length) { | ||
}; | ||
cloud.fontStyle = function (_) { | ||
@@ -216,3 +201,2 @@ if (arguments.length) { | ||
}; | ||
cloud.fontWeight = function (_) { | ||
@@ -226,3 +210,2 @@ if (arguments.length) { | ||
}; | ||
cloud.rotate = function (_) { | ||
@@ -236,3 +219,2 @@ if (arguments.length) { | ||
}; | ||
cloud.text = function (_) { | ||
@@ -246,3 +228,2 @@ if (arguments.length) { | ||
}; | ||
cloud.spiral = function (_) { | ||
@@ -256,3 +237,2 @@ if (arguments.length) { | ||
}; | ||
cloud.fontSize = function (_) { | ||
@@ -266,3 +246,2 @@ if (arguments.length) { | ||
}; | ||
cloud.padding = function (_) { | ||
@@ -276,3 +255,2 @@ if (arguments.length) { | ||
}; | ||
cloud.random = function (_) { | ||
@@ -286,23 +264,22 @@ if (arguments.length) { | ||
}; | ||
return cloud; | ||
} | ||
return cloud; | ||
} // Fetches a monochrome sprite bitmap for the specified text. | ||
// Fetches a monochrome sprite bitmap for the specified text. | ||
// Load in batches for speed. | ||
function cloudSprite(contextAndRatio, d, data, di) { | ||
if (d.sprite) return; | ||
var c = contextAndRatio.context, | ||
ratio = contextAndRatio.ratio; | ||
ratio = contextAndRatio.ratio; | ||
c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio); | ||
var x = 0, | ||
y = 0, | ||
maxh = 0, | ||
n = data.length, | ||
w, | ||
w32, | ||
h, | ||
i, | ||
j; | ||
y = 0, | ||
maxh = 0, | ||
n = data.length, | ||
w, | ||
w32, | ||
h, | ||
i, | ||
j; | ||
--di; | ||
while (++di < n) { | ||
@@ -314,10 +291,9 @@ d = data[di]; | ||
h = d.size << 1; | ||
if (d.rotate) { | ||
var sr = Math.sin(d.rotate * cloudRadians), | ||
cr = Math.cos(d.rotate * cloudRadians), | ||
wcr = w * cr, | ||
wsr = w * sr, | ||
hcr = h * cr, | ||
hsr = h * sr; | ||
cr = Math.cos(d.rotate * cloudRadians), | ||
wcr = w * cr, | ||
wsr = w * sr, | ||
hcr = h * cr, | ||
hsr = h * sr; | ||
w = Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f >> 5 << 5; | ||
@@ -328,5 +304,3 @@ h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr)); | ||
} | ||
if (h > maxh) maxh = h; | ||
if (x + w >= cw << 5) { | ||
@@ -337,3 +311,2 @@ x = 0; | ||
} | ||
if (y + h >= ch) break; | ||
@@ -343,3 +316,2 @@ c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio); | ||
c.fillText(d.text, 0, 0); | ||
if (d.padding) { | ||
@@ -349,3 +321,2 @@ c.lineWidth = 2 * d.padding; | ||
} | ||
c.restore(); | ||
@@ -363,6 +334,4 @@ d.width = w; | ||
} | ||
var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data, | ||
sprite = []; | ||
sprite = []; | ||
while (--di >= 0) { | ||
@@ -373,6 +342,5 @@ d = data[di]; | ||
w32 = w >> 5; | ||
h = d.y1 - d.y0; // Zero the buffer | ||
h = d.y1 - d.y0; | ||
// Zero the buffer | ||
for (i = 0; i < h * w32; i++) sprite[i] = 0; | ||
x = d.xoff; | ||
@@ -382,12 +350,10 @@ if (x == null) return; | ||
var seen = 0, | ||
seenRow = -1; | ||
seenRow = -1; | ||
for (j = 0; j < h; j++) { | ||
for (i = 0; i < w; i++) { | ||
var k = w32 * j + (i >> 5), | ||
m = pixels[(y + j) * (cw << 5) + (x + i) << 2] ? 1 << 31 - i % 32 : 0; | ||
m = pixels[(y + j) * (cw << 5) + (x + i) << 2] ? 1 << 31 - i % 32 : 0; | ||
sprite[k] |= m; | ||
seen |= m; | ||
} | ||
if (seen) seenRow = j;else { | ||
@@ -400,36 +366,30 @@ d.y0++; | ||
} | ||
d.y1 = d.y0 + seenRow; | ||
d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32); | ||
} | ||
} // Use mask-based collision detection. | ||
} | ||
// Use mask-based collision detection. | ||
function cloudCollide(tag, board, sw) { | ||
sw >>= 5; | ||
var sprite = tag.sprite, | ||
w = tag.width >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
w = tag.width >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
for (var j = 0; j < h; j++) { | ||
last = 0; | ||
for (var i = 0; i <= w; i++) { | ||
if ((last << msx | (i < w ? (last = sprite[j * w + i]) >>> sx : 0)) & board[x + i]) return true; | ||
} | ||
x += sw; | ||
} | ||
return false; | ||
} | ||
function cloudBounds(bounds, d) { | ||
var b0 = bounds[0], | ||
b1 = bounds[1]; | ||
b1 = bounds[1]; | ||
if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; | ||
@@ -440,7 +400,5 @@ if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; | ||
} | ||
function collideRects(a, b) { | ||
return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y; | ||
} | ||
function archimedeanSpiral(size) { | ||
@@ -452,11 +410,10 @@ var e = size[0] / size[1]; | ||
} | ||
function rectangularSpiral(size) { | ||
var dy = 4, | ||
dx = dy * size[0] / size[1], | ||
x = 0, | ||
y = 0; | ||
dx = dy * size[0] / size[1], | ||
x = 0, | ||
y = 0; | ||
return function (t) { | ||
var sign = t < 0 ? -1 : 1; // See triangular numbers: T_n = n * (n + 1) / 2. | ||
var sign = t < 0 ? -1 : 1; | ||
// See triangular numbers: T_n = n * (n + 1) / 2. | ||
switch (Math.sqrt(1 + 4 * sign * t) - sign & 3) { | ||
@@ -466,11 +423,8 @@ case 0: | ||
break; | ||
case 1: | ||
y += dy; | ||
break; | ||
case 2: | ||
x -= dx; | ||
break; | ||
default: | ||
@@ -480,17 +434,13 @@ y -= dy; | ||
} | ||
return [x, y]; | ||
}; | ||
} // TODO reuse arrays? | ||
} | ||
// TODO reuse arrays? | ||
function zeroArray(n) { | ||
var a = [], | ||
i = -1; | ||
i = -1; | ||
while (++i < n) a[i] = 0; | ||
return a; | ||
} | ||
function functor(d) { | ||
@@ -501,3 +451,2 @@ return typeof d === 'function' ? d : function () { | ||
} | ||
var spirals = { | ||
@@ -577,3 +526,2 @@ archimedean: archimedeanSpiral, | ||
} | ||
function modp(param) { | ||
@@ -583,20 +531,17 @@ const p = _[param]; | ||
} | ||
const mod = _.modified(); | ||
if (!(mod || pulse.changed(pulse.ADD_REM) || Params.some(modp))) return; | ||
const data = pulse.materialize(pulse.SOURCE).source, | ||
layout = this.value, | ||
as = _.as || Output; | ||
layout = this.value, | ||
as = _.as || Output; | ||
let fontSize = _.fontSize || 14, | ||
range; | ||
vegaUtil.isFunction(fontSize) ? range = _.fontSizeRange : fontSize = vegaUtil.constant(fontSize); // create font size scaling function as needed | ||
range; | ||
vegaUtil.isFunction(fontSize) ? range = _.fontSizeRange : fontSize = vegaUtil.constant(fontSize); | ||
// create font size scaling function as needed | ||
if (range) { | ||
const fsize = fontSize, | ||
sizeScale = vegaScale.scale('sqrt')().domain(vegaUtil.extent(data, fsize)).range(range); | ||
sizeScale = vegaScale.scale('sqrt')().domain(vegaUtil.extent(data, fsize)).range(range); | ||
fontSize = x => sizeScale(fsize(x)); | ||
} | ||
data.forEach(t => { | ||
@@ -606,10 +551,10 @@ t[as[0]] = NaN; | ||
t[as[3]] = 0; | ||
}); // configure layout | ||
}); | ||
// configure layout | ||
const words = layout.words(data).text(_.text).size(_.size || [500, 500]).padding(_.padding || 1).spiral(_.spiral || 'archimedean').rotate(_.rotate || 0).font(_.font || 'sans-serif').fontStyle(_.fontStyle || 'normal').fontWeight(_.fontWeight || 'normal').fontSize(fontSize).random(vegaStatistics.random).layout(); | ||
const size = layout.size(), | ||
dx = size[0] >> 1, | ||
dy = size[1] >> 1, | ||
n = words.length; | ||
dx = size[0] >> 1, | ||
dy = size[1] >> 1, | ||
n = words.length; | ||
for (let i = 0, w, t; i < n; ++i) { | ||
@@ -626,6 +571,4 @@ w = words[i]; | ||
} | ||
return pulse.reflow(mod).modifies(as); | ||
} | ||
}); | ||
@@ -635,4 +578,2 @@ | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); | ||
})); |
@@ -1,2 +0,2 @@ | ||
this.vega=this.vega||{},this.vega.transforms=function(t,e,n,r,a,i){"use strict";var o=Math.PI/180,f=2048;function s(){var t,n,r,a,i,o,s,d=[256,256],g=h,m=[],p=Math.random,v={};function z(t,e,n){for(var r,a,i,o,f,s=e.x,u=e.y,l=Math.sqrt(d[0]*d[0]+d[1]*d[1]),h=g(d),x=p()<.5?1:-1,c=-x;(r=h(c+=x))&&(a=~~r[0],i=~~r[1],!(Math.min(Math.abs(a),Math.abs(i))>=l));)if(e.x=s+a,e.y=u+i,!(e.x+e.x0<0||e.y+e.y0<0||e.x+e.x1>d[0]||e.y+e.y1>d[1]||n&&y(e,t,d[0])||n&&(f=n,!((o=e).x+o.x1>f[0].x&&o.x+o.x0<f[1].x&&o.y+o.y1>f[0].y&&o.y+o.y0<f[1].y)))){for(var m,v=e.sprite,z=e.width>>5,M=d[0]>>5,b=e.x-(z<<4),S=127&b,w=32-S,T=e.y1-e.y0,W=(e.y+e.y0)*M+(b>>5),k=0;k<T;k++){m=0;for(var D=0;D<=z;D++)t[W+D]|=m<<w|(D<z?(m=v[k*z+D])>>>S:0);W+=M}return e.sprite=null,!0}return!1}return v.layout=function(){for(var y=function(t){t.width=t.height=1;var e=Math.sqrt(t.getContext("2d").getImageData(0,0,1,1).data.length>>2);t.width=2048/e,t.height=f/e;var n=t.getContext("2d");return n.fillStyle=n.strokeStyle="red",n.textAlign="center",{context:n,ratio:e}}(e.canvas()),h=function(t){var e=[],n=-1;for(;++n<t;)e[n]=0;return e}((d[0]>>5)*d[1]),x=null,c=m.length,g=-1,v=[],M=m.map(e=>({text:t(e),font:n(e),style:a(e),weight:i(e),rotate:o(e),size:~~(r(e)+1e-14),padding:s(e),xoff:0,yoff:0,x1:0,y1:0,x0:0,y0:0,hasText:!1,sprite:null,datum:e})).sort((t,e)=>e.size-t.size);++g<c;){var b=M[g];b.x=d[0]*(p()+.5)>>1,b.y=d[1]*(p()+.5)>>1,u(y,b,M,g),b.hasText&&z(h,b,x)&&(v.push(b),x?l(x,b):x=[{x:b.x+b.x0,y:b.y+b.y0},{x:b.x+b.x1,y:b.y+b.y1}],b.x-=d[0]>>1,b.y-=d[1]>>1)}return v},v.words=function(t){return arguments.length?(m=t,v):m},v.size=function(t){return arguments.length?(d=[+t[0],+t[1]],v):d},v.font=function(t){return arguments.length?(n=x(t),v):n},v.fontStyle=function(t){return arguments.length?(a=x(t),v):a},v.fontWeight=function(t){return arguments.length?(i=x(t),v):i},v.rotate=function(t){return arguments.length?(o=x(t),v):o},v.text=function(e){return arguments.length?(t=x(e),v):t},v.spiral=function(t){return arguments.length?(g=c[t]||t,v):g},v.fontSize=function(t){return arguments.length?(r=x(t),v):r},v.padding=function(t){return arguments.length?(s=x(t),v):s},v.random=function(t){return arguments.length?(p=t,v):p},v}function u(t,e,n,r){if(!e.sprite){var a=t.context,i=t.ratio;a.clearRect(0,0,2048/i,f/i);var s,u,y,l,h,x=0,c=0,d=0,g=n.length;for(--r;++r<g;){if(e=n[r],a.save(),a.font=e.style+" "+e.weight+" "+~~((e.size+1)/i)+"px "+e.font,s=a.measureText(e.text+"m").width*i,y=e.size<<1,e.rotate){var m=Math.sin(e.rotate*o),p=Math.cos(e.rotate*o),v=s*p,z=s*m,M=y*p,b=y*m;s=Math.max(Math.abs(v+b),Math.abs(v-b))+31>>5<<5,y=~~Math.max(Math.abs(z+M),Math.abs(z-M))}else s=s+31>>5<<5;if(y>d&&(d=y),x+s>=2048&&(x=0,c+=d,d=0),c+y>=f)break;a.translate((x+(s>>1))/i,(c+(y>>1))/i),e.rotate&&a.rotate(e.rotate*o),a.fillText(e.text,0,0),e.padding&&(a.lineWidth=2*e.padding,a.strokeText(e.text,0,0)),a.restore(),e.width=s,e.height=y,e.xoff=x,e.yoff=c,e.x1=s>>1,e.y1=y>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,x+=s}for(var S=a.getImageData(0,0,2048/i,f/i).data,w=[];--r>=0;)if((e=n[r]).hasText){for(u=(s=e.width)>>5,y=e.y1-e.y0,l=0;l<y*u;l++)w[l]=0;if(null==(x=e.xoff))return;c=e.yoff;var T=0,W=-1;for(h=0;h<y;h++){for(l=0;l<s;l++){var k=u*h+(l>>5),D=S[2048*(c+h)+(x+l)<<2]?1<<31-l%32:0;w[k]|=D,T|=D}T?W=h:(e.y0++,y--,h--,c++)}e.y1=e.y0+W,e.sprite=w.slice(0,(e.y1-e.y0)*u)}}}function y(t,e,n){n>>=5;for(var r,a=t.sprite,i=t.width>>5,o=t.x-(i<<4),f=127&o,s=32-f,u=t.y1-t.y0,y=(t.y+t.y0)*n+(o>>5),l=0;l<u;l++){r=0;for(var h=0;h<=i;h++)if((r<<s|(h<i?(r=a[l*i+h])>>>f:0))&e[y+h])return!0;y+=n}return!1}function l(t,e){var n=t[0],r=t[1];e.x+e.x0<n.x&&(n.x=e.x+e.x0),e.y+e.y0<n.y&&(n.y=e.y+e.y0),e.x+e.x1>r.x&&(r.x=e.x+e.x1),e.y+e.y1>r.y&&(r.y=e.y+e.y1)}function h(t){var e=t[0]/t[1];return function(t){return[e*(t*=.1)*Math.cos(t),t*Math.sin(t)]}}function x(t){return"function"==typeof t?t:function(){return t}}var c={archimedean:h,rectangular:function(t){var e=4*t[0]/t[1],n=0,r=0;return function(t){var a=t<0?-1:1;switch(Math.sqrt(1+4*a*t)-a&3){case 0:n+=e;break;case 1:r+=4;break;case 2:n-=e;break;default:r-=4}return[n,r]}}};const d=["x","y","font","fontSize","fontStyle","fontWeight","angle"],g=["text","font","rotate","fontSize","fontStyle","fontWeight"];function m(t){n.Transform.call(this,s(),t)}return m.Definition={type:"Wordcloud",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2},{name:"font",type:"string",expr:!0,default:"sans-serif"},{name:"fontStyle",type:"string",expr:!0,default:"normal"},{name:"fontWeight",type:"string",expr:!0,default:"normal"},{name:"fontSize",type:"number",expr:!0,default:14},{name:"fontSizeRange",type:"number",array:"nullable",default:[10,50]},{name:"rotate",type:"number",expr:!0,default:0},{name:"text",type:"field"},{name:"spiral",type:"string",values:["archimedean","rectangular"]},{name:"padding",type:"number",expr:!0},{name:"as",type:"string",array:!0,length:7,default:d}]},r.inherits(m,n.Transform,{transform(t,e){!t.size||t.size[0]&&t.size[1]||r.error("Wordcloud size dimensions must be non-zero.");const n=t.modified();if(!(n||e.changed(e.ADD_REM)||g.some((function(n){const a=t[n];return r.isFunction(a)&&e.modified(a.fields)}))))return;const o=e.materialize(e.SOURCE).source,f=this.value,s=t.as||d;let u,y=t.fontSize||14;if(r.isFunction(y)?u=t.fontSizeRange:y=r.constant(y),u){const t=y,e=a.scale("sqrt")().domain(r.extent(o,t)).range(u);y=n=>e(t(n))}o.forEach(t=>{t[s[0]]=NaN,t[s[1]]=NaN,t[s[3]]=0});const l=f.words(o).text(t.text).size(t.size||[500,500]).padding(t.padding||1).spiral(t.spiral||"archimedean").rotate(t.rotate||0).font(t.font||"sans-serif").fontStyle(t.fontStyle||"normal").fontWeight(t.fontWeight||"normal").fontSize(y).random(i.random).layout(),h=f.size(),x=h[0]>>1,c=h[1]>>1,m=l.length;for(let t,e,n=0;n<m;++n)t=l[n],e=t.datum,e[s[0]]=t.x+x,e[s[1]]=t.y+c,e[s[2]]=t.font,e[s[3]]=t.size,e[s[4]]=t.style,e[s[5]]=t.weight,e[s[6]]=t.rotate;return e.reflow(n).modifies(s)}}),t.wordcloud=m,t}({},vega,vega,vega,vega,vega); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("vega-canvas"),require("vega-dataflow"),require("vega-util"),require("vega-scale"),require("vega-statistics")):"function"==typeof define&&define.amd?define(["exports","vega-canvas","vega-dataflow","vega-util","vega-scale","vega-statistics"],e):e(((t="undefined"!=typeof globalThis?globalThis:t||self).vega=t.vega||{},t.vega.transforms={}),t.vega,t.vega,t.vega,t.vega,t.vega)}(this,(function(t,e,n,a,r,i){"use strict";var o=Math.PI/180,f=64,s=2048;function u(){var t,n,a,r,i,o,u,c=[256,256],m=d,p=[],v=Math.random,z={};function b(t,e,n){for(var a,r,i,o,f,s=e.x,u=e.y,l=Math.sqrt(c[0]*c[0]+c[1]*c[1]),x=m(c),d=v()<.5?1:-1,g=-d;(a=x(g+=d))&&(r=~~a[0],i=~~a[1],!(Math.min(Math.abs(r),Math.abs(i))>=l));)if(e.x=s+r,e.y=u+i,!(e.x+e.x0<0||e.y+e.y0<0||e.x+e.x1>c[0]||e.y+e.y1>c[1]||n&&y(e,t,c[0])||n&&(f=n,!((o=e).x+o.x1>f[0].x&&o.x+o.x0<f[1].x&&o.y+o.y1>f[0].y&&o.y+o.y0<f[1].y)))){for(var h,p=e.sprite,z=e.width>>5,b=c[0]>>5,M=e.x-(z<<4),w=127&M,S=32-w,T=e.y1-e.y0,q=(e.y+e.y0)*b+(M>>5),W=0;W<T;W++){h=0;for(var k=0;k<=z;k++)t[q+k]|=h<<S|(k<z?(h=p[W*z+k])>>>w:0);q+=b}return e.sprite=null,!0}return!1}return z.layout=function(){for(var y=function(t){t.width=t.height=1;var e=Math.sqrt(t.getContext("2d").getImageData(0,0,1,1).data.length>>2);t.width=(f<<5)/e,t.height=s/e;var n=t.getContext("2d");return n.fillStyle=n.strokeStyle="red",n.textAlign="center",{context:n,ratio:e}}(e.canvas()),d=function(t){var e=[],n=-1;for(;++n<t;)e[n]=0;return e}((c[0]>>5)*c[1]),g=null,h=p.length,m=-1,z=[],M=p.map((e=>({text:t(e),font:n(e),style:r(e),weight:i(e),rotate:o(e),size:~~(a(e)+1e-14),padding:u(e),xoff:0,yoff:0,x1:0,y1:0,x0:0,y0:0,hasText:!1,sprite:null,datum:e}))).sort(((t,e)=>e.size-t.size));++m<h;){var w=M[m];w.x=c[0]*(v()+.5)>>1,w.y=c[1]*(v()+.5)>>1,l(y,w,M,m),w.hasText&&b(d,w,g)&&(z.push(w),g?x(g,w):g=[{x:w.x+w.x0,y:w.y+w.y0},{x:w.x+w.x1,y:w.y+w.y1}],w.x-=c[0]>>1,w.y-=c[1]>>1)}return z},z.words=function(t){return arguments.length?(p=t,z):p},z.size=function(t){return arguments.length?(c=[+t[0],+t[1]],z):c},z.font=function(t){return arguments.length?(n=g(t),z):n},z.fontStyle=function(t){return arguments.length?(r=g(t),z):r},z.fontWeight=function(t){return arguments.length?(i=g(t),z):i},z.rotate=function(t){return arguments.length?(o=g(t),z):o},z.text=function(e){return arguments.length?(t=g(e),z):t},z.spiral=function(t){return arguments.length?(m=h[t]||t,z):m},z.fontSize=function(t){return arguments.length?(a=g(t),z):a},z.padding=function(t){return arguments.length?(u=g(t),z):u},z.random=function(t){return arguments.length?(v=t,z):v},z}function l(t,e,n,a){if(!e.sprite){var r=t.context,i=t.ratio;r.clearRect(0,0,(f<<5)/i,s/i);var u,l,y,x,d,g=0,h=0,c=0,m=n.length;for(--a;++a<m;){if(e=n[a],r.save(),r.font=e.style+" "+e.weight+" "+~~((e.size+1)/i)+"px "+e.font,u=r.measureText(e.text+"m").width*i,y=e.size<<1,e.rotate){var p=Math.sin(e.rotate*o),v=Math.cos(e.rotate*o),z=u*v,b=u*p,M=y*v,w=y*p;u=Math.max(Math.abs(z+w),Math.abs(z-w))+31>>5<<5,y=~~Math.max(Math.abs(b+M),Math.abs(b-M))}else u=u+31>>5<<5;if(y>c&&(c=y),g+u>=f<<5&&(g=0,h+=c,c=0),h+y>=s)break;r.translate((g+(u>>1))/i,(h+(y>>1))/i),e.rotate&&r.rotate(e.rotate*o),r.fillText(e.text,0,0),e.padding&&(r.lineWidth=2*e.padding,r.strokeText(e.text,0,0)),r.restore(),e.width=u,e.height=y,e.xoff=g,e.yoff=h,e.x1=u>>1,e.y1=y>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,g+=u}for(var S=r.getImageData(0,0,(f<<5)/i,s/i).data,T=[];--a>=0;)if((e=n[a]).hasText){for(l=(u=e.width)>>5,y=e.y1-e.y0,x=0;x<y*l;x++)T[x]=0;if(null==(g=e.xoff))return;h=e.yoff;var q=0,W=-1;for(d=0;d<y;d++){for(x=0;x<u;x++){var k=l*d+(x>>5),D=S[(h+d)*(f<<5)+(g+x)<<2]?1<<31-x%32:0;T[k]|=D,q|=D}q?W=d:(e.y0++,y--,d--,h++)}e.y1=e.y0+W,e.sprite=T.slice(0,(e.y1-e.y0)*l)}}}function y(t,e,n){n>>=5;for(var a,r=t.sprite,i=t.width>>5,o=t.x-(i<<4),f=127&o,s=32-f,u=t.y1-t.y0,l=(t.y+t.y0)*n+(o>>5),y=0;y<u;y++){a=0;for(var x=0;x<=i;x++)if((a<<s|(x<i?(a=r[y*i+x])>>>f:0))&e[l+x])return!0;l+=n}return!1}function x(t,e){var n=t[0],a=t[1];e.x+e.x0<n.x&&(n.x=e.x+e.x0),e.y+e.y0<n.y&&(n.y=e.y+e.y0),e.x+e.x1>a.x&&(a.x=e.x+e.x1),e.y+e.y1>a.y&&(a.y=e.y+e.y1)}function d(t){var e=t[0]/t[1];return function(t){return[e*(t*=.1)*Math.cos(t),t*Math.sin(t)]}}function g(t){return"function"==typeof t?t:function(){return t}}var h={archimedean:d,rectangular:function(t){var e=4*t[0]/t[1],n=0,a=0;return function(t){var r=t<0?-1:1;switch(Math.sqrt(1+4*r*t)-r&3){case 0:n+=e;break;case 1:a+=4;break;case 2:n-=e;break;default:a-=4}return[n,a]}}};const c=["x","y","font","fontSize","fontStyle","fontWeight","angle"],m=["text","font","rotate","fontSize","fontStyle","fontWeight"];function p(t){n.Transform.call(this,u(),t)}p.Definition={type:"Wordcloud",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2},{name:"font",type:"string",expr:!0,default:"sans-serif"},{name:"fontStyle",type:"string",expr:!0,default:"normal"},{name:"fontWeight",type:"string",expr:!0,default:"normal"},{name:"fontSize",type:"number",expr:!0,default:14},{name:"fontSizeRange",type:"number",array:"nullable",default:[10,50]},{name:"rotate",type:"number",expr:!0,default:0},{name:"text",type:"field"},{name:"spiral",type:"string",values:["archimedean","rectangular"]},{name:"padding",type:"number",expr:!0},{name:"as",type:"string",array:!0,length:7,default:c}]},a.inherits(p,n.Transform,{transform(t,e){!t.size||t.size[0]&&t.size[1]||a.error("Wordcloud size dimensions must be non-zero.");const n=t.modified();if(!(n||e.changed(e.ADD_REM)||m.some((function(n){const r=t[n];return a.isFunction(r)&&e.modified(r.fields)}))))return;const o=e.materialize(e.SOURCE).source,f=this.value,s=t.as||c;let u,l=t.fontSize||14;if(a.isFunction(l)?u=t.fontSizeRange:l=a.constant(l),u){const t=l,e=r.scale("sqrt")().domain(a.extent(o,t)).range(u);l=n=>e(t(n))}o.forEach((t=>{t[s[0]]=NaN,t[s[1]]=NaN,t[s[3]]=0}));const y=f.words(o).text(t.text).size(t.size||[500,500]).padding(t.padding||1).spiral(t.spiral||"archimedean").rotate(t.rotate||0).font(t.font||"sans-serif").fontStyle(t.fontStyle||"normal").fontWeight(t.fontWeight||"normal").fontSize(l).random(i.random).layout(),x=f.size(),d=x[0]>>1,g=x[1]>>1,h=y.length;for(let t,e,n=0;n<h;++n)t=y[n],e=t.datum,e[s[0]]=t.x+d,e[s[1]]=t.y+g,e[s[2]]=t.font,e[s[3]]=t.size,e[s[4]]=t.style,e[s[5]]=t.weight,e[s[6]]=t.rotate;return e.reflow(n).modifies(s)}}),t.wordcloud=p})); | ||
//# sourceMappingURL=vega-wordcloud.min.js.map |
@@ -35,2 +35,3 @@ import { canvas } from 'vega-canvas'; | ||
*/ | ||
// Word cloud layout by Jason Davies, https://www.jasondavies.com/wordcloud/ | ||
@@ -40,44 +41,42 @@ // Algorithm due to Jonathan Feinberg, http://static.mrfeinberg.com/bv_ch03.pdf | ||
var cloudRadians = Math.PI / 180, | ||
cw = 1 << 11 >> 5, | ||
ch = 1 << 11; | ||
cw = 1 << 11 >> 5, | ||
ch = 1 << 11; | ||
function cloud () { | ||
var size = [256, 256], | ||
text, | ||
font, | ||
fontSize, | ||
fontStyle, | ||
fontWeight, | ||
rotate, | ||
padding, | ||
spiral = archimedeanSpiral, | ||
words = [], | ||
random = Math.random, | ||
cloud = {}; | ||
text, | ||
font, | ||
fontSize, | ||
fontStyle, | ||
fontWeight, | ||
rotate, | ||
padding, | ||
spiral = archimedeanSpiral, | ||
words = [], | ||
random = Math.random, | ||
cloud = {}; | ||
cloud.layout = function () { | ||
var contextAndRatio = getContext(canvas()), | ||
board = zeroArray((size[0] >> 5) * size[1]), | ||
bounds = null, | ||
n = words.length, | ||
i = -1, | ||
tags = [], | ||
data = words.map(d => ({ | ||
text: text(d), | ||
font: font(d), | ||
style: fontStyle(d), | ||
weight: fontWeight(d), | ||
rotate: rotate(d), | ||
size: ~~(fontSize(d) + 1e-14), | ||
padding: padding(d), | ||
xoff: 0, | ||
yoff: 0, | ||
x1: 0, | ||
y1: 0, | ||
x0: 0, | ||
y0: 0, | ||
hasText: false, | ||
sprite: null, | ||
datum: d | ||
})).sort((a, b) => b.size - a.size); | ||
board = zeroArray((size[0] >> 5) * size[1]), | ||
bounds = null, | ||
n = words.length, | ||
i = -1, | ||
tags = [], | ||
data = words.map(d => ({ | ||
text: text(d), | ||
font: font(d), | ||
style: fontStyle(d), | ||
weight: fontWeight(d), | ||
rotate: rotate(d), | ||
size: ~~(fontSize(d) + 1e-14), | ||
padding: padding(d), | ||
xoff: 0, | ||
yoff: 0, | ||
x1: 0, | ||
y1: 0, | ||
x0: 0, | ||
y0: 0, | ||
hasText: false, | ||
sprite: null, | ||
datum: d | ||
})).sort((a, b) => b.size - a.size); | ||
while (++i < n) { | ||
@@ -88,3 +87,2 @@ var d = data[i]; | ||
cloudSprite(contextAndRatio, d, data, i); | ||
if (d.hasText && place(board, d, bounds)) { | ||
@@ -98,4 +96,4 @@ tags.push(d); | ||
y: d.y + d.y1 | ||
}]; // Temporary hack | ||
}]; | ||
// Temporary hack | ||
d.x -= size[0] >> 1; | ||
@@ -105,6 +103,4 @@ d.y -= size[1] >> 1; | ||
} | ||
return tags; | ||
}; | ||
function getContext(canvas) { | ||
@@ -123,14 +119,12 @@ canvas.width = canvas.height = 1; | ||
} | ||
function place(board, tag, bounds) { | ||
var startX = tag.x, | ||
startY = tag.y, | ||
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), | ||
s = spiral(size), | ||
dt = random() < .5 ? 1 : -1, | ||
t = -dt, | ||
dxdy, | ||
dx, | ||
dy; | ||
startY = tag.y, | ||
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), | ||
s = spiral(size), | ||
dt = random() < .5 ? 1 : -1, | ||
t = -dt, | ||
dxdy, | ||
dx, | ||
dy; | ||
while (dxdy = s(t += dt)) { | ||
@@ -142,26 +136,22 @@ dx = ~~dxdy[0]; | ||
tag.y = startY + dy; | ||
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; // TODO only check for collisions within current bounds. | ||
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; | ||
// TODO only check for collisions within current bounds. | ||
if (!bounds || !cloudCollide(tag, board, size[0])) { | ||
if (!bounds || collideRects(tag, bounds)) { | ||
var sprite = tag.sprite, | ||
w = tag.width >> 5, | ||
sw = size[0] >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
w = tag.width >> 5, | ||
sw = size[0] >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
for (var j = 0; j < h; j++) { | ||
last = 0; | ||
for (var i = 0; i <= w; i++) { | ||
board[x + i] |= last << msx | (i < w ? (last = sprite[j * w + i]) >>> sx : 0); | ||
} | ||
x += sw; | ||
} | ||
tag.sprite = null; | ||
@@ -172,6 +162,4 @@ return true; | ||
} | ||
return false; | ||
} | ||
cloud.words = function (_) { | ||
@@ -185,3 +173,2 @@ if (arguments.length) { | ||
}; | ||
cloud.size = function (_) { | ||
@@ -195,3 +182,2 @@ if (arguments.length) { | ||
}; | ||
cloud.font = function (_) { | ||
@@ -205,3 +191,2 @@ if (arguments.length) { | ||
}; | ||
cloud.fontStyle = function (_) { | ||
@@ -215,3 +200,2 @@ if (arguments.length) { | ||
}; | ||
cloud.fontWeight = function (_) { | ||
@@ -225,3 +209,2 @@ if (arguments.length) { | ||
}; | ||
cloud.rotate = function (_) { | ||
@@ -235,3 +218,2 @@ if (arguments.length) { | ||
}; | ||
cloud.text = function (_) { | ||
@@ -245,3 +227,2 @@ if (arguments.length) { | ||
}; | ||
cloud.spiral = function (_) { | ||
@@ -255,3 +236,2 @@ if (arguments.length) { | ||
}; | ||
cloud.fontSize = function (_) { | ||
@@ -265,3 +245,2 @@ if (arguments.length) { | ||
}; | ||
cloud.padding = function (_) { | ||
@@ -275,3 +254,2 @@ if (arguments.length) { | ||
}; | ||
cloud.random = function (_) { | ||
@@ -285,23 +263,22 @@ if (arguments.length) { | ||
}; | ||
return cloud; | ||
} | ||
return cloud; | ||
} // Fetches a monochrome sprite bitmap for the specified text. | ||
// Fetches a monochrome sprite bitmap for the specified text. | ||
// Load in batches for speed. | ||
function cloudSprite(contextAndRatio, d, data, di) { | ||
if (d.sprite) return; | ||
var c = contextAndRatio.context, | ||
ratio = contextAndRatio.ratio; | ||
ratio = contextAndRatio.ratio; | ||
c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio); | ||
var x = 0, | ||
y = 0, | ||
maxh = 0, | ||
n = data.length, | ||
w, | ||
w32, | ||
h, | ||
i, | ||
j; | ||
y = 0, | ||
maxh = 0, | ||
n = data.length, | ||
w, | ||
w32, | ||
h, | ||
i, | ||
j; | ||
--di; | ||
while (++di < n) { | ||
@@ -313,10 +290,9 @@ d = data[di]; | ||
h = d.size << 1; | ||
if (d.rotate) { | ||
var sr = Math.sin(d.rotate * cloudRadians), | ||
cr = Math.cos(d.rotate * cloudRadians), | ||
wcr = w * cr, | ||
wsr = w * sr, | ||
hcr = h * cr, | ||
hsr = h * sr; | ||
cr = Math.cos(d.rotate * cloudRadians), | ||
wcr = w * cr, | ||
wsr = w * sr, | ||
hcr = h * cr, | ||
hsr = h * sr; | ||
w = Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f >> 5 << 5; | ||
@@ -327,5 +303,3 @@ h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr)); | ||
} | ||
if (h > maxh) maxh = h; | ||
if (x + w >= cw << 5) { | ||
@@ -336,3 +310,2 @@ x = 0; | ||
} | ||
if (y + h >= ch) break; | ||
@@ -342,3 +315,2 @@ c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio); | ||
c.fillText(d.text, 0, 0); | ||
if (d.padding) { | ||
@@ -348,3 +320,2 @@ c.lineWidth = 2 * d.padding; | ||
} | ||
c.restore(); | ||
@@ -362,6 +333,4 @@ d.width = w; | ||
} | ||
var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data, | ||
sprite = []; | ||
sprite = []; | ||
while (--di >= 0) { | ||
@@ -372,6 +341,5 @@ d = data[di]; | ||
w32 = w >> 5; | ||
h = d.y1 - d.y0; // Zero the buffer | ||
h = d.y1 - d.y0; | ||
// Zero the buffer | ||
for (i = 0; i < h * w32; i++) sprite[i] = 0; | ||
x = d.xoff; | ||
@@ -381,12 +349,10 @@ if (x == null) return; | ||
var seen = 0, | ||
seenRow = -1; | ||
seenRow = -1; | ||
for (j = 0; j < h; j++) { | ||
for (i = 0; i < w; i++) { | ||
var k = w32 * j + (i >> 5), | ||
m = pixels[(y + j) * (cw << 5) + (x + i) << 2] ? 1 << 31 - i % 32 : 0; | ||
m = pixels[(y + j) * (cw << 5) + (x + i) << 2] ? 1 << 31 - i % 32 : 0; | ||
sprite[k] |= m; | ||
seen |= m; | ||
} | ||
if (seen) seenRow = j;else { | ||
@@ -399,36 +365,30 @@ d.y0++; | ||
} | ||
d.y1 = d.y0 + seenRow; | ||
d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32); | ||
} | ||
} // Use mask-based collision detection. | ||
} | ||
// Use mask-based collision detection. | ||
function cloudCollide(tag, board, sw) { | ||
sw >>= 5; | ||
var sprite = tag.sprite, | ||
w = tag.width >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
w = tag.width >> 5, | ||
lx = tag.x - (w << 4), | ||
sx = lx & 0x7f, | ||
msx = 32 - sx, | ||
h = tag.y1 - tag.y0, | ||
x = (tag.y + tag.y0) * sw + (lx >> 5), | ||
last; | ||
for (var j = 0; j < h; j++) { | ||
last = 0; | ||
for (var i = 0; i <= w; i++) { | ||
if ((last << msx | (i < w ? (last = sprite[j * w + i]) >>> sx : 0)) & board[x + i]) return true; | ||
} | ||
x += sw; | ||
} | ||
return false; | ||
} | ||
function cloudBounds(bounds, d) { | ||
var b0 = bounds[0], | ||
b1 = bounds[1]; | ||
b1 = bounds[1]; | ||
if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; | ||
@@ -439,7 +399,5 @@ if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; | ||
} | ||
function collideRects(a, b) { | ||
return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y; | ||
} | ||
function archimedeanSpiral(size) { | ||
@@ -451,11 +409,10 @@ var e = size[0] / size[1]; | ||
} | ||
function rectangularSpiral(size) { | ||
var dy = 4, | ||
dx = dy * size[0] / size[1], | ||
x = 0, | ||
y = 0; | ||
dx = dy * size[0] / size[1], | ||
x = 0, | ||
y = 0; | ||
return function (t) { | ||
var sign = t < 0 ? -1 : 1; // See triangular numbers: T_n = n * (n + 1) / 2. | ||
var sign = t < 0 ? -1 : 1; | ||
// See triangular numbers: T_n = n * (n + 1) / 2. | ||
switch (Math.sqrt(1 + 4 * sign * t) - sign & 3) { | ||
@@ -465,11 +422,8 @@ case 0: | ||
break; | ||
case 1: | ||
y += dy; | ||
break; | ||
case 2: | ||
x -= dx; | ||
break; | ||
default: | ||
@@ -479,17 +433,13 @@ y -= dy; | ||
} | ||
return [x, y]; | ||
}; | ||
} // TODO reuse arrays? | ||
} | ||
// TODO reuse arrays? | ||
function zeroArray(n) { | ||
var a = [], | ||
i = -1; | ||
i = -1; | ||
while (++i < n) a[i] = 0; | ||
return a; | ||
} | ||
function functor(d) { | ||
@@ -500,3 +450,2 @@ return typeof d === 'function' ? d : function () { | ||
} | ||
var spirals = { | ||
@@ -576,3 +525,2 @@ archimedean: archimedeanSpiral, | ||
} | ||
function modp(param) { | ||
@@ -582,20 +530,17 @@ const p = _[param]; | ||
} | ||
const mod = _.modified(); | ||
if (!(mod || pulse.changed(pulse.ADD_REM) || Params.some(modp))) return; | ||
const data = pulse.materialize(pulse.SOURCE).source, | ||
layout = this.value, | ||
as = _.as || Output; | ||
layout = this.value, | ||
as = _.as || Output; | ||
let fontSize = _.fontSize || 14, | ||
range; | ||
isFunction(fontSize) ? range = _.fontSizeRange : fontSize = constant(fontSize); // create font size scaling function as needed | ||
range; | ||
isFunction(fontSize) ? range = _.fontSizeRange : fontSize = constant(fontSize); | ||
// create font size scaling function as needed | ||
if (range) { | ||
const fsize = fontSize, | ||
sizeScale = scale('sqrt')().domain(extent(data, fsize)).range(range); | ||
sizeScale = scale('sqrt')().domain(extent(data, fsize)).range(range); | ||
fontSize = x => sizeScale(fsize(x)); | ||
} | ||
data.forEach(t => { | ||
@@ -605,10 +550,10 @@ t[as[0]] = NaN; | ||
t[as[3]] = 0; | ||
}); // configure layout | ||
}); | ||
// configure layout | ||
const words = layout.words(data).text(_.text).size(_.size || [500, 500]).padding(_.padding || 1).spiral(_.spiral || 'archimedean').rotate(_.rotate || 0).font(_.font || 'sans-serif').fontStyle(_.fontStyle || 'normal').fontWeight(_.fontWeight || 'normal').fontSize(fontSize).random(random).layout(); | ||
const size = layout.size(), | ||
dx = size[0] >> 1, | ||
dy = size[1] >> 1, | ||
n = words.length; | ||
dx = size[0] >> 1, | ||
dy = size[1] >> 1, | ||
n = words.length; | ||
for (let i = 0, w, t; i < n; ++i) { | ||
@@ -625,8 +570,6 @@ w = words[i]; | ||
} | ||
return pulse.reflow(mod).modifies(as); | ||
} | ||
}); | ||
export { Wordcloud as wordcloud }; |
{ | ||
"name": "vega-wordcloud", | ||
"version": "4.1.3", | ||
"version": "4.1.4", | ||
"description": "Wordcloud layout transform for Vega dataflows.", | ||
@@ -18,3 +18,3 @@ "keywords": [ | ||
"prebuild": "rimraf build", | ||
"build": "rollup -c --config-transform", | ||
"build": "rollup -c rollup.config.mjs --config-transform", | ||
"pretest": "yarn build --config-test", | ||
@@ -25,7 +25,7 @@ "test": "tape 'test/**/*-test.js'", | ||
"dependencies": { | ||
"vega-canvas": "^1.2.5", | ||
"vega-dataflow": "^5.7.3", | ||
"vega-scale": "^7.1.1", | ||
"vega-statistics": "^1.7.9", | ||
"vega-util": "^1.15.2" | ||
"vega-canvas": "^1.2.7", | ||
"vega-dataflow": "^5.7.5", | ||
"vega-scale": "^7.3.0", | ||
"vega-statistics": "^1.8.1", | ||
"vega-util": "^1.17.1" | ||
}, | ||
@@ -35,3 +35,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "4affcbedb9d14815dbb6d3b250ed231b54fc95c0" | ||
"gitHead": "fb1092f6b931d450f9c210b67ae4752bd3dd461b" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79299
1554
2
Updatedvega-canvas@^1.2.7
Updatedvega-dataflow@^5.7.5
Updatedvega-scale@^7.3.0
Updatedvega-statistics@^1.8.1
Updatedvega-util@^1.17.1