chartjs-chart-wordcloud
Advanced tools
Comparing version 4.4.1 to 4.4.2
@@ -190,3 +190,3 @@ /** | ||
} | ||
console.warn('cannot fit all text elements in three tries'); | ||
console.warn(`cannot fit all text elements in ${growOptions.maxTries} tries`); | ||
} | ||
@@ -193,0 +193,0 @@ const wb = bounds[1].x - bounds[0].x; |
@@ -45,3 +45,3 @@ /** | ||
function dispatch$1() { | ||
function dispatch() { | ||
for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { | ||
@@ -67,3 +67,3 @@ if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) throw new Error("illegal type: " + t); | ||
Dispatch.prototype = dispatch$1.prototype = { | ||
Dispatch.prototype = dispatch.prototype = { | ||
constructor: Dispatch, | ||
@@ -130,3 +130,3 @@ on: function(typename, callback) { | ||
__proto__: null, | ||
dispatch: dispatch$1 | ||
dispatch: dispatch | ||
}); | ||
@@ -136,408 +136,417 @@ | ||
// Word cloud layout by Jason Davies, https://www.jasondavies.com/wordcloud/ | ||
// Algorithm due to Jonathan Feinberg, https://s3.amazonaws.com/static.mrfeinberg.com/bv_ch03.pdf | ||
var d3Cloud; | ||
var hasRequiredD3Cloud; | ||
const dispatch = require$$0.dispatch; | ||
function requireD3Cloud () { | ||
if (hasRequiredD3Cloud) return d3Cloud; | ||
hasRequiredD3Cloud = 1; | ||
// Word cloud layout by Jason Davies, https://www.jasondavies.com/wordcloud/ | ||
// Algorithm due to Jonathan Feinberg, https://s3.amazonaws.com/static.mrfeinberg.com/bv_ch03.pdf | ||
const RADIANS = Math.PI / 180; | ||
const dispatch = require$$0.dispatch; | ||
const SPIRALS = { | ||
archimedean: archimedeanSpiral, | ||
rectangular: rectangularSpiral | ||
}; | ||
const RADIANS = Math.PI / 180; | ||
const cw = 1 << 11 >> 5; | ||
const ch = 1 << 11; | ||
const SPIRALS = { | ||
archimedean: archimedeanSpiral, | ||
rectangular: rectangularSpiral | ||
}; | ||
var d3Cloud = function() { | ||
var size = [256, 256], | ||
text = cloudText, | ||
font = cloudFont, | ||
fontSize = cloudFontSize, | ||
fontStyle = cloudFontNormal, | ||
fontWeight = cloudFontNormal, | ||
rotate = cloudRotate, | ||
padding = cloudPadding, | ||
spiral = archimedeanSpiral, | ||
words = [], | ||
timeInterval = Infinity, | ||
event = dispatch("word", "end"), | ||
timer = null, | ||
random = Math.random, | ||
cloud = {}, | ||
canvas = cloudCanvas; | ||
const cw = 1 << 11 >> 5; | ||
const ch = 1 << 11; | ||
cloud.canvas = function(_) { | ||
return arguments.length ? (canvas = functor(_), cloud) : canvas; | ||
}; | ||
d3Cloud = function() { | ||
var size = [256, 256], | ||
text = cloudText, | ||
font = cloudFont, | ||
fontSize = cloudFontSize, | ||
fontStyle = cloudFontNormal, | ||
fontWeight = cloudFontNormal, | ||
rotate = cloudRotate, | ||
padding = cloudPadding, | ||
spiral = archimedeanSpiral, | ||
words = [], | ||
timeInterval = Infinity, | ||
event = dispatch("word", "end"), | ||
timer = null, | ||
random = Math.random, | ||
cloud = {}, | ||
canvas = cloudCanvas; | ||
cloud.start = function() { | ||
var contextAndRatio = getContext(canvas()), | ||
board = zeroArray((size[0] >> 5) * size[1]), | ||
bounds = null, | ||
n = words.length, | ||
i = -1, | ||
tags = [], | ||
data = words.map(function(d, i) { | ||
d.text = text.call(this, d, i); | ||
d.font = font.call(this, d, i); | ||
d.style = fontStyle.call(this, d, i); | ||
d.weight = fontWeight.call(this, d, i); | ||
d.rotate = rotate.call(this, d, i); | ||
d.size = ~~fontSize.call(this, d, i); | ||
d.padding = padding.call(this, d, i); | ||
return d; | ||
}).sort(function(a, b) { return b.size - a.size; }); | ||
cloud.canvas = function(_) { | ||
return arguments.length ? (canvas = functor(_), cloud) : canvas; | ||
}; | ||
if (timer) clearInterval(timer); | ||
timer = setInterval(step, 0); | ||
step(); | ||
cloud.start = function() { | ||
var contextAndRatio = getContext(canvas()), | ||
board = zeroArray((size[0] >> 5) * size[1]), | ||
bounds = null, | ||
n = words.length, | ||
i = -1, | ||
tags = [], | ||
data = words.map(function(d, i) { | ||
d.text = text.call(this, d, i); | ||
d.font = font.call(this, d, i); | ||
d.style = fontStyle.call(this, d, i); | ||
d.weight = fontWeight.call(this, d, i); | ||
d.rotate = rotate.call(this, d, i); | ||
d.size = ~~fontSize.call(this, d, i); | ||
d.padding = padding.call(this, d, i); | ||
return d; | ||
}).sort(function(a, b) { return b.size - a.size; }); | ||
return cloud; | ||
if (timer) clearInterval(timer); | ||
timer = setInterval(step, 0); | ||
step(); | ||
function step() { | ||
var start = Date.now(); | ||
while (Date.now() - start < timeInterval && ++i < n && timer) { | ||
var d = data[i]; | ||
d.x = (size[0] * (random() + .5)) >> 1; | ||
d.y = (size[1] * (random() + .5)) >> 1; | ||
cloudSprite(contextAndRatio, d, data, i); | ||
if (d.hasText && place(board, d, bounds)) { | ||
tags.push(d); | ||
event.call("word", cloud, d); | ||
if (bounds) cloudBounds(bounds, d); | ||
else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: d.y + d.y1}]; | ||
// Temporary hack | ||
d.x -= size[0] >> 1; | ||
d.y -= size[1] >> 1; | ||
} | ||
} | ||
if (i >= n) { | ||
cloud.stop(); | ||
event.call("end", cloud, tags, bounds); | ||
} | ||
} | ||
}; | ||
return cloud; | ||
cloud.stop = function() { | ||
if (timer) { | ||
clearInterval(timer); | ||
timer = null; | ||
} | ||
for (const d of words) { | ||
delete d.sprite; | ||
} | ||
return cloud; | ||
}; | ||
function step() { | ||
var start = Date.now(); | ||
while (Date.now() - start < timeInterval && ++i < n && timer) { | ||
var d = data[i]; | ||
d.x = (size[0] * (random() + .5)) >> 1; | ||
d.y = (size[1] * (random() + .5)) >> 1; | ||
cloudSprite(contextAndRatio, d, data, i); | ||
if (d.hasText && place(board, d, bounds)) { | ||
tags.push(d); | ||
event.call("word", cloud, d); | ||
if (bounds) cloudBounds(bounds, d); | ||
else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: d.y + d.y1}]; | ||
// Temporary hack | ||
d.x -= size[0] >> 1; | ||
d.y -= size[1] >> 1; | ||
} | ||
} | ||
if (i >= n) { | ||
cloud.stop(); | ||
event.call("end", cloud, tags, bounds); | ||
} | ||
} | ||
}; | ||
function getContext(canvas) { | ||
const context = canvas.getContext("2d", {willReadFrequently: true}); | ||
cloud.stop = function() { | ||
if (timer) { | ||
clearInterval(timer); | ||
timer = null; | ||
} | ||
for (const d of words) { | ||
delete d.sprite; | ||
} | ||
return cloud; | ||
}; | ||
canvas.width = canvas.height = 1; | ||
const ratio = Math.sqrt(context.getImageData(0, 0, 1, 1).data.length >> 2); | ||
canvas.width = (cw << 5) / ratio; | ||
canvas.height = ch / ratio; | ||
function getContext(canvas) { | ||
const context = canvas.getContext("2d", {willReadFrequently: true}); | ||
context.fillStyle = context.strokeStyle = "red"; | ||
canvas.width = canvas.height = 1; | ||
const ratio = Math.sqrt(context.getImageData(0, 0, 1, 1).data.length >> 2); | ||
canvas.width = (cw << 5) / ratio; | ||
canvas.height = ch / ratio; | ||
return {context, ratio}; | ||
} | ||
context.fillStyle = context.strokeStyle = "red"; | ||
function place(board, tag, bounds) { | ||
[{x: 0, y: 0}, {x: size[0], y: size[1]}]; | ||
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; | ||
return {context, ratio}; | ||
} | ||
while (dxdy = s(t += dt)) { | ||
dx = ~~dxdy[0]; | ||
dy = ~~dxdy[1]; | ||
function place(board, tag, bounds) { | ||
[{x: 0, y: 0}, {x: size[0], y: size[1]}]; | ||
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; | ||
if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break; | ||
while (dxdy = s(t += dt)) { | ||
dx = ~~dxdy[0]; | ||
dy = ~~dxdy[1]; | ||
tag.x = startX + dx; | ||
tag.y = startY + dy; | ||
if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break; | ||
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 || collideRects(tag, bounds)) { | ||
if (!cloudCollide(tag, board, size[0])) { | ||
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; | ||
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; | ||
} | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
tag.x = startX + dx; | ||
tag.y = startY + dy; | ||
cloud.timeInterval = function(_) { | ||
return arguments.length ? (timeInterval = _ == null ? Infinity : _, cloud) : timeInterval; | ||
}; | ||
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 || collideRects(tag, bounds)) { | ||
if (!cloudCollide(tag, board, size[0])) { | ||
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; | ||
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; | ||
} | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
cloud.words = function(_) { | ||
return arguments.length ? (words = _, cloud) : words; | ||
}; | ||
cloud.timeInterval = function(_) { | ||
return arguments.length ? (timeInterval = _ == null ? Infinity : _, cloud) : timeInterval; | ||
}; | ||
cloud.size = function(_) { | ||
return arguments.length ? (size = [+_[0], +_[1]], cloud) : size; | ||
}; | ||
cloud.words = function(_) { | ||
return arguments.length ? (words = _, cloud) : words; | ||
}; | ||
cloud.font = function(_) { | ||
return arguments.length ? (font = functor(_), cloud) : font; | ||
}; | ||
cloud.size = function(_) { | ||
return arguments.length ? (size = [+_[0], +_[1]], cloud) : size; | ||
}; | ||
cloud.fontStyle = function(_) { | ||
return arguments.length ? (fontStyle = functor(_), cloud) : fontStyle; | ||
}; | ||
cloud.font = function(_) { | ||
return arguments.length ? (font = functor(_), cloud) : font; | ||
}; | ||
cloud.fontWeight = function(_) { | ||
return arguments.length ? (fontWeight = functor(_), cloud) : fontWeight; | ||
}; | ||
cloud.fontStyle = function(_) { | ||
return arguments.length ? (fontStyle = functor(_), cloud) : fontStyle; | ||
}; | ||
cloud.rotate = function(_) { | ||
return arguments.length ? (rotate = functor(_), cloud) : rotate; | ||
}; | ||
cloud.fontWeight = function(_) { | ||
return arguments.length ? (fontWeight = functor(_), cloud) : fontWeight; | ||
}; | ||
cloud.text = function(_) { | ||
return arguments.length ? (text = functor(_), cloud) : text; | ||
}; | ||
cloud.rotate = function(_) { | ||
return arguments.length ? (rotate = functor(_), cloud) : rotate; | ||
}; | ||
cloud.spiral = function(_) { | ||
return arguments.length ? (spiral = SPIRALS[_] || _, cloud) : spiral; | ||
}; | ||
cloud.text = function(_) { | ||
return arguments.length ? (text = functor(_), cloud) : text; | ||
}; | ||
cloud.fontSize = function(_) { | ||
return arguments.length ? (fontSize = functor(_), cloud) : fontSize; | ||
}; | ||
cloud.spiral = function(_) { | ||
return arguments.length ? (spiral = SPIRALS[_] || _, cloud) : spiral; | ||
}; | ||
cloud.padding = function(_) { | ||
return arguments.length ? (padding = functor(_), cloud) : padding; | ||
}; | ||
cloud.fontSize = function(_) { | ||
return arguments.length ? (fontSize = functor(_), cloud) : fontSize; | ||
}; | ||
cloud.random = function(_) { | ||
return arguments.length ? (random = _, cloud) : random; | ||
}; | ||
cloud.padding = function(_) { | ||
return arguments.length ? (padding = functor(_), cloud) : padding; | ||
}; | ||
cloud.on = function() { | ||
var value = event.on.apply(event, arguments); | ||
return value === event ? cloud : value; | ||
}; | ||
cloud.random = function(_) { | ||
return arguments.length ? (random = _, cloud) : random; | ||
}; | ||
return cloud; | ||
}; | ||
cloud.on = function() { | ||
var value = event.on.apply(event, arguments); | ||
return value === event ? cloud : value; | ||
}; | ||
function cloudText(d) { | ||
return d.text; | ||
} | ||
return cloud; | ||
}; | ||
function cloudFont() { | ||
return "serif"; | ||
} | ||
function cloudText(d) { | ||
return d.text; | ||
} | ||
function cloudFontNormal() { | ||
return "normal"; | ||
} | ||
function cloudFont() { | ||
return "serif"; | ||
} | ||
function cloudFontSize(d) { | ||
return Math.sqrt(d.value); | ||
} | ||
function cloudFontNormal() { | ||
return "normal"; | ||
} | ||
function cloudRotate() { | ||
return (~~(random() * 6) - 3) * 30; | ||
} | ||
function cloudFontSize(d) { | ||
return Math.sqrt(d.value); | ||
} | ||
function cloudPadding() { | ||
return 1; | ||
} | ||
function cloudRotate() { | ||
return (~~(random() * 6) - 3) * 30; | ||
} | ||
// 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; | ||
function cloudPadding() { | ||
return 1; | ||
} | ||
c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio); | ||
var x = 0, | ||
y = 0, | ||
maxh = 0, | ||
n = data.length; | ||
--di; | ||
while (++di < n) { | ||
d = data[di]; | ||
c.save(); | ||
c.font = d.style + " " + d.weight + " " + ~~((d.size + 1) / ratio) + "px " + d.font; | ||
const metrics = c.measureText(d.text); | ||
const anchor = -Math.floor(metrics.width / 2); | ||
let w = (metrics.width + 1) * ratio; | ||
let h = d.size << 1; | ||
if (d.rotate) { | ||
var sr = Math.sin(d.rotate * RADIANS), | ||
cr = Math.cos(d.rotate * RADIANS), | ||
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; | ||
h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr)); | ||
} else { | ||
w = (w + 0x1f) >> 5 << 5; | ||
} | ||
if (h > maxh) maxh = h; | ||
if (x + w >= (cw << 5)) { | ||
x = 0; | ||
y += maxh; | ||
maxh = 0; | ||
} | ||
if (y + h >= ch) break; | ||
c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio); | ||
if (d.rotate) c.rotate(d.rotate * RADIANS); | ||
c.fillText(d.text, anchor, 0); | ||
if (d.padding) c.lineWidth = 2 * d.padding, c.strokeText(d.text, anchor, 0); | ||
c.restore(); | ||
d.width = w; | ||
d.height = h; | ||
d.xoff = x; | ||
d.yoff = y; | ||
d.x1 = w >> 1; | ||
d.y1 = h >> 1; | ||
d.x0 = -d.x1; | ||
d.y0 = -d.y1; | ||
d.hasText = true; | ||
x += w; | ||
} | ||
var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data, | ||
sprite = []; | ||
while (--di >= 0) { | ||
d = data[di]; | ||
if (!d.hasText) continue; | ||
var w = d.width, | ||
w32 = w >> 5, | ||
h = d.y1 - d.y0; | ||
// Zero the buffer | ||
for (var i = 0; i < h * w32; i++) sprite[i] = 0; | ||
x = d.xoff; | ||
if (x == null) return; | ||
y = d.yoff; | ||
var seen = 0, | ||
seenRow = -1; | ||
for (var j = 0; j < h; j++) { | ||
for (var 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; | ||
sprite[k] |= m; | ||
seen |= m; | ||
} | ||
if (seen) seenRow = j; | ||
else { | ||
d.y0++; | ||
h--; | ||
j--; | ||
y++; | ||
} | ||
} | ||
d.y1 = d.y0 + seenRow; | ||
d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32); | ||
} | ||
} | ||
// 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; | ||
// 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; | ||
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; | ||
} | ||
c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio); | ||
var x = 0, | ||
y = 0, | ||
maxh = 0, | ||
n = data.length; | ||
--di; | ||
while (++di < n) { | ||
d = data[di]; | ||
c.save(); | ||
c.font = d.style + " " + d.weight + " " + ~~((d.size + 1) / ratio) + "px " + d.font; | ||
const metrics = c.measureText(d.text); | ||
const anchor = -Math.floor(metrics.width / 2); | ||
let w = (metrics.width + 1) * ratio; | ||
let h = d.size << 1; | ||
if (d.rotate) { | ||
var sr = Math.sin(d.rotate * RADIANS), | ||
cr = Math.cos(d.rotate * RADIANS), | ||
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; | ||
h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr)); | ||
} else { | ||
w = (w + 0x1f) >> 5 << 5; | ||
} | ||
if (h > maxh) maxh = h; | ||
if (x + w >= (cw << 5)) { | ||
x = 0; | ||
y += maxh; | ||
maxh = 0; | ||
} | ||
if (y + h >= ch) break; | ||
c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio); | ||
if (d.rotate) c.rotate(d.rotate * RADIANS); | ||
c.fillText(d.text, anchor, 0); | ||
if (d.padding) c.lineWidth = 2 * d.padding, c.strokeText(d.text, anchor, 0); | ||
c.restore(); | ||
d.width = w; | ||
d.height = h; | ||
d.xoff = x; | ||
d.yoff = y; | ||
d.x1 = w >> 1; | ||
d.y1 = h >> 1; | ||
d.x0 = -d.x1; | ||
d.y0 = -d.y1; | ||
d.hasText = true; | ||
x += w; | ||
} | ||
var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data, | ||
sprite = []; | ||
while (--di >= 0) { | ||
d = data[di]; | ||
if (!d.hasText) continue; | ||
var w = d.width, | ||
w32 = w >> 5, | ||
h = d.y1 - d.y0; | ||
// Zero the buffer | ||
for (var i = 0; i < h * w32; i++) sprite[i] = 0; | ||
x = d.xoff; | ||
if (x == null) return; | ||
y = d.yoff; | ||
var seen = 0, | ||
seenRow = -1; | ||
for (var j = 0; j < h; j++) { | ||
for (var 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; | ||
sprite[k] |= m; | ||
seen |= m; | ||
} | ||
if (seen) seenRow = j; | ||
else { | ||
d.y0++; | ||
h--; | ||
j--; | ||
y++; | ||
} | ||
} | ||
d.y1 = d.y0 + seenRow; | ||
d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32); | ||
} | ||
} | ||
function cloudBounds(bounds, d) { | ||
var b0 = bounds[0], | ||
b1 = bounds[1]; | ||
if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; | ||
if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; | ||
if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1; | ||
if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1; | ||
} | ||
// 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; | ||
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 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 cloudBounds(bounds, d) { | ||
var b0 = bounds[0], | ||
b1 = bounds[1]; | ||
if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; | ||
if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; | ||
if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1; | ||
if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1; | ||
} | ||
function archimedeanSpiral(size) { | ||
var e = size[0] / size[1]; | ||
return function(t) { | ||
return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)]; | ||
}; | ||
} | ||
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 rectangularSpiral(size) { | ||
var dy = 4, | ||
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. | ||
switch ((Math.sqrt(1 + 4 * sign * t) - sign) & 3) { | ||
case 0: x += dx; break; | ||
case 1: y += dy; break; | ||
case 2: x -= dx; break; | ||
default: y -= dy; break; | ||
} | ||
return [x, y]; | ||
}; | ||
} | ||
function archimedeanSpiral(size) { | ||
var e = size[0] / size[1]; | ||
return function(t) { | ||
return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)]; | ||
}; | ||
} | ||
// TODO reuse arrays? | ||
function zeroArray(n) { | ||
var a = [], | ||
i = -1; | ||
while (++i < n) a[i] = 0; | ||
return a; | ||
} | ||
function rectangularSpiral(size) { | ||
var dy = 4, | ||
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. | ||
switch ((Math.sqrt(1 + 4 * sign * t) - sign) & 3) { | ||
case 0: x += dx; break; | ||
case 1: y += dy; break; | ||
case 2: x -= dx; break; | ||
default: y -= dy; break; | ||
} | ||
return [x, y]; | ||
}; | ||
} | ||
function cloudCanvas() { | ||
return document.createElement("canvas"); | ||
} | ||
// TODO reuse arrays? | ||
function zeroArray(n) { | ||
var a = [], | ||
i = -1; | ||
while (++i < n) a[i] = 0; | ||
return a; | ||
} | ||
function functor(d) { | ||
return typeof d === "function" ? d : function() { return d; }; | ||
function cloudCanvas() { | ||
return document.createElement("canvas"); | ||
} | ||
function functor(d) { | ||
return typeof d === "function" ? d : function() { return d; }; | ||
} | ||
return d3Cloud; | ||
} | ||
var layout = /*@__PURE__*/getDefaultExportFromCjs(d3Cloud); | ||
var d3CloudExports = requireD3Cloud(); | ||
var layout = /*@__PURE__*/getDefaultExportFromCjs(d3CloudExports); | ||
@@ -722,3 +731,3 @@ class WordElement extends chart_js.Element { | ||
} | ||
console.warn('cannot fit all text elements in three tries'); | ||
console.warn(`cannot fit all text elements in ${growOptions.maxTries} tries`); | ||
} | ||
@@ -725,0 +734,0 @@ const wb = bounds[1].x - bounds[0].x; |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ChartWordCloud={},t.Chart,t.Chart.helpers)}(this,(function(t,e,n){"use strict";function r(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function o(t){if(t.__esModule)return t;var e=t.default;if("function"==typeof e){var n=function t(){return this instanceof t?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};n.prototype=e.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(t).forEach((function(e){var r=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(n,e,r.get?r:{enumerable:!0,get:function(){return t[e]}})})),n}var a={value:function(){}};function i(){for(var t,e=0,n=arguments.length,r={};e<n;++e){if(!(t=arguments[e]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new s(r)}function s(t){this._=t}function l(t,e){for(var n,r=0,o=t.length;r<o;++r)if((n=t[r]).name===e)return n.value}function u(t,e,n){for(var r=0,o=t.length;r<o;++r)if(t[r].name===e){t[r]=a,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=n&&t.push({name:e,value:n}),t}s.prototype=i.prototype={constructor:s,on:function(t,e){var n,r,o=this._,a=(r=o,(t+"").trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");if(n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}}))),i=-1,s=a.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++i<s;)if(n=(t=a[i]).type)o[n]=u(o[n],t.name,e);else if(null==e)for(n in o)o[n]=u(o[n],t.name,null);return this}for(;++i<s;)if((n=(t=a[i]).type)&&(n=l(o[n],t.name)))return n},copy:function(){var t={},e=this._;for(var n in e)t[n]=e[n].slice();return new s(t)},call:function(t,e){if((n=arguments.length-2)>0)for(var n,r,o=new Array(n),a=0;a<n;++a)o[a]=arguments[a+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(a=0,n=(r=this._[t]).length;a<n;++a)r[a].value.apply(e,o)},apply:function(t,e,n){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],o=0,a=r.length;o<a;++o)r[o].value.apply(e,n)}};const c=o(Object.freeze({__proto__:null,dispatch:i})).dispatch,h=Math.PI/180,f={archimedean:E,rectangular:function(t){var e=4*t[0]/t[1],n=0,r=0;return function(t){var o=t<0?-1:1;switch(Math.sqrt(1+4*o*t)-o&3){case 0:n+=e;break;case 1:r+=4;break;case 2:n-=e;break;default:r-=4}return[n,r]}}},d=2048;var y=function(){var t=[256,256],e=p,n=x,r=m,o=g,a=g,i=v,s=w,l=E,u=[],h=1/0,y=c("word","end"),R=null,C=Math.random,P={},z=_;function O(e,n,r){t[0],t[1];for(var o,a,i,s,u,c=n.x,h=n.y,f=Math.sqrt(t[0]*t[0]+t[1]*t[1]),d=l(t),y=C()<.5?1:-1,p=-y;(o=d(p+=y))&&(a=~~o[0],i=~~o[1],!(Math.min(Math.abs(a),Math.abs(i))>=f));)if(n.x=c+a,n.y=h+i,!(n.x+n.x0<0||n.y+n.y0<0||n.x+n.x1>t[0]||n.y+n.y1>t[1]||r&&(u=r,!((s=n).x+s.x1>u[0].x&&s.x+s.x0<u[1].x&&s.y+s.y1>u[0].y&&s.y+s.y0<u[1].y))||M(n,e,t[0]))){for(var x,g=n.sprite,m=n.width>>5,v=t[0]>>5,w=n.x-(m<<4),b=127&w,S=32-b,E=n.y1-n.y0,_=(n.y+n.y0)*v+(w>>5),k=0;k<E;k++){x=0;for(var R=0;R<=m;R++)e[_+R]|=x<<S|(R<m?(x=g[k*m+R])>>>b:0);_+=v}return!0}return!1}return P.canvas=function(t){return arguments.length?(z=k(t),P):z},P.start=function(){var l=function(t){const e=t.getContext("2d",{willReadFrequently:!0});t.width=t.height=1;const n=Math.sqrt(e.getImageData(0,0,1,1).data.length>>2);return t.width=2048/n,t.height=d/n,e.fillStyle=e.strokeStyle="red",{context:e,ratio:n}}(z()),c=function(t){var e=[],n=-1;for(;++n<t;)e[n]=0;return e}((t[0]>>5)*t[1]),f=null,p=u.length,x=-1,g=[],m=u.map((function(t,l){return t.text=e.call(this,t,l),t.font=n.call(this,t,l),t.style=o.call(this,t,l),t.weight=a.call(this,t,l),t.rotate=i.call(this,t,l),t.size=~~r.call(this,t,l),t.padding=s.call(this,t,l),t})).sort((function(t,e){return e.size-t.size}));return R&&clearInterval(R),R=setInterval(v,0),v(),P;function v(){for(var e=Date.now();Date.now()-e<h&&++x<p&&R;){var n=m[x];n.x=t[0]*(C()+.5)>>1,n.y=t[1]*(C()+.5)>>1,b(l,n,m,x),n.hasText&&O(c,n,f)&&(g.push(n),y.call("word",P,n),f?S(f,n):f=[{x:n.x+n.x0,y:n.y+n.y0},{x:n.x+n.x1,y:n.y+n.y1}],n.x-=t[0]>>1,n.y-=t[1]>>1)}x>=p&&(P.stop(),y.call("end",P,g,f))}},P.stop=function(){R&&(clearInterval(R),R=null);for(const t of u)delete t.sprite;return P},P.timeInterval=function(t){return arguments.length?(h=null==t?1/0:t,P):h},P.words=function(t){return arguments.length?(u=t,P):u},P.size=function(e){return arguments.length?(t=[+e[0],+e[1]],P):t},P.font=function(t){return arguments.length?(n=k(t),P):n},P.fontStyle=function(t){return arguments.length?(o=k(t),P):o},P.fontWeight=function(t){return arguments.length?(a=k(t),P):a},P.rotate=function(t){return arguments.length?(i=k(t),P):i},P.text=function(t){return arguments.length?(e=k(t),P):e},P.spiral=function(t){return arguments.length?(l=f[t]||t,P):l},P.fontSize=function(t){return arguments.length?(r=k(t),P):r},P.padding=function(t){return arguments.length?(s=k(t),P):s},P.random=function(t){return arguments.length?(C=t,P):C},P.on=function(){var t=y.on.apply(y,arguments);return t===y?P:t},P};function p(t){return t.text}function x(){return"serif"}function g(){return"normal"}function m(t){return Math.sqrt(t.value)}function v(){return 30*(~~(6*random())-3)}function w(){return 1}function b(t,e,n,r){if(!e.sprite){var o=t.context,a=t.ratio;o.clearRect(0,0,2048/a,d/a);var i=0,s=0,l=0,u=n.length;for(--r;++r<u;){e=n[r],o.save(),o.font=e.style+" "+e.weight+" "+~~((e.size+1)/a)+"px "+e.font;const t=o.measureText(e.text),u=-Math.floor(t.width/2);let m=(t.width+1)*a,v=e.size<<1;if(e.rotate){var c=Math.sin(e.rotate*h),f=Math.cos(e.rotate*h),y=m*f,p=m*c,x=v*f,g=v*c;m=Math.max(Math.abs(y+g),Math.abs(y-g))+31>>5<<5,v=~~Math.max(Math.abs(p+x),Math.abs(p-x))}else m=m+31>>5<<5;if(v>l&&(l=v),i+m>=2048&&(i=0,s+=l,l=0),s+v>=d)break;o.translate((i+(m>>1))/a,(s+(v>>1))/a),e.rotate&&o.rotate(e.rotate*h),o.fillText(e.text,u,0),e.padding&&(o.lineWidth=2*e.padding,o.strokeText(e.text,u,0)),o.restore(),e.width=m,e.height=v,e.xoff=i,e.yoff=s,e.x1=m>>1,e.y1=v>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,i+=m}for(var m=o.getImageData(0,0,2048/a,d/a).data,v=[];--r>=0;)if((e=n[r]).hasText){for(var w=e.width,b=w>>5,M=e.y1-e.y0,S=0;S<M*b;S++)v[S]=0;if(null==(i=e.xoff))return;s=e.yoff;for(var E=0,_=-1,k=0;k<M;k++){for(S=0;S<w;S++){var R=b*k+(S>>5),C=m[2048*(s+k)+(i+S)<<2]?1<<31-S%32:0;v[R]|=C,E|=C}E?_=k:(e.y0++,M--,k--,s++)}e.y1=e.y0+_,e.sprite=v.slice(0,(e.y1-e.y0)*b)}}}function M(t,e,n){n>>=5;for(var r,o=t.sprite,a=t.width>>5,i=t.x-(a<<4),s=127&i,l=32-s,u=t.y1-t.y0,c=(t.y+t.y0)*n+(i>>5),h=0;h<u;h++){r=0;for(var f=0;f<=a;f++)if((r<<l|(f<a?(r=o[h*a+f])>>>s:0))&e[c+f])return!0;c+=n}return!1}function S(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 E(t){var e=t[0]/t[1];return function(t){return[e*(t*=.1)*Math.cos(t),t*Math.sin(t)]}}function _(){return document.createElement("canvas")}function k(t){return"function"==typeof t?t:function(){return t}}var R=r(y);class C extends e.Element{static computeRotation(t,e){if(t.rotationSteps<=1)return 0;if(t.minRotation===t.maxRotation)return t.minRotation;const n=Math.min(t.rotationSteps,Math.floor(e()*t.rotationSteps))/(t.rotationSteps-1),r=t.maxRotation-t.minRotation;return t.minRotation+n*r}inRange(t,e){const n=this.getProps(["x","y","width","height","scale"]);if(n.scale<=0)return!1;const r=Number.isNaN(t)?n.x:t,o=Number.isNaN(e)?n.y:e;return r>=n.x-n.width/2&&r<=n.x+n.width/2&&o>=n.y-n.height/2&&o<=n.y+n.height/2}inXRange(t){return this.inRange(t,Number.NaN)}inYRange(t){return this.inRange(Number.NaN,t)}getCenterPoint(){return this.getProps(["x","y"])}tooltipPosition(){return this.getCenterPoint()}draw(t){const{options:e}=this,r=this.getProps(["x","y","width","height","text","scale"]);if(r.scale<=0)return;t.save();const o=n.toFont({...e,size:e.size*r.scale});t.font=o.string,t.fillStyle=e.color,t.textAlign="center",t.translate(r.x,r.y),t.rotate(e.rotate/180*Math.PI),e.strokeStyle&&(null!=e.strokeWidth&&(t.lineWidth=e.strokeWidth),t.strokeStyle=e.strokeStyle,t.strokeText(r.text,0,0)),t.fillText(r.text,0,0),t.restore()}}C.id="word",C.defaults={minRotation:-90,maxRotation:0,rotationSteps:2,padding:1,strokeStyle:void 0,strokeWidth:void 0,size:t=>t.parsed.y,hoverColor:"#ababab"},C.defaultRoutes={color:"color",family:"font.family",style:"font.style",weight:"font.weight",lineHeight:"font.lineHeight"};class P extends e.DatasetController{constructor(){super(...arguments),this.wordLayout=R().text((t=>t.text)).padding((t=>t.options.padding)).rotate((t=>t.options.rotate)).font((t=>t.options.family)).fontSize((t=>t.options.size)).fontStyle((t=>t.options.style)).fontWeight((t=>{var e;return null!==(e=t.options.weight)&&void 0!==e?e:1})),this.rand=Math.random}update(t){var e;super.update(t);const n=this.options;this.rand=function(t=Date.now()){let e="number"==typeof t?t:Array.from(t).reduce(((t,e)=>t+e.charCodeAt(0)),0);return()=>(e=(9301*e+49297)%233280,e/233280)}(null!==(e=n.randomRotationSeed)&&void 0!==e?e:this.chart.id);const r=this._cachedMeta.data||[];this.updateElements(r,0,r.length,t)}updateElements(t,e,r,o){var a,i,s,l,u;this.wordLayout.stop();const c=this.options,h=this._cachedMeta.xScale,f=this._cachedMeta.yScale,d=h.right-h.left,y=f.bottom-f.top,p=this.chart.data.labels,x={maxTries:3,scalingFactor:1.2};Object.assign(x,null!==(a=null==c?void 0:c.autoGrow)&&void 0!==a?a:{});const g=[];for(let t=e;t<e+r;t+=1){const e=this.resolveDataElementOptions(t,o);null==e.rotate&&(e.rotate=C.computeRotation(e,this.rand));const r={options:{...n.toFont(e),...e},x:null!==(s=null===(i=this._cachedMeta.xScale)||void 0===i?void 0:i.getPixelForDecimal(.5))&&void 0!==s?s:0,y:null!==(u=null===(l=this._cachedMeta.yScale)||void 0===l?void 0:l.getPixelForDecimal(.5))&&void 0!==u?u:0,width:10,height:10,scale:1,index:t,text:p[t]};g.push(r)}if("reset"===o)return void g.forEach((e=>{this.updateElement(t[e.index],e.index,e,o)}));this.wordLayout.random(this.rand).words(g);const m=(e=1,n=x.maxTries)=>{this.wordLayout.size([d*e,y*e]).on("end",((r,a)=>{if(r.length<p.length){if(n>0){const t="function"==typeof x.scalingFactor?x.scalingFactor(e,r,p.length):e*x.scalingFactor;return void m(t,n-1)}console.warn("cannot fit all text elements in three tries")}const i=a[1].x-a[0].x,s=a[1].y-a[0].y,l=c.fit?Math.min(d/i,y/s):1,u=new Set(p.map(((t,e)=>e)));r.forEach((e=>{u.delete(e.index),this.updateElement(t[e.index],e.index,{options:e.options,scale:l,x:h.left+l*e.x+d/2,y:f.top+l*e.y+y/2,width:l*e.width,height:l*e.height,text:e.text},o)})),u.forEach((e=>this.updateElement(t[e],e,{scale:0},o)))})).start()};m()}draw(){const t=this._cachedMeta.data,{ctx:e}=this.chart;t.forEach((t=>t.draw(e)))}getLabelAndValue(t){const e=super.getLabelAndValue(t),n=this.chart.data.labels;return e.label=n[t],e}}P.id="wordCloud",P.defaults={datasets:{animation:{colors:{properties:["color","strokeStyle"]},numbers:{properties:["x","y","size","rotate"]}}},maintainAspectRatio:!1,dataElementType:C.id},P.overrides={scales:{x:{type:"linear",min:-1,max:1,display:!1},y:{type:"linear",min:-1,max:1,display:!1}}};class z extends e.Chart{constructor(t,n){super(t,function(t,n,r,o=[],a=[]){e.registry.addControllers(r),Array.isArray(o)?e.registry.addElements(...o):e.registry.addElements(o),Array.isArray(a)?e.registry.addScales(...a):e.registry.addScales(a);const i=n;return i.type=t,i}("wordCloud",n,P,C))}}z.id=P.id,e.registry.addControllers(P),e.registry.addElements(C),t.WordCloudChart=z,t.WordCloudController=P,t.WordElement=C})); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ChartWordCloud={},t.Chart,t.Chart.helpers)}(this,(function(t,e,n){"use strict";function r(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function o(t){if(t.__esModule)return t;var e=t.default;if("function"==typeof e){var n=function t(){return this instanceof t?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};n.prototype=e.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(t).forEach((function(e){var r=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(n,e,r.get?r:{enumerable:!0,get:function(){return t[e]}})})),n}var a={value:function(){}};function i(){for(var t,e=0,n=arguments.length,r={};e<n;++e){if(!(t=arguments[e]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new s(r)}function s(t){this._=t}function l(t,e){for(var n,r=0,o=t.length;r<o;++r)if((n=t[r]).name===e)return n.value}function u(t,e,n){for(var r=0,o=t.length;r<o;++r)if(t[r].name===e){t[r]=a,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=n&&t.push({name:e,value:n}),t}s.prototype=i.prototype={constructor:s,on:function(t,e){var n,r,o=this._,a=(r=o,(t+"").trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");if(n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}}))),i=-1,s=a.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++i<s;)if(n=(t=a[i]).type)o[n]=u(o[n],t.name,e);else if(null==e)for(n in o)o[n]=u(o[n],t.name,null);return this}for(;++i<s;)if((n=(t=a[i]).type)&&(n=l(o[n],t.name)))return n},copy:function(){var t={},e=this._;for(var n in e)t[n]=e[n].slice();return new s(t)},call:function(t,e){if((n=arguments.length-2)>0)for(var n,r,o=new Array(n),a=0;a<n;++a)o[a]=arguments[a+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(a=0,n=(r=this._[t]).length;a<n;++a)r[a].value.apply(e,o)},apply:function(t,e,n){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],o=0,a=r.length;o<a;++o)r[o].value.apply(e,n)}};var c,h,f=o(Object.freeze({__proto__:null,dispatch:i}));var d=function(){if(h)return c;h=1;const t=f.dispatch,e=Math.PI/180,n={archimedean:x,rectangular:function(t){var e=4*t[0]/t[1],n=0,r=0;return function(t){var o=t<0?-1:1;switch(Math.sqrt(1+4*o*t)-o&3){case 0:n+=e;break;case 1:r+=4;break;case 2:n-=e;break;default:r-=4}return[n,r]}}},r=2048;function o(t){return t.text}function a(){return"serif"}function i(){return"normal"}function s(t){return Math.sqrt(t.value)}function l(){return 30*(~~(6*random())-3)}function u(){return 1}function d(t,n,o,a){if(!n.sprite){var i=t.context,s=t.ratio;i.clearRect(0,0,2048/s,r/s);var l=0,u=0,c=0,h=o.length;for(--a;++a<h;){n=o[a],i.save(),i.font=n.style+" "+n.weight+" "+~~((n.size+1)/s)+"px "+n.font;const t=i.measureText(n.text),h=-Math.floor(t.width/2);let m=(t.width+1)*s,v=n.size<<1;if(n.rotate){var f=Math.sin(n.rotate*e),d=Math.cos(n.rotate*e),y=m*d,p=m*f,x=v*d,g=v*f;m=Math.max(Math.abs(y+g),Math.abs(y-g))+31>>5<<5,v=~~Math.max(Math.abs(p+x),Math.abs(p-x))}else m=m+31>>5<<5;if(v>c&&(c=v),l+m>=2048&&(l=0,u+=c,c=0),u+v>=r)break;i.translate((l+(m>>1))/s,(u+(v>>1))/s),n.rotate&&i.rotate(n.rotate*e),i.fillText(n.text,h,0),n.padding&&(i.lineWidth=2*n.padding,i.strokeText(n.text,h,0)),i.restore(),n.width=m,n.height=v,n.xoff=l,n.yoff=u,n.x1=m>>1,n.y1=v>>1,n.x0=-n.x1,n.y0=-n.y1,n.hasText=!0,l+=m}for(var m=i.getImageData(0,0,2048/s,r/s).data,v=[];--a>=0;)if((n=o[a]).hasText){for(var w=n.width,b=w>>5,M=n.y1-n.y0,S=0;S<M*b;S++)v[S]=0;if(null==(l=n.xoff))return;u=n.yoff;for(var E=0,_=-1,k=0;k<M;k++){for(S=0;S<w;S++){var R=b*k+(S>>5),C=m[2048*(u+k)+(l+S)<<2]?1<<31-S%32:0;v[R]|=C,E|=C}E?_=k:(n.y0++,M--,k--,u++)}n.y1=n.y0+_,n.sprite=v.slice(0,(n.y1-n.y0)*b)}}}function y(t,e,n){n>>=5;for(var r,o=t.sprite,a=t.width>>5,i=t.x-(a<<4),s=127&i,l=32-s,u=t.y1-t.y0,c=(t.y+t.y0)*n+(i>>5),h=0;h<u;h++){r=0;for(var f=0;f<=a;f++)if((r<<l|(f<a?(r=o[h*a+f])>>>s:0))&e[c+f])return!0;c+=n}return!1}function p(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 x(t){var e=t[0]/t[1];return function(t){return[e*(t*=.1)*Math.cos(t),t*Math.sin(t)]}}function g(){return document.createElement("canvas")}function m(t){return"function"==typeof t?t:function(){return t}}return c=function(){var e=[256,256],c=o,h=a,f=s,v=i,w=i,b=l,M=u,S=x,E=[],_=1/0,k=t("word","end"),R=null,C=Math.random,P={},z=g;function O(t,n,r){e[0],e[1];for(var o,a,i,s,l,u=n.x,c=n.y,h=Math.sqrt(e[0]*e[0]+e[1]*e[1]),f=S(e),d=C()<.5?1:-1,p=-d;(o=f(p+=d))&&(a=~~o[0],i=~~o[1],!(Math.min(Math.abs(a),Math.abs(i))>=h));)if(n.x=u+a,n.y=c+i,!(n.x+n.x0<0||n.y+n.y0<0||n.x+n.x1>e[0]||n.y+n.y1>e[1]||r&&(l=r,!((s=n).x+s.x1>l[0].x&&s.x+s.x0<l[1].x&&s.y+s.y1>l[0].y&&s.y+s.y0<l[1].y))||y(n,t,e[0]))){for(var x,g=n.sprite,m=n.width>>5,v=e[0]>>5,w=n.x-(m<<4),b=127&w,M=32-b,E=n.y1-n.y0,_=(n.y+n.y0)*v+(w>>5),k=0;k<E;k++){x=0;for(var R=0;R<=m;R++)t[_+R]|=x<<M|(R<m?(x=g[k*m+R])>>>b:0);_+=v}return!0}return!1}return P.canvas=function(t){return arguments.length?(z=m(t),P):z},P.start=function(){var t=function(t){const e=t.getContext("2d",{willReadFrequently:!0});t.width=t.height=1;const n=Math.sqrt(e.getImageData(0,0,1,1).data.length>>2);return t.width=2048/n,t.height=r/n,e.fillStyle=e.strokeStyle="red",{context:e,ratio:n}}(z()),n=function(t){var e=[],n=-1;for(;++n<t;)e[n]=0;return e}((e[0]>>5)*e[1]),o=null,a=E.length,i=-1,s=[],l=E.map((function(t,e){return t.text=c.call(this,t,e),t.font=h.call(this,t,e),t.style=v.call(this,t,e),t.weight=w.call(this,t,e),t.rotate=b.call(this,t,e),t.size=~~f.call(this,t,e),t.padding=M.call(this,t,e),t})).sort((function(t,e){return e.size-t.size}));return R&&clearInterval(R),R=setInterval(u,0),u(),P;function u(){for(var r=Date.now();Date.now()-r<_&&++i<a&&R;){var u=l[i];u.x=e[0]*(C()+.5)>>1,u.y=e[1]*(C()+.5)>>1,d(t,u,l,i),u.hasText&&O(n,u,o)&&(s.push(u),k.call("word",P,u),o?p(o,u):o=[{x:u.x+u.x0,y:u.y+u.y0},{x:u.x+u.x1,y:u.y+u.y1}],u.x-=e[0]>>1,u.y-=e[1]>>1)}i>=a&&(P.stop(),k.call("end",P,s,o))}},P.stop=function(){R&&(clearInterval(R),R=null);for(const t of E)delete t.sprite;return P},P.timeInterval=function(t){return arguments.length?(_=null==t?1/0:t,P):_},P.words=function(t){return arguments.length?(E=t,P):E},P.size=function(t){return arguments.length?(e=[+t[0],+t[1]],P):e},P.font=function(t){return arguments.length?(h=m(t),P):h},P.fontStyle=function(t){return arguments.length?(v=m(t),P):v},P.fontWeight=function(t){return arguments.length?(w=m(t),P):w},P.rotate=function(t){return arguments.length?(b=m(t),P):b},P.text=function(t){return arguments.length?(c=m(t),P):c},P.spiral=function(t){return arguments.length?(S=n[t]||t,P):S},P.fontSize=function(t){return arguments.length?(f=m(t),P):f},P.padding=function(t){return arguments.length?(M=m(t),P):M},P.random=function(t){return arguments.length?(C=t,P):C},P.on=function(){var t=k.on.apply(k,arguments);return t===k?P:t},P},c}(),y=r(d);class p extends e.Element{static computeRotation(t,e){if(t.rotationSteps<=1)return 0;if(t.minRotation===t.maxRotation)return t.minRotation;const n=Math.min(t.rotationSteps,Math.floor(e()*t.rotationSteps))/(t.rotationSteps-1),r=t.maxRotation-t.minRotation;return t.minRotation+n*r}inRange(t,e){const n=this.getProps(["x","y","width","height","scale"]);if(n.scale<=0)return!1;const r=Number.isNaN(t)?n.x:t,o=Number.isNaN(e)?n.y:e;return r>=n.x-n.width/2&&r<=n.x+n.width/2&&o>=n.y-n.height/2&&o<=n.y+n.height/2}inXRange(t){return this.inRange(t,Number.NaN)}inYRange(t){return this.inRange(Number.NaN,t)}getCenterPoint(){return this.getProps(["x","y"])}tooltipPosition(){return this.getCenterPoint()}draw(t){const{options:e}=this,r=this.getProps(["x","y","width","height","text","scale"]);if(r.scale<=0)return;t.save();const o=n.toFont({...e,size:e.size*r.scale});t.font=o.string,t.fillStyle=e.color,t.textAlign="center",t.translate(r.x,r.y),t.rotate(e.rotate/180*Math.PI),e.strokeStyle&&(null!=e.strokeWidth&&(t.lineWidth=e.strokeWidth),t.strokeStyle=e.strokeStyle,t.strokeText(r.text,0,0)),t.fillText(r.text,0,0),t.restore()}}p.id="word",p.defaults={minRotation:-90,maxRotation:0,rotationSteps:2,padding:1,strokeStyle:void 0,strokeWidth:void 0,size:t=>t.parsed.y,hoverColor:"#ababab"},p.defaultRoutes={color:"color",family:"font.family",style:"font.style",weight:"font.weight",lineHeight:"font.lineHeight"};class x extends e.DatasetController{constructor(){super(...arguments),this.wordLayout=y().text((t=>t.text)).padding((t=>t.options.padding)).rotate((t=>t.options.rotate)).font((t=>t.options.family)).fontSize((t=>t.options.size)).fontStyle((t=>t.options.style)).fontWeight((t=>{var e;return null!==(e=t.options.weight)&&void 0!==e?e:1})),this.rand=Math.random}update(t){var e;super.update(t);const n=this.options;this.rand=function(t=Date.now()){let e="number"==typeof t?t:Array.from(t).reduce(((t,e)=>t+e.charCodeAt(0)),0);return()=>(e=(9301*e+49297)%233280,e/233280)}(null!==(e=n.randomRotationSeed)&&void 0!==e?e:this.chart.id);const r=this._cachedMeta.data||[];this.updateElements(r,0,r.length,t)}updateElements(t,e,r,o){var a,i,s,l,u;this.wordLayout.stop();const c=this.options,h=this._cachedMeta.xScale,f=this._cachedMeta.yScale,d=h.right-h.left,y=f.bottom-f.top,x=this.chart.data.labels,g={maxTries:3,scalingFactor:1.2};Object.assign(g,null!==(a=null==c?void 0:c.autoGrow)&&void 0!==a?a:{});const m=[];for(let t=e;t<e+r;t+=1){const e=this.resolveDataElementOptions(t,o);null==e.rotate&&(e.rotate=p.computeRotation(e,this.rand));const r={options:{...n.toFont(e),...e},x:null!==(s=null===(i=this._cachedMeta.xScale)||void 0===i?void 0:i.getPixelForDecimal(.5))&&void 0!==s?s:0,y:null!==(u=null===(l=this._cachedMeta.yScale)||void 0===l?void 0:l.getPixelForDecimal(.5))&&void 0!==u?u:0,width:10,height:10,scale:1,index:t,text:x[t]};m.push(r)}if("reset"===o)return void m.forEach((e=>{this.updateElement(t[e.index],e.index,e,o)}));this.wordLayout.random(this.rand).words(m);const v=(e=1,n=g.maxTries)=>{this.wordLayout.size([d*e,y*e]).on("end",((r,a)=>{if(r.length<x.length){if(n>0){const t="function"==typeof g.scalingFactor?g.scalingFactor(e,r,x.length):e*g.scalingFactor;return void v(t,n-1)}console.warn(`cannot fit all text elements in ${g.maxTries} tries`)}const i=a[1].x-a[0].x,s=a[1].y-a[0].y,l=c.fit?Math.min(d/i,y/s):1,u=new Set(x.map(((t,e)=>e)));r.forEach((e=>{u.delete(e.index),this.updateElement(t[e.index],e.index,{options:e.options,scale:l,x:h.left+l*e.x+d/2,y:f.top+l*e.y+y/2,width:l*e.width,height:l*e.height,text:e.text},o)})),u.forEach((e=>this.updateElement(t[e],e,{scale:0},o)))})).start()};v()}draw(){const t=this._cachedMeta.data,{ctx:e}=this.chart;t.forEach((t=>t.draw(e)))}getLabelAndValue(t){const e=super.getLabelAndValue(t),n=this.chart.data.labels;return e.label=n[t],e}}x.id="wordCloud",x.defaults={datasets:{animation:{colors:{properties:["color","strokeStyle"]},numbers:{properties:["x","y","size","rotate"]}}},maintainAspectRatio:!1,dataElementType:p.id},x.overrides={scales:{x:{type:"linear",min:-1,max:1,display:!1},y:{type:"linear",min:-1,max:1,display:!1}}};class g extends e.Chart{constructor(t,n){super(t,function(t,n,r,o=[],a=[]){e.registry.addControllers(r),Array.isArray(o)?e.registry.addElements(...o):e.registry.addElements(o),Array.isArray(a)?e.registry.addScales(...a):e.registry.addScales(a);const i=n;return i.type=t,i}("wordCloud",n,x,p))}}g.id=x.id,e.registry.addControllers(x),e.registry.addElements(p),t.WordCloudChart=g,t.WordCloudController=x,t.WordElement=p})); | ||
//# sourceMappingURL=index.umd.min.js.map |
{ | ||
"name": "chartjs-chart-wordcloud", | ||
"description": "Chart.js module for word clouds", | ||
"version": "4.4.1", | ||
"version": "4.4.2", | ||
"author": { | ||
@@ -57,47 +57,35 @@ "name": "Samuel Gratzl", | ||
"@chiogen/rollup-plugin-terser": "^7.1.3", | ||
"@rollup/plugin-commonjs": "^26.0.1", | ||
"@rollup/plugin-node-resolve": "^15.2.3", | ||
"@rollup/plugin-replace": "^5.0.7", | ||
"@rollup/plugin-typescript": "^11.1.6", | ||
"@types/jest": "^29.5.12", | ||
"@eslint/js": "^9.11.1", | ||
"@rollup/plugin-commonjs": "^28.0.0", | ||
"@rollup/plugin-node-resolve": "^15.3.0", | ||
"@rollup/plugin-replace": "^6.0.1", | ||
"@rollup/plugin-typescript": "^12.1.0", | ||
"@types/jest-image-snapshot": "^6.4.0", | ||
"@types/node": "^20.14.2", | ||
"@typescript-eslint/eslint-plugin": "^7.12.0", | ||
"@typescript-eslint/parser": "^7.12.0", | ||
"@yarnpkg/sdks": "^3.1.2", | ||
"@types/node": "^22.7.4", | ||
"@yarnpkg/sdks": "^3.2.0", | ||
"canvas": "^2.11.2", | ||
"canvas-5-polyfill": "^0.1.5", | ||
"chart.js": "^4.4.3", | ||
"eslint": "^8.57.0", | ||
"eslint-config-airbnb-typescript": "^18.0.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-config-react-app": "^7.0.1", | ||
"eslint-plugin-flowtype": "^8.0.3", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-jsx-a11y": "^6.8.0", | ||
"eslint-plugin-prettier": "^5.1.3", | ||
"eslint-plugin-react": "^7.34.2", | ||
"eslint-plugin-react-hooks": "^4.6.2", | ||
"jest": "^29.7.0", | ||
"jest-environment-jsdom": "^29.7.0", | ||
"chart.js": "^4.4.4", | ||
"eslint": "^9.11.1", | ||
"eslint-plugin-prettier": "^5.2.1", | ||
"jest-image-snapshot": "^6.4.0", | ||
"prettier": "^3.3.1", | ||
"rimraf": "^5.0.7", | ||
"rollup": "^4.18.0", | ||
"jsdom": "^25.0.1", | ||
"prettier": "^3.3.3", | ||
"rimraf": "^6.0.1", | ||
"rollup": "^4.22.5", | ||
"rollup-plugin-cleanup": "^3.2.1", | ||
"rollup-plugin-dts": "^6.1.1", | ||
"ts-jest": "^29.1.4", | ||
"tslib": "^2.6.3", | ||
"typedoc": "^0.25.13", | ||
"typedoc-plugin-markdown": "^4.0.3", | ||
"typedoc-vitepress-theme": "^1.0.0", | ||
"typescript": "^5.4.5", | ||
"vitepress": "^1.2.3", | ||
"vue": "^3.4.27", | ||
"ts-jest": "^29.2.5", | ||
"tslib": "^2.7.0", | ||
"typedoc": "^0.26.7", | ||
"typedoc-plugin-markdown": "^4.2.8", | ||
"typedoc-vitepress-theme": "^1.0.1", | ||
"typescript": "^5.6.2", | ||
"typescript-eslint": "^8.7.0", | ||
"vite": "^5.4.8", | ||
"vitepress": "^1.3.4", | ||
"vitest": "^2.1.1", | ||
"vue": "^3.5.10", | ||
"vue-chartjs": "^5.3.1" | ||
}, | ||
"resolutions": { | ||
"@typescript-eslint/eslint-plugin": "^7.2.0", | ||
"@typescript-eslint/parser": "^7.2.0" | ||
}, | ||
"scripts": { | ||
@@ -109,3 +97,3 @@ "clean": "rimraf --glob build node_modules \"*.tgz\" \"*.tsbuildinfo\"", | ||
"build": "rollup -c", | ||
"test": "yarn node --experimental-vm-modules $(yarn bin jest) --passWithNoTests --detectOpenHandles --forceExit", | ||
"test": "vitest --passWithNoTests", | ||
"test:watch": "yarn run test --watch", | ||
@@ -117,3 +105,3 @@ "test:coverage": "yarn run test --coverage", | ||
"prettier": "prettier \"*\" \"*/**\" --check", | ||
"eslint": "eslint src --ext .ts,.tsx --cache", | ||
"eslint": "eslint src --cache", | ||
"eslint:fix": "yarn run eslint --fix", | ||
@@ -130,3 +118,3 @@ "prepare": "yarn run build", | ||
}, | ||
"packageManager": "yarn@4.2.2" | ||
"packageManager": "yarn@4.5.0" | ||
} |
@@ -1,4 +0,4 @@ | ||
/// <reference types="jest" /> | ||
/// <reference types="node" /> | ||
import { expect } from 'vitest'; | ||
import { Chart, ChartConfiguration, defaults, ChartType, DefaultDataPoint } from 'chart.js'; | ||
@@ -15,3 +15,3 @@ import { toMatchImageSnapshot, MatchImageSnapshotOptions } from 'jest-image-snapshot'; | ||
file.onload = () => resolve(Buffer.from(file.result as ArrayBuffer)); | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
file.readAsArrayBuffer(b!); | ||
@@ -38,9 +38,9 @@ }); | ||
LABEL = string, | ||
>(config: ChartConfiguration<TYPE, DATA, LABEL>, width = 300, height = 300): ChartHelper<TYPE, DATA, LABEL> { | ||
>(config: ChartConfiguration<TYPE, DATA, LABEL>, width = 800, height = 600): ChartHelper<TYPE, DATA, LABEL> { | ||
const canvas = document.createElement('canvas'); | ||
canvas.width = width; | ||
canvas.height = height; | ||
Object.assign(defaults.font, { family: 'Courier New' }); | ||
defaults.color = 'transparent'; | ||
// eslint-disable-next-line no-param-reassign | ||
Object.assign(defaults.font, { family: "'Courier New', sans-serif" }); | ||
// defaults.color = 'transparent'; | ||
config.options = { | ||
@@ -61,3 +61,3 @@ responsive: false, | ||
} as any; | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const ctx = canvas.getContext('2d')!; | ||
@@ -64,0 +64,0 @@ |
@@ -1,2 +0,1 @@ | ||
/// <reference types="jest" /> | ||
import { LinearScale, registry } from 'chart.js'; | ||
@@ -6,3 +5,3 @@ import { WordCloudController } from './WordCloudController'; | ||
import createChart from '../__tests__/createChart'; | ||
import { describe, beforeAll, test } from 'vitest'; | ||
describe('default', () => { | ||
@@ -22,2 +21,3 @@ beforeAll(() => { | ||
data: words.map((_, i) => 10 + (i / words.length) * 90), | ||
randomRotationSeed: 'x', | ||
}, | ||
@@ -36,4 +36,7 @@ ], | ||
return chart.toMatchImageSnapshot(); | ||
return chart.toMatchImageSnapshot({ | ||
failureThreshold: 1.85, | ||
failureThresholdType: 'percent', | ||
}); | ||
}); | ||
}); |
@@ -164,4 +164,4 @@ import { | ||
} | ||
// eslint-disable-next-line no-console | ||
console.warn('cannot fit all text elements in three tries'); | ||
console.warn(`cannot fit all text elements in ${growOptions.maxTries} tries`); | ||
} | ||
@@ -168,0 +168,0 @@ const wb = bounds[1].x - bounds[0].x; |
@@ -181,2 +181,3 @@ import { Element, FontSpec, VisualElement, ScriptableAndArrayOptions, ScriptableContext, ChartType } from 'chart.js'; | ||
ctx.font = f.string; | ||
// console.log(ctx.font); | ||
ctx.fillStyle = options.color; | ||
@@ -183,0 +184,0 @@ ctx.textAlign = 'center'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
33
2481
237928