blob: 8594012fcc3e13df887788fd0ab6c7946cbbe08e [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const SVG_NAMESPACE = "http://www.w3.org/2000/svg"
function fastIntersect(x,y,nx,ny) {
if (x.getAttribute("id") == y.getAttribute("id")) { // can't collide with itself
return false
}
let spacing = 2 // number of pixels to keep elements apart
nx = nx ? nx : 0
ny = ny ? ny : 0
let a = x.getBoundingClientRect()
let b = y.getBoundingClientRect()
return !(b.left-spacing > (a.right+nx)
|| b.right+spacing < (a.left+nx)
|| b.top-spacing > (a.bottom+ny)
|| b.bottom+spacing < (a.top+ny));
}
function makeWord(word, size) {
let textBox = document.createElementNS(SVG_NAMESPACE, "text");
textBox.setAttribute("font-size", size + "px")
textBox.setAttribute("x", "0")
textBox.setAttribute("y", "40")
textBox.setAttribute("class", "cloudword")
textBox.setAttribute("onclick", "search(\"" + word + "\", 'lte=1M')")
textBox.textContent = word
return textBox
}
async function wordCloud(hash, width, height, obj) {
let total = 0
let boxes = []
let space = width * height
for (let i in hash) {
total += Math.sqrt(hash[i])
}
let hashSorted = []
for (let word in hash) hashSorted.push(word)
hashSorted = hashSorted.sort(function(a,b) { return hash[a] > hash[b] })
let svg = document.createElementNS(SVG_NAMESPACE, "svg");
document.body.appendChild(svg)
svg.setAttribute("width", width)
svg.setAttribute("height", height)
svg.setAttribute("class", "wordcloud")
for (let word of hashSorted) {
let size = 0;
let expected_area = ( Math.sqrt(hash[word]) / total ) * (space*0.9)
//console.log(expected_area)
let textBox = document.createElementNS(SVG_NAMESPACE, "text");
textBox.textContent = word
textBox.setAttribute("font-size", "100px")
svg.appendChild(textBox)
let w = textBox.getBoundingClientRect();
for (let s = 100; s > 0; s-=5) {
let area = w.width * w.height * ( (s/100)*(s/100) );
if (area <= expected_area ) {
size = s;
svg.removeChild(textBox)
break
}
}
let popped = false
// Try with random placement
textBox = makeWord(word, size)
textBox.setAttribute("id", "svg_wc_" + word)
svg.appendChild(textBox)
if (!popped) {
textBox.setAttribute("x", 0)
textBox.setAttribute("y", 0)
for (let ss = size; ss > 5; ss *= 0.9) {
// alert(ss)
if (popped) {
break
}
textBox.setAttribute("font-size", ss + "px")
w = textBox.getBoundingClientRect()
for (let l = 0; l < 80; l++) {
let nx = 4 + (Math.random() * (width-8-w.width))
let ny = 4 + w.height + ((l/80) * (height-8-w.height))
let it = false
for (let box of boxes) {
if (fastIntersect(textBox, box, nx, ny)) {
it = true
break
}
}
if (it == false) {
popped = true
textBox.setAttribute("x", nx)
textBox.setAttribute("y", ny)
break
}
}
}
}
if (popped) {
let color = 'hsl('+ Math.random()*360 +', 40%, 50%)';
textBox.setAttribute("fill", color)
boxes.push(textBox)
} else {
//alert("Could not add " + word)
svg.removeChild(textBox)
}
}
// Try to size up texts a bit
for (let textBox of boxes) {
let osize = parseFloat(textBox.getAttribute('font-size'))
let psize = osize
for (let n = 1; n < 1.4; n+=0.2) {
let nsize = osize * n
textBox.setAttribute("font-size", nsize + "px")
let w = textBox.getBoundingClientRect()
let good = true
for (let box of boxes) {
if (fastIntersect(textBox, box)) {
good = false
break
}
}
if (!good || w.right > width-4 || w.top < 4) {
textBox.setAttribute("font-size", psize + "px")
break
}
psize = nsize
}
}
document.body.removeChild(svg)
console.log("Word Cloud generated");
obj.inject(svg);
}