Comparing version 1.1.1 to 1.1.2
{ | ||
"name": "wordcloud", | ||
"version": "1.1.1", | ||
"version": "1.1.2", | ||
"description": "Tag cloud/Wordle presentation on 2D canvas or HTML", | ||
@@ -26,7 +26,10 @@ "homepage": "http://timdream.org/wordcloud2.js/", | ||
"scripts": { | ||
"test": "grunt test" | ||
"test": "grunt test", | ||
"lint": "eslint --ext .js,.ts src" | ||
}, | ||
"main": "src/wordcloud2.js", | ||
"devDependencies": { | ||
"grunt": "^1.0.4", | ||
"@arkweid/lefthook": "^0.7.1", | ||
"eslint": "^7.0.0", | ||
"grunt": "^1.1.0", | ||
"grunt-cli": "^1.3.2", | ||
@@ -33,0 +36,0 @@ "grunt-contrib-connect": "^2.1.0", |
@@ -9,7 +9,7 @@ /*! | ||
'use strict'; | ||
'use strict' | ||
// setImmediate | ||
if (!window.setImmediate) { | ||
window.setImmediate = (function setupSetImmediate() { | ||
window.setImmediate = (function setupSetImmediate () { | ||
return window.msSetImmediate || | ||
@@ -19,9 +19,9 @@ window.webkitSetImmediate || | ||
window.oSetImmediate || | ||
(function setupSetZeroTimeout() { | ||
(function setupSetZeroTimeout () { | ||
if (!window.postMessage || !window.addEventListener) { | ||
return null; | ||
return null | ||
} | ||
var callbacks = [undefined]; | ||
var message = 'zero-timeout-message'; | ||
var callbacks = [undefined] | ||
var message = 'zero-timeout-message' | ||
@@ -31,11 +31,11 @@ // Like setTimeout, but only takes a function argument. There's | ||
// use a closure). | ||
var setZeroTimeout = function setZeroTimeout(callback) { | ||
var id = callbacks.length; | ||
callbacks.push(callback); | ||
window.postMessage(message + id.toString(36), '*'); | ||
var setZeroTimeout = function setZeroTimeout (callback) { | ||
var id = callbacks.length | ||
callbacks.push(callback) | ||
window.postMessage(message + id.toString(36), '*') | ||
return id; | ||
}; | ||
return id | ||
} | ||
window.addEventListener('message', function setZeroTimeoutMessage(evt) { | ||
window.addEventListener('message', function setZeroTimeoutMessage (evt) { | ||
// Skipping checking event source, retarded IE confused this window | ||
@@ -46,36 +46,36 @@ // object with another in the presence of iframe | ||
evt.source !== window */) { | ||
return; | ||
return | ||
} | ||
evt.stopImmediatePropagation(); | ||
evt.stopImmediatePropagation() | ||
var id = parseInt(evt.data.substr(message.length), 36); | ||
var id = parseInt(evt.data.substr(message.length), 36) | ||
if (!callbacks[id]) { | ||
return; | ||
return | ||
} | ||
callbacks[id](); | ||
callbacks[id] = undefined; | ||
}, true); | ||
callbacks[id]() | ||
callbacks[id] = undefined | ||
}, true) | ||
/* specify clearImmediate() here since we need the scope */ | ||
window.clearImmediate = function clearZeroTimeout(id) { | ||
window.clearImmediate = function clearZeroTimeout (id) { | ||
if (!callbacks[id]) { | ||
return; | ||
return | ||
} | ||
callbacks[id] = undefined; | ||
}; | ||
callbacks[id] = undefined | ||
} | ||
return setZeroTimeout; | ||
return setZeroTimeout | ||
})() || | ||
// fallback | ||
function setImmediateFallback(fn) { | ||
window.setTimeout(fn, 0); | ||
}; | ||
})(); | ||
function setImmediateFallback (fn) { | ||
window.setTimeout(fn, 0) | ||
} | ||
})() | ||
} | ||
if (!window.clearImmediate) { | ||
window.clearImmediate = (function setupClearImmediate() { | ||
window.clearImmediate = (function setupClearImmediate () { | ||
return window.msClearImmediate || | ||
@@ -87,97 +87,98 @@ window.webkitClearImmediate || | ||
// fallback | ||
function clearImmediateFallback(timer) { | ||
window.clearTimeout(timer); | ||
}; | ||
})(); | ||
function clearImmediateFallback (timer) { | ||
window.clearTimeout(timer) | ||
} | ||
})() | ||
} | ||
(function(global) { | ||
(function (global) { | ||
// Check if WordCloud can run on this browser | ||
var isSupported = (function isSupported() { | ||
var canvas = document.createElement('canvas'); | ||
var isSupported = (function isSupported () { | ||
var canvas = document.createElement('canvas') | ||
if (!canvas || !canvas.getContext) { | ||
return false; | ||
return false | ||
} | ||
var ctx = canvas.getContext('2d'); | ||
var ctx = canvas.getContext('2d') | ||
if (!ctx) { | ||
return false; | ||
return false | ||
} | ||
if (!ctx.getImageData) { | ||
return false; | ||
return false | ||
} | ||
if (!ctx.fillText) { | ||
return false; | ||
return false | ||
} | ||
if (!Array.prototype.some) { | ||
return false; | ||
return false | ||
} | ||
if (!Array.prototype.push) { | ||
return false; | ||
return false | ||
} | ||
return true; | ||
}()); | ||
return true | ||
}()) | ||
// Find out if the browser impose minium font size by | ||
// drawing small texts on a canvas and measure it's width. | ||
var minFontSize = (function getMinFontSize() { | ||
var minFontSize = (function getMinFontSize () { | ||
if (!isSupported) { | ||
return; | ||
return | ||
} | ||
var ctx = document.createElement('canvas').getContext('2d'); | ||
var ctx = document.createElement('canvas').getContext('2d') | ||
// start from 20 | ||
var size = 20; | ||
var size = 20 | ||
// two sizes to measure | ||
var hanWidth, mWidth; | ||
var hanWidth, mWidth | ||
while (size) { | ||
ctx.font = size.toString(10) + 'px sans-serif'; | ||
ctx.font = size.toString(10) + 'px sans-serif' | ||
if ((ctx.measureText('\uFF37').width === hanWidth) && | ||
(ctx.measureText('m').width) === mWidth) { | ||
return (size + 1); | ||
return (size + 1) | ||
} | ||
hanWidth = ctx.measureText('\uFF37').width; | ||
mWidth = ctx.measureText('m').width; | ||
hanWidth = ctx.measureText('\uFF37').width | ||
mWidth = ctx.measureText('m').width | ||
size--; | ||
size-- | ||
} | ||
return 0; | ||
})(); | ||
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 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) { | ||
var WordCloud = function WordCloud (elements, options) { | ||
if (!isSupported) { | ||
return; | ||
return | ||
} | ||
if (!Array.isArray(elements)) { | ||
elements = [elements]; | ||
elements = [elements] | ||
} | ||
elements.forEach(function(el, i) { | ||
elements.forEach(function (el, i) { | ||
if (typeof el === 'string') { | ||
elements[i] = document.getElementById(el); | ||
elements[i] = document.getElementById(el) | ||
if (!elements[i]) { | ||
throw 'The element id specified is not found.'; | ||
throw new Error('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.'; | ||
throw new Error('You must pass valid HTML elements, or ID of the element.') | ||
} | ||
}); | ||
}) | ||
@@ -194,3 +195,3 @@ /* Default values to be overwritten by options object */ | ||
clearCanvas: true, | ||
backgroundColor: '#fff', // opaque white = rgba(255, 255, 255, 1) | ||
backgroundColor: '#fff', // opaque white = rgba(255, 255, 255, 1) | ||
@@ -208,5 +209,5 @@ gridSize: 8, | ||
abortThreshold: 0, // disabled | ||
abort: function noop() {}, | ||
abort: function noop () {}, | ||
minRotation: - Math.PI / 2, | ||
minRotation: -Math.PI / 2, | ||
maxRotation: Math.PI / 2, | ||
@@ -225,3 +226,3 @@ rotationSteps: 0, | ||
click: null | ||
}; | ||
} | ||
@@ -231,3 +232,3 @@ if (options) { | ||
if (key in settings) { | ||
settings[key] = options[key]; | ||
settings[key] = options[key] | ||
} | ||
@@ -239,6 +240,6 @@ } | ||
if (typeof settings.weightFactor !== 'function') { | ||
var factor = settings.weightFactor; | ||
settings.weightFactor = function weightFactor(pt) { | ||
return pt * factor; //in px | ||
}; | ||
var factor = settings.weightFactor | ||
settings.weightFactor = function weightFactor (pt) { | ||
return pt * factor // in px | ||
} | ||
} | ||
@@ -253,23 +254,20 @@ | ||
// 'circle' is the default and a shortcut in the code loop. | ||
settings.shape = 'circle'; | ||
break; | ||
settings.shape = 'circle' | ||
break | ||
case 'cardioid': | ||
settings.shape = function shapeCardioid(theta) { | ||
return 1 - Math.sin(theta); | ||
}; | ||
break; | ||
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) | ||
*/ | ||
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': | ||
@@ -279,7 +277,7 @@ // http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+ | ||
// +0+..+2*PI | ||
settings.shape = function shapeSquare(theta) { | ||
var thetaPrime = theta % (2 * Math.PI / 4); | ||
return 1 / (Math.cos(thetaPrime) + Math.sin(thetaPrime)); | ||
}; | ||
break; | ||
settings.shape = function shapeSquare (theta) { | ||
var thetaPrime = theta % (2 * Math.PI / 4) | ||
return 1 / (Math.cos(thetaPrime) + Math.sin(thetaPrime)) | ||
} | ||
break | ||
@@ -289,9 +287,9 @@ case 'square': | ||
// )),1%2Fabs(sin(t)))),+t+%3D+0+..+2*PI | ||
settings.shape = function shapeSquare(theta) { | ||
settings.shape = function shapeSquare (theta) { | ||
return Math.min( | ||
1 / Math.abs(Math.cos(theta)), | ||
1 / Math.abs(Math.sin(theta)) | ||
); | ||
}; | ||
break; | ||
) | ||
} | ||
break | ||
@@ -302,38 +300,38 @@ case 'triangle-forward': | ||
// %29%29%2C+t+%3D+0+..+2*PI | ||
settings.shape = function shapeTriangle(theta) { | ||
var thetaPrime = theta % (2 * Math.PI / 3); | ||
settings.shape = function shapeTriangle (theta) { | ||
var thetaPrime = theta % (2 * Math.PI / 3) | ||
return 1 / (Math.cos(thetaPrime) + | ||
Math.sqrt(3) * Math.sin(thetaPrime)); | ||
}; | ||
break; | ||
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); | ||
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; | ||
Math.sqrt(3) * Math.sin(thetaPrime)) | ||
} | ||
break | ||
case 'pentagon': | ||
settings.shape = function shapePentagon(theta) { | ||
var thetaPrime = (theta + 0.955) % (2 * Math.PI / 5); | ||
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; | ||
0.726543 * Math.sin(thetaPrime)) | ||
} | ||
break | ||
case 'star': | ||
settings.shape = function shapeStar(theta) { | ||
var thetaPrime = (theta + 0.955) % (2 * Math.PI / 10); | ||
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)); | ||
3.07768 * Math.sin((2 * Math.PI / 10) - thetaPrime)) | ||
} else { | ||
return 1 / (Math.cos(thetaPrime) + | ||
3.07768 * Math.sin(thetaPrime)); | ||
3.07768 * Math.sin(thetaPrime)) | ||
} | ||
}; | ||
break; | ||
} | ||
break | ||
} | ||
@@ -343,12 +341,12 @@ } | ||
/* Make sure gridSize is a whole number and is not smaller than 4px */ | ||
settings.gridSize = Math.max(Math.floor(settings.gridSize), 4); | ||
settings.gridSize = Math.max(Math.floor(settings.gridSize), 4) | ||
/* shorthand */ | ||
var g = settings.gridSize; | ||
var maskRectWidth = g - settings.maskGapWidth; | ||
var g = settings.gridSize | ||
var maskRectWidth = g - settings.maskGapWidth | ||
/* normalize rotation settings */ | ||
var rotationRange = Math.abs(settings.maxRotation - settings.minRotation); | ||
var rotationSteps = Math.abs(Math.floor(settings.rotationSteps)); | ||
var minRotation = Math.min(settings.maxRotation, settings.minRotation); | ||
var rotationRange = Math.abs(settings.maxRotation - settings.minRotation) | ||
var rotationSteps = Math.abs(Math.floor(settings.rotationSteps)) | ||
var minRotation = Math.min(settings.maxRotation, settings.minRotation) | ||
@@ -359,119 +357,118 @@ /* information/object available to all functions, set when start() */ | ||
center, // position of the center of the cloud | ||
maxRadius; | ||
maxRadius | ||
/* timestamp for measuring each putWord() action */ | ||
var escapeTime; | ||
var escapeTime | ||
/* function for getting the color of the text */ | ||
var getTextColor; | ||
function random_hsl_color(min, max) { | ||
var getTextColor | ||
function randomHslColor (min, max) { | ||
return 'hsl(' + | ||
(Math.random() * 360).toFixed() + ',' + | ||
(Math.random() * 30 + 70).toFixed() + '%,' + | ||
(Math.random() * (max - min) + min).toFixed() + '%)'; | ||
(Math.random() * (max - min) + min).toFixed() + '%)' | ||
} | ||
switch (settings.color) { | ||
case 'random-dark': | ||
getTextColor = function getRandomDarkColor() { | ||
return random_hsl_color(10, 50); | ||
}; | ||
break; | ||
getTextColor = function getRandomDarkColor () { | ||
return randomHslColor(10, 50) | ||
} | ||
break | ||
case 'random-light': | ||
getTextColor = function getRandomLightColor() { | ||
return random_hsl_color(50, 90); | ||
}; | ||
break; | ||
getTextColor = function getRandomLightColor () { | ||
return randomHslColor(50, 90) | ||
} | ||
break | ||
default: | ||
if (typeof settings.color === 'function') { | ||
getTextColor = settings.color; | ||
getTextColor = settings.color | ||
} | ||
break; | ||
break | ||
} | ||
/* function for getting the font-weight of the text */ | ||
var getTextFontWeight; | ||
var getTextFontWeight | ||
if (typeof settings.fontWeight === 'function') { | ||
getTextFontWeight = settings.fontWeight; | ||
getTextFontWeight = settings.fontWeight | ||
} | ||
/* function for getting the classes of the text */ | ||
var getTextClasses = null; | ||
var getTextClasses = null | ||
if (typeof settings.classes === 'function') { | ||
getTextClasses = settings.classes; | ||
getTextClasses = settings.classes | ||
} | ||
/* Interactive */ | ||
var interactive = false; | ||
var infoGrid = []; | ||
var hovered; | ||
var interactive = false | ||
var infoGrid = [] | ||
var hovered | ||
var getInfoGridFromMouseTouchEvent = | ||
function getInfoGridFromMouseTouchEvent(evt) { | ||
var canvas = evt.currentTarget; | ||
var rect = canvas.getBoundingClientRect(); | ||
var clientX; | ||
var clientY; | ||
function getInfoGridFromMouseTouchEvent (evt) { | ||
var canvas = evt.currentTarget | ||
var rect = canvas.getBoundingClientRect() | ||
var clientX | ||
var clientY | ||
/** Detect if touches are available */ | ||
if (evt.touches) { | ||
clientX = evt.touches[0].clientX; | ||
clientY = evt.touches[0].clientY; | ||
clientX = evt.touches[0].clientX | ||
clientY = evt.touches[0].clientY | ||
} else { | ||
clientX = evt.clientX; | ||
clientY = evt.clientY; | ||
clientX = evt.clientX | ||
clientY = evt.clientY | ||
} | ||
var eventX = clientX - rect.left; | ||
var eventY = clientY - rect.top; | ||
var eventX = clientX - rect.left | ||
var eventY = 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); | ||
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]; | ||
}; | ||
return infoGrid[x][y] | ||
} | ||
var wordcloudhover = function wordcloudhover(evt) { | ||
var info = getInfoGridFromMouseTouchEvent(evt); | ||
var wordcloudhover = function wordcloudhover (evt) { | ||
var info = getInfoGridFromMouseTouchEvent(evt) | ||
if (hovered === info) { | ||
return; | ||
return | ||
} | ||
hovered = info; | ||
hovered = info | ||
if (!info) { | ||
settings.hover(undefined, undefined, evt); | ||
settings.hover(undefined, undefined, evt) | ||
return; | ||
return | ||
} | ||
settings.hover(info.item, info.dimension, evt); | ||
settings.hover(info.item, info.dimension, evt) | ||
} | ||
}; | ||
var wordcloudclick = function wordcloudclick(evt) { | ||
var info = getInfoGridFromMouseTouchEvent(evt); | ||
var wordcloudclick = function wordcloudclick (evt) { | ||
var info = getInfoGridFromMouseTouchEvent(evt) | ||
if (!info) { | ||
return; | ||
return | ||
} | ||
settings.click(info.item, info.dimension, evt); | ||
evt.preventDefault(); | ||
}; | ||
settings.click(info.item, info.dimension, evt) | ||
evt.preventDefault() | ||
} | ||
/* Get points on the grid for a given radius away from the center */ | ||
var pointsAtRadius = []; | ||
var getPointsAtRadius = function getPointsAtRadius(radius) { | ||
var pointsAtRadius = [] | ||
var getPointsAtRadius = function getPointsAtRadius (radius) { | ||
if (pointsAtRadius[radius]) { | ||
return pointsAtRadius[radius]; | ||
return pointsAtRadius[radius] | ||
} | ||
// Look for these number of points on each radius | ||
var T = radius * 8; | ||
var T = radius * 8 | ||
// Getting all the points at this radius | ||
var t = T; | ||
var points = []; | ||
var t = T | ||
var points = [] | ||
if (radius === 0) { | ||
points.push([center[0], center[1], 0]); | ||
points.push([center[0], center[1], 0]) | ||
} | ||
@@ -481,8 +478,8 @@ | ||
// distort the radius to put the cloud in shape | ||
var rx = 1; | ||
var rx = 1 | ||
if (settings.shape !== 'circle') { | ||
rx = settings.shape(t / T * 2 * Math.PI); // 0 to 1 | ||
rx = settings.shape(t / T * 2 * Math.PI) // 0 to 1 | ||
} | ||
// Push [x, y, t]; t is used solely for getTextColor() | ||
// Push [x, y, t] t is used solely for getTextColor() | ||
points.push([ | ||
@@ -492,27 +489,27 @@ center[0] + radius * rx * Math.cos(-t / T * 2 * Math.PI), | ||
settings.ellipticity, | ||
t / T * 2 * Math.PI]); | ||
t / T * 2 * Math.PI]) | ||
} | ||
pointsAtRadius[radius] = points; | ||
return points; | ||
}; | ||
pointsAtRadius[radius] = points | ||
return points | ||
} | ||
/* Return true if we had spent too much time */ | ||
var exceedTime = function exceedTime() { | ||
var exceedTime = function exceedTime () { | ||
return ((settings.abortThreshold > 0) && | ||
((new Date()).getTime() - escapeTime > settings.abortThreshold)); | ||
}; | ||
((new Date()).getTime() - escapeTime > settings.abortThreshold)) | ||
} | ||
/* Get the deg of rotation according to settings, and luck. */ | ||
var getRotateDeg = function getRotateDeg() { | ||
var getRotateDeg = function getRotateDeg () { | ||
if (settings.rotateRatio === 0) { | ||
return 0; | ||
return 0 | ||
} | ||
if (Math.random() > settings.rotateRatio) { | ||
return 0; | ||
return 0 | ||
} | ||
if (rotationRange === 0) { | ||
return minRotation; | ||
return minRotation | ||
} | ||
@@ -524,17 +521,16 @@ | ||
Math.floor(Math.random() * rotationSteps) * | ||
rotationRange / (rotationSteps - 1); | ||
rotationRange / (rotationSteps - 1) | ||
} else { | ||
return minRotation + Math.random() * rotationRange | ||
} | ||
else { | ||
return minRotation + Math.random() * rotationRange; | ||
} | ||
}; | ||
} | ||
var getTextInfo = function getTextInfo(word, weight, rotateDeg) { | ||
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); | ||
var debug = false | ||
var fontSize = settings.weightFactor(weight) | ||
if (fontSize <= settings.minSize) { | ||
return false; | ||
return false | ||
} | ||
@@ -545,41 +541,42 @@ | ||
// It will always be 1 or 2n. | ||
var mu = 1; | ||
var mu = 1 | ||
if (fontSize < minFontSize) { | ||
mu = (function calculateScaleFactor() { | ||
var mu = 2; | ||
mu = (function calculateScaleFactor () { | ||
var mu = 2 | ||
while (mu * fontSize < minFontSize) { | ||
mu += 2; | ||
mu += 2 | ||
} | ||
return mu; | ||
})(); | ||
return mu | ||
})() | ||
} | ||
// Get fontWeight that will be used to set fctx.font | ||
var fontWeight; | ||
var fontWeight | ||
if (getTextFontWeight) { | ||
fontWeight = getTextFontWeight(word, weight, fontSize); | ||
fontWeight = getTextFontWeight(word, weight, fontSize) | ||
} else { | ||
fontWeight = settings.fontWeight; | ||
fontWeight = settings.fontWeight | ||
} | ||
var fcanvas = document.createElement('canvas'); | ||
var fctx = fcanvas.getContext('2d', { willReadFrequently: true }); | ||
var fcanvas = document.createElement('canvas') | ||
var fctx = fcanvas.getContext('2d', { willReadFrequently: true }) | ||
fctx.font = fontWeight + ' ' + | ||
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily; | ||
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily | ||
// Estimate the dimension of the text with measureText(). | ||
var fw = fctx.measureText(word).width / mu; | ||
var fw = fctx.measureText(word).width / mu | ||
var fh = Math.max(fontSize * mu, | ||
fctx.measureText('m').width, | ||
fctx.measureText('\uFF37').width) / 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; | ||
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 | ||
@@ -590,30 +587,30 @@ // Calculate the proper offsets to make the text centered at | ||
// This is simply half of the width. | ||
var fillTextOffsetX = - fw / 2; | ||
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; | ||
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); | ||
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; | ||
boxHeight * Math.abs(Math.sin(rotateDeg))) / g) | ||
var width = cgw * g | ||
var height = cgh * g | ||
fcanvas.setAttribute('width', width); | ||
fcanvas.setAttribute('height', height); | ||
fcanvas.setAttribute('width', width) | ||
fcanvas.setAttribute('height', height) | ||
if (debug) { | ||
// Attach fcanvas to the DOM | ||
document.body.appendChild(fcanvas); | ||
document.body.appendChild(fcanvas) | ||
// Save it's state so that we could restore and draw the grid correctly. | ||
fctx.save(); | ||
fctx.save() | ||
} | ||
// Scale the canvas with |mu|. | ||
fctx.scale(1 / mu, 1 / mu); | ||
fctx.translate(width * mu / 2, height * mu / 2); | ||
fctx.rotate(- rotateDeg); | ||
fctx.scale(1 / mu, 1 / mu) | ||
fctx.translate(width * mu / 2, height * mu / 2) | ||
fctx.rotate(-rotateDeg) | ||
@@ -623,3 +620,3 @@ // Once the width/height is set, ctx info will be reset. | ||
fctx.font = fontWeight + ' ' + | ||
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily; | ||
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily | ||
@@ -632,12 +629,14 @@ // Fill the text into the fcanvas. | ||
// 0.5 * fontSize lower. | ||
fctx.fillStyle = '#000'; | ||
fctx.textBaseline = 'middle'; | ||
fctx.fillText(word, fillTextOffsetX * mu, | ||
(fillTextOffsetY + fontSize * 0.5) * mu); | ||
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; | ||
var imageData = fctx.getImageData(0, 0, width, height).data | ||
if (exceedTime()) { | ||
return false; | ||
return false | ||
} | ||
@@ -647,49 +646,51 @@ | ||
// Draw the box of the original estimation | ||
fctx.strokeRect(fillTextOffsetX * mu, | ||
fillTextOffsetY, fw * mu, fh * mu); | ||
fctx.restore(); | ||
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]; | ||
var occupied = [] | ||
var gx = cgw | ||
var gy, x, y | ||
var bounds = [cgh / 2, cgw / 2, cgh / 2, cgw / 2] | ||
while (gx--) { | ||
gy = cgh; | ||
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]); | ||
y = g | ||
/* eslint no-labels: ["error", { "allowLoop": true }] */ | ||
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 (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(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, 0, 255, 0.5)' | ||
fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5) | ||
} | ||
} | ||
@@ -699,7 +700,9 @@ } | ||
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); | ||
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 | ||
) | ||
} | ||
@@ -719,84 +722,75 @@ | ||
fontSize: fontSize | ||
}; | ||
}; | ||
} | ||
} | ||
/* Determine if there is room available in the given dimension */ | ||
var canFitText = function canFitText(gx, gy, gw, gh, occupied) { | ||
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; | ||
var i = occupied.length | ||
while (i--) { | ||
var px = gx + occupied[i][0]; | ||
var py = gy + occupied[i][1]; | ||
var px = gx + occupied[i][0] | ||
var py = gy + occupied[i][1] | ||
if (px >= ngx || py >= ngy || px < 0 || py < 0) { | ||
if (!settings.drawOutOfBound) { | ||
return false; | ||
return false | ||
} | ||
continue; | ||
continue | ||
} | ||
if (!grid[px][py]) { | ||
return false; | ||
return false | ||
} | ||
} | ||
return true; | ||
}; | ||
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; | ||
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); | ||
color = getTextColor(word, weight, fontSize, distance, theta) | ||
} else { | ||
color = settings.color; | ||
color = settings.color | ||
} | ||
// get fontWeight that will be used to set ctx.font and font style rule | ||
var fontWeight; | ||
var fontWeight | ||
if (getTextFontWeight) { | ||
fontWeight = getTextFontWeight(word, weight, fontSize); | ||
fontWeight = getTextFontWeight(word, weight, fontSize) | ||
} else { | ||
fontWeight = settings.fontWeight; | ||
fontWeight = settings.fontWeight | ||
} | ||
var classes; | ||
var classes | ||
if (getTextClasses) { | ||
classes = getTextClasses(word, weight, fontSize); | ||
classes = getTextClasses(word, weight, fontSize) | ||
} else { | ||
classes = settings.classes; | ||
classes = settings.classes | ||
} | ||
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) { | ||
elements.forEach(function (el) { | ||
if (el.getContext) { | ||
var ctx = el.getContext('2d'); | ||
var mu = info.mu; | ||
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.save() | ||
ctx.scale(1 / mu, 1 / mu) | ||
ctx.font = fontWeight + ' ' + | ||
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily; | ||
ctx.fillStyle = color; | ||
(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); | ||
ctx.translate( | ||
(gx + info.gw / 2) * g * mu, | ||
(gy + info.gh / 2) * g * mu | ||
) | ||
if (rotateDeg !== 0) { | ||
ctx.rotate(- rotateDeg); | ||
ctx.rotate(-rotateDeg) | ||
} | ||
@@ -811,93 +805,95 @@ | ||
// 0.5 * fontSize lower. | ||
ctx.textBaseline = 'middle'; | ||
ctx.fillText(word, info.fillTextOffsetX * mu, | ||
(info.fillTextOffsetY + fontSize * 0.5) * mu); | ||
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); */ | ||
info.fillTextWidth, info.fillTextHeight) */ | ||
// Restore the state. | ||
ctx.restore(); | ||
ctx.restore() | ||
} else { | ||
// drawText on DIV element | ||
var span = document.createElement('span'); | ||
var transformRule = ''; | ||
transformRule = 'rotate(' + (- rotateDeg / Math.PI * 180) + 'deg) '; | ||
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) + ')'; | ||
'scale(' + (1 / info.mu) + ')' | ||
} | ||
var styleRules = { | ||
'position': 'absolute', | ||
'display': 'block', | ||
'font': 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', | ||
'lineHeight': fontSize + 'px', | ||
'whiteSpace': 'nowrap', | ||
'transform': transformRule, | ||
'webkitTransform': transformRule, | ||
'msTransform': transformRule, | ||
'transformOrigin': '50% 40%', | ||
'webkitTransformOrigin': '50% 40%', | ||
'msTransformOrigin': '50% 40%' | ||
}; | ||
position: 'absolute', | ||
display: 'block', | ||
font: 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', | ||
lineHeight: fontSize + 'px', | ||
whiteSpace: 'nowrap', | ||
transform: transformRule, | ||
webkitTransform: transformRule, | ||
msTransform: transformRule, | ||
transformOrigin: '50% 40%', | ||
webkitTransformOrigin: '50% 40%', | ||
msTransformOrigin: '50% 40%' | ||
} | ||
if (color) { | ||
styleRules.color = color; | ||
styleRules.color = color | ||
} | ||
span.textContent = word; | ||
span.textContent = word | ||
for (var cssProp in styleRules) { | ||
span.style[cssProp] = styleRules[cssProp]; | ||
span.style[cssProp] = styleRules[cssProp] | ||
} | ||
if (attributes) { | ||
for (var attribute in attributes) { | ||
span.setAttribute(attribute, attributes[attribute]); | ||
span.setAttribute(attribute, attributes[attribute]) | ||
} | ||
} | ||
if (classes) { | ||
span.className += classes; | ||
span.className += classes | ||
} | ||
el.appendChild(span); | ||
el.appendChild(span) | ||
} | ||
}); | ||
}; | ||
}) | ||
} | ||
/* Help function to updateGrid */ | ||
var fillGridAt = function fillGridAt(x, y, drawMask, dimension, item) { | ||
var fillGridAt = function fillGridAt (x, y, drawMask, dimension, item) { | ||
if (x >= ngx || y >= ngy || x < 0 || y < 0) { | ||
return; | ||
return | ||
} | ||
grid[x][y] = false; | ||
grid[x][y] = false | ||
if (drawMask) { | ||
var ctx = elements[0].getContext('2d'); | ||
ctx.fillRect(x * g, y * g, maskRectWidth, maskRectWidth); | ||
var ctx = elements[0].getContext('2d') | ||
ctx.fillRect(x * g, y * g, maskRectWidth, maskRectWidth) | ||
} | ||
if (interactive) { | ||
infoGrid[x][y] = { item: item, dimension: dimension }; | ||
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; | ||
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; | ||
ctx = elements[0].getContext('2d') | ||
ctx.save() | ||
ctx.fillStyle = settings.maskColor | ||
} | ||
var dimension; | ||
var dimension | ||
if (interactive) { | ||
var bounds = info.bounds; | ||
var bounds = info.bounds | ||
dimension = { | ||
@@ -908,21 +904,21 @@ x: (gx + bounds[3]) * g, | ||
h: (bounds[2] - bounds[0] + 1) * g | ||
}; | ||
} | ||
} | ||
var i = occupied.length; | ||
var i = occupied.length | ||
while (i--) { | ||
var px = gx + occupied[i][0]; | ||
var py = gy + occupied[i][1]; | ||
var px = gx + occupied[i][0] | ||
var py = gy + occupied[i][1] | ||
if (px >= ngx || py >= ngy || px < 0 || py < 0) { | ||
continue; | ||
continue | ||
} | ||
fillGridAt(px, py, drawMask, dimension, item); | ||
fillGridAt(px, py, drawMask, dimension, item) | ||
} | ||
if (drawMask) { | ||
ctx.restore(); | ||
ctx.restore() | ||
} | ||
}; | ||
} | ||
@@ -932,24 +928,24 @@ /* putWord() processes each item on the list, | ||
put it on the canvas. */ | ||
var putWord = function putWord(item) { | ||
var word, weight, attributes; | ||
var putWord = function putWord (item) { | ||
var word, weight, attributes | ||
if (Array.isArray(item)) { | ||
word = item[0]; | ||
weight = item[1]; | ||
word = item[0] | ||
weight = item[1] | ||
} else { | ||
word = item.word; | ||
weight = item.weight; | ||
attributes = item.attributes; | ||
word = item.word | ||
weight = item.weight | ||
attributes = item.attributes | ||
} | ||
var rotateDeg = getRotateDeg(); | ||
var rotateDeg = getRotateDeg() | ||
// get info needed to put the text onto the canvas | ||
var info = getTextInfo(word, weight, rotateDeg); | ||
var info = getTextInfo(word, weight, rotateDeg) | ||
// not getting the info means we shouldn't be drawing this one. | ||
if (!info) { | ||
return false; | ||
return false | ||
} | ||
if (exceedTime()) { | ||
return false; | ||
return false | ||
} | ||
@@ -960,7 +956,7 @@ | ||
// word is larger than the canvas. | ||
if (!settings.drawOutOfBound) { | ||
if (!settings.drawOutOfBound && !settings.shrinkToFit) { | ||
var bounds = info.bounds; | ||
if ((bounds[1] - bounds[3] + 1) > ngx || | ||
(bounds[2] - bounds[0] + 1) > ngy) { | ||
return false; | ||
return false | ||
} | ||
@@ -971,9 +967,9 @@ } | ||
// start looking for the nearest points | ||
var r = maxRadius + 1; | ||
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; | ||
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 | ||
@@ -983,3 +979,3 @@ // If we cannot fit the text at this position, return false | ||
if (!canFitText(gx, gy, gw, gh, info.occupied)) { | ||
return false; | ||
return false | ||
} | ||
@@ -989,17 +985,17 @@ | ||
drawText(gx, gy, info, word, weight, | ||
(maxRadius - r), gxy[2], rotateDeg, attributes); | ||
(maxRadius - r), gxy[2], rotateDeg, attributes) | ||
// Mark the spaces on the grid as filled | ||
updateGrid(gx, gy, gw, gh, info, item); | ||
updateGrid(gx, gy, gw, gh, info, item) | ||
// Return true so some() will stop and also return true. | ||
return true; | ||
}; | ||
return true | ||
} | ||
while (r--) { | ||
var points = getPointsAtRadius(maxRadius - r); | ||
var points = getPointsAtRadius(maxRadius - r) | ||
if (settings.shuffle) { | ||
points = [].concat(points); | ||
shuffleArray(points); | ||
points = [].concat(points) | ||
shuffleArray(points) | ||
} | ||
@@ -1011,7 +1007,7 @@ | ||
// If all the points returns false, array.some() returns false. | ||
var drawn = points.some(tryToPutWordAtPoint); | ||
var drawn = points.some(tryToPutWordAtPoint) | ||
if (drawn) { | ||
// leave putWord() and return true | ||
return true; | ||
return true | ||
} | ||
@@ -1021,45 +1017,45 @@ } | ||
if (Array.isArray(item)) { | ||
item[1] = item[1] * 3 / 4; | ||
item[1] = item[1] * 3 / 4 | ||
} else { | ||
item.weight = item.weight * 3 / 4; | ||
item.weight = item.weight * 3 / 4 | ||
} | ||
return putWord(item); | ||
return putWord(item) | ||
} | ||
// we tried all distances but text won't fit, return false | ||
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, details) { | ||
var sendEvent = function sendEvent (type, cancelable, details) { | ||
if (cancelable) { | ||
return !elements.some(function(el) { | ||
return !elements.some(function (el) { | ||
var event = new CustomEvent(type, { | ||
detail: details || {} | ||
}); | ||
return !el.dispatchEvent(event); | ||
}, this); | ||
}) | ||
return !el.dispatchEvent(event) | ||
}, this) | ||
} else { | ||
elements.forEach(function(el) { | ||
elements.forEach(function (el) { | ||
var event = new CustomEvent(type, { | ||
detail: details || {} | ||
}); | ||
el.dispatchEvent(event); | ||
}, this); | ||
}) | ||
el.dispatchEvent(event) | ||
}, this) | ||
} | ||
}; | ||
} | ||
/* Start drawing on a canvas */ | ||
var start = function start() { | ||
var start = function start () { | ||
// For dimensions, clearCanvas etc., | ||
// we only care about the first element. | ||
var canvas = elements[0]; | ||
var canvas = elements[0] | ||
if (canvas.getContext) { | ||
ngx = Math.ceil(canvas.width / g); | ||
ngy = Math.ceil(canvas.height / g); | ||
ngx = Math.ceil(canvas.width / g) | ||
ngy = Math.ceil(canvas.height / g) | ||
} else { | ||
var rect = canvas.getBoundingClientRect(); | ||
ngx = Math.ceil(rect.width / g); | ||
ngy = Math.ceil(rect.height / g); | ||
var rect = canvas.getBoundingClientRect() | ||
ngx = Math.ceil(rect.width / g) | ||
ngy = Math.ceil(rect.height / g) | ||
} | ||
@@ -1070,39 +1066,39 @@ | ||
if (!sendEvent('wordcloudstart', true)) { | ||
return; | ||
return | ||
} | ||
// Determine the center of the word cloud | ||
center = (settings.origin) ? | ||
[settings.origin[0]/g, settings.origin[1]/g] : | ||
[ngx / 2, ngy / 2]; | ||
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)); | ||
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 = []; | ||
grid = [] | ||
var gx, gy, i; | ||
var gx, gy, i | ||
if (!canvas.getContext || settings.clearCanvas) { | ||
elements.forEach(function(el) { | ||
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)); | ||
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; | ||
el.style.position = 'relative'; | ||
el.textContent = '' | ||
el.style.backgroundColor = settings.backgroundColor | ||
el.style.position = 'relative' | ||
} | ||
}); | ||
}) | ||
/* fill the grid with empty state */ | ||
gx = ngx; | ||
gx = ngx | ||
while (gx--) { | ||
grid[gx] = []; | ||
gy = ngy; | ||
grid[gx] = [] | ||
gy = ngy | ||
while (gy--) { | ||
grid[gx][gy] = true; | ||
grid[gx][gy] = true | ||
} | ||
@@ -1113,7 +1109,7 @@ } | ||
another canvas and fill the specified background color. */ | ||
var bctx = document.createElement('canvas').getContext('2d'); | ||
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; | ||
bctx.fillStyle = settings.backgroundColor | ||
bctx.fillRect(0, 0, 1, 1) | ||
var bgPixel = bctx.getImageData(0, 0, 1, 1).data | ||
@@ -1124,20 +1120,21 @@ /* Read back the pixels of the canvas we got to tell which part of the | ||
var imageData = | ||
canvas.getContext('2d').getImageData(0, 0, ngx * g, ngy * g).data; | ||
canvas.getContext('2d').getImageData(0, 0, ngx * g, ngy * g).data | ||
gx = ngx; | ||
var x, y; | ||
gx = ngx | ||
var x, y | ||
while (gx--) { | ||
grid[gx] = []; | ||
gy = ngy; | ||
grid[gx] = [] | ||
gy = ngy | ||
while (gy--) { | ||
y = g; | ||
y = g | ||
/* eslint no-labels: ["error", { "allowLoop": true }] */ | ||
singleGridLoop: while (y--) { | ||
x = g; | ||
x = g | ||
while (x--) { | ||
i = 4; | ||
i = 4 | ||
while (i--) { | ||
if (imageData[((gy * g + y) * ngx * g + | ||
(gx * g + x)) * 4 + i] !== bgPixel[i]) { | ||
grid[gx][gy] = false; | ||
break singleGridLoop; | ||
grid[gx][gy] = false | ||
break singleGridLoop | ||
} | ||
@@ -1148,3 +1145,3 @@ } | ||
if (grid[gx][gy] !== false) { | ||
grid[gx][gy] = true; | ||
grid[gx][gy] = true | ||
} | ||
@@ -1154,3 +1151,3 @@ } | ||
imageData = bctx = bgPixel = undefined; | ||
imageData = bctx = bgPixel = undefined | ||
} | ||
@@ -1160,100 +1157,100 @@ | ||
if (settings.hover || settings.click) { | ||
interactive = true | ||
interactive = true; | ||
/* fill the grid with empty state */ | ||
gx = ngx + 1; | ||
gx = ngx + 1 | ||
while (gx--) { | ||
infoGrid[gx] = []; | ||
infoGrid[gx] = [] | ||
} | ||
if (settings.hover) { | ||
canvas.addEventListener('mousemove', wordcloudhover); | ||
canvas.addEventListener('mousemove', wordcloudhover) | ||
} | ||
if (settings.click) { | ||
canvas.addEventListener('click', wordcloudclick); | ||
canvas.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)'; | ||
canvas.addEventListener('click', wordcloudclick) | ||
canvas.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)' | ||
} | ||
canvas.addEventListener('wordcloudstart', function stopInteraction() { | ||
canvas.removeEventListener('wordcloudstart', stopInteraction); | ||
canvas.addEventListener('wordcloudstart', function stopInteraction () { | ||
canvas.removeEventListener('wordcloudstart', stopInteraction) | ||
canvas.removeEventListener('mousemove', wordcloudhover); | ||
canvas.removeEventListener('click', wordcloudclick); | ||
hovered = undefined; | ||
}); | ||
canvas.removeEventListener('mousemove', wordcloudhover) | ||
canvas.removeEventListener('click', wordcloudclick) | ||
hovered = undefined | ||
}) | ||
} | ||
i = 0; | ||
var loopingFunction, stoppingFunction; | ||
i = 0 | ||
var loopingFunction, stoppingFunction | ||
if (settings.wait !== 0) { | ||
loopingFunction = window.setTimeout; | ||
stoppingFunction = window.clearTimeout; | ||
loopingFunction = window.setTimeout | ||
stoppingFunction = window.clearTimeout | ||
} else { | ||
loopingFunction = window.setImmediate; | ||
stoppingFunction = window.clearImmediate; | ||
loopingFunction = window.setImmediate | ||
stoppingFunction = window.clearImmediate | ||
} | ||
var addEventListener = function addEventListener(type, listener) { | ||
elements.forEach(function(el) { | ||
el.addEventListener(type, listener); | ||
}, this); | ||
}; | ||
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 removeEventListener = function removeEventListener (type, listener) { | ||
elements.forEach(function (el) { | ||
el.removeEventListener(type, listener) | ||
}, this) | ||
} | ||
var anotherWordCloudStart = function anotherWordCloudStart() { | ||
removeEventListener('wordcloudstart', anotherWordCloudStart); | ||
stoppingFunction(timer); | ||
}; | ||
var anotherWordCloudStart = function anotherWordCloudStart () { | ||
removeEventListener('wordcloudstart', anotherWordCloudStart) | ||
stoppingFunction(timer) | ||
} | ||
addEventListener('wordcloudstart', anotherWordCloudStart); | ||
addEventListener('wordcloudstart', anotherWordCloudStart) | ||
var timer = loopingFunction(function loop() { | ||
var timer = loopingFunction(function loop () { | ||
if (i >= settings.list.length) { | ||
stoppingFunction(timer); | ||
sendEvent('wordcloudstop', false); | ||
removeEventListener('wordcloudstart', anotherWordCloudStart); | ||
stoppingFunction(timer) | ||
sendEvent('wordcloudstop', false) | ||
removeEventListener('wordcloudstart', anotherWordCloudStart) | ||
return; | ||
return | ||
} | ||
escapeTime = (new Date()).getTime(); | ||
var drawn = putWord(settings.list[i]); | ||
escapeTime = (new Date()).getTime() | ||
var drawn = putWord(settings.list[i]) | ||
var canceled = !sendEvent('wordclouddrawn', true, { | ||
item: settings.list[i], drawn: drawn }); | ||
item: settings.list[i], | ||
drawn: drawn | ||
}) | ||
if (exceedTime() || canceled) { | ||
stoppingFunction(timer); | ||
settings.abort(); | ||
sendEvent('wordcloudabort', false); | ||
sendEvent('wordcloudstop', false); | ||
removeEventListener('wordcloudstart', anotherWordCloudStart); | ||
return; | ||
stoppingFunction(timer) | ||
settings.abort() | ||
sendEvent('wordcloudabort', false) | ||
sendEvent('wordcloudstop', false) | ||
removeEventListener('wordcloudstart', anotherWordCloudStart) | ||
return | ||
} | ||
i++; | ||
timer = loopingFunction(loop, settings.wait); | ||
}, settings.wait); | ||
}; | ||
i++ | ||
timer = loopingFunction(loop, settings.wait) | ||
}, settings.wait) | ||
} | ||
// All set, start the drawing | ||
start(); | ||
}; | ||
start() | ||
} | ||
WordCloud.isSupported = isSupported; | ||
WordCloud.minFontSize = minFontSize; | ||
WordCloud.isSupported = isSupported | ||
WordCloud.minFontSize = minFontSize | ||
// Expose the library as an AMD module | ||
if (typeof define === 'function' && define.amd) { | ||
global.WordCloud = WordCloud; | ||
define('wordcloud', [], function() { return WordCloud; }); | ||
} else if (typeof module !== 'undefined' && module.exports) { | ||
module.exports = WordCloud; | ||
if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef | ||
global.WordCloud = WordCloud | ||
define('wordcloud', [], function () { return WordCloud }) // eslint-disable-line no-undef | ||
} else if (typeof module !== 'undefined' && module.exports) { // eslint-disable-line no-undef | ||
module.exports = WordCloud // eslint-disable-line no-undef | ||
} else { | ||
global.WordCloud = WordCloud; | ||
global.WordCloud = WordCloud | ||
} | ||
})(this); //jshint ignore:line | ||
})(this) // jshint ignore:line |
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
332100
18
2421
7