Создание облака тегов на JS
Приветствую, друзья!)
Надо, значится, сделать облако тегов содержащихся в многомерном массиве. Само облако нужно поместить в уже имеющемся контейнере. С размещением тегов из массива в контейнере у меня особых проблем не возникло. Однако не могу приложить ума, как заставить меняться размер шрифта тегов в зависимости от того, сколько каждый из тегов имеет голосов (т.е. надо еще сложить между собой числа в каждом из подмассивов), цвет у тегов должен быть тоже разным. Есть идеи, как можно решить задачу? Заранее спасибо за ответы! Код:
<!DOCTYPE HTML> |
DmitryBelg,
в чём проблема сделать цикл и сложить всё что нужно заранее? |
числа я сложил.
код теперь выглядит вот так: var arrTags = [ ["Javascript", 1634, 987], ["jQuery", 1111, 34], ["PHP", 1024,1122], ["Asp.Net", 977, 1005], ["Photoshop", 594, 789], ["XML", 40, 666], ["Access", 55, 77], ["Java", 278, 277], ["MySQL", 155, 122] ] window.onload = function () { var tagCont = document.getElementById('tagContainer'); for (var i = 0; i < arrTags.length; i++){ arrTags[i][1] = arrTags[i][1]+arrTags[i][2]; console.log(arrTags[i][1]); var eSpan = document.createElement('span'); eSpan.className = "tag"; var x = Math.floor(Math.random()*250); var y = Math.floor(Math.random()*250); eSpan.style.left = x +'px'; eSpan.style.top = y +'px'; eSpan.innerHTML = arrTags[i][0]; tagCont.appendChild(eSpan); } } Но как теперь заставить шрифт подгоняться под полученные значения, я не знаю. |
DmitryBelg,
общую сумму голосов нужно точно? может только первое число? |
DmitryBelg,
в строке 15 отсортируйте массив и потом eSpan.style.fontSize = (12 + i * 2.3) + 'px'; |
А что эти числа означают? За-против? Тогда наверное вычитать нужно а не складывать.
|
DmitryBelg,
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>JS PF taak: TagCloud</title> <style> #tagContainer { position:relative; background-color:#FFE4E1; margin:1em; padding:0; width: 500px; height:400px; overflow:hidden; border:2px solid silver; } span.tag { position:absolute; top:0; left:0; text-shadow: 5px 1px 3px #FFFAFA; font-weight: 400; } </style> <script> var arrTags = [ ["Javascript", 1634, 987], ["jQuery", 1111, 34], ["PHP", 1024, 1122], ["Asp.Net", 977, 1005], ["Photoshop", 594, 789], ["XML", 40, 666], ["Access", 55, 77], ["Java", 278, 277], ["MySQL", 155, 122] ]; window.onload = function() { var tagCont = document.getElementById("tagContainer"); function sum(el) { return el[1] + el[2] } var obj = arrTags.reduce(function(a, b) { b = sum(b); if (a.min > b) a.min = b; if (a.max < b) a.max = b; return a }, { max: sum(arrTags[0]), min: sum(arrTags[0]) }); for (var i = 0; i < arrTags.length; i++) { var eSpan = document.createElement("span"); eSpan.className = "tag"; var font = 12 + 52 * (arrTags[i][1] - obj.min) / (obj.max - obj.min); var x = Math.floor(Math.random() * 250); var y = Math.floor(Math.random() * 250); eSpan.style.fontSize = font + "px"; eSpan.style.left = x + "px"; eSpan.style.top = y + "px"; eSpan.style.color = "#" + ("000000" + (Math.random() * 16777215 | 0).toString(16)).slice(-6); eSpan.innerHTML = arrTags[i][0]; tagCont.appendChild(eSpan) } }; </script> </head> <body> <div id="tagContainer"></div> </body> </html> |
Цитата:
|
воууу)) блин) я аж подавился, когда увидел результат) Сейчас буду вникать.
Спасибо в очередной раз тебе и все остальным, кто не прошел мимо) |
DmitryBelg,
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>JS PF taak: TagCloud</title> <style> #tagContainer { position:relative; background-color:#FFE4E1; margin:1em; padding:0; width: 500px; height:400px; overflow:hidden; border:2px solid silver; } span.tag { position:absolute; top:0; left:0; text-shadow: 5px 1px 3px #FFFAFA; font-weight: 400; } </style> <script> var arrTags = [ ["Javascript", 1634, 987], ["jQuery", 1111, 34], ["PHP", 1024, 1122], ["Asp.Net", 977, 1005], ["Photoshop", 594, 789], ["XML", 40, 666], ["Access", 55, 77], ["Java", 278, 277], ["MySQL", 155, 122] ]; window.onload = function() { var tagCont = document.getElementById("tagContainer"); function sum(el) { return el[1] + el[2] } arrTags.sort(function(a, b) { return sum(a) - sum(b) }); for (var i = 0; i < arrTags.length; i++) { var eSpan = document.createElement("span"); eSpan.className = "tag"; var font = 12 + (i * i); var x = Math.floor(Math.random() * 250); var y = Math.floor(Math.random() * 250); eSpan.style.fontSize = font + "px"; eSpan.style.left = x + "px"; eSpan.style.top = y + "px"; eSpan.style.color = "#" + ("000000" + (Math.random() * 16777215 | 0).toString(16)).slice(-6); eSpan.innerHTML = arrTags[i][0]; tagCont.appendChild(eSpan) } }; </script> </head> <body> <div id="tagContainer"></div> </body> </html> |
Цитата:
|
Для того, чтобы слова не обрезались и не скучивались где-то в уголке, можно использовать такой приём: пусть центр каждого тега не появляется в 25% (от ширины/высоты) от края.
Цвета генерировать можно, например, на основе оттенка H в модели HSL зависящего от популярности тега. (т. е. яркость и насыщенность остаются равномерными) Менее популярные теги сложно прочитать, поскольку они очень мелкие. Я думаю, что популярность тега можно выразить не через размер, а через жирность начертания шрифта. Тогда размер, например, может колебаться от 1.5em до 4em (что подходит для чтения). А для подчёркивания популярности использовать жирность шрифта (font weight, обозначается как "wght") от 100 до 900, что даёт более широкий набор возможностей, какие стили применить. (Например, более жирный текст отбрасывает более крупную тень, которую, если подкрасить, можно в данном случае воспринять так, что более популярные теги ярче светятся) P. S. Для примера я использовал шрифт https://v-fonts.com/fonts/ff-meta-variable, я подключил его через CORS Proxy, чтобы были правильные заголовки, вы же можете скачать его к себе, или какой-либо другой переменный шрифт. Обратите внимание, что это должен быть именно переменный шрифт, только тогда дробные жирности будут работать. Если вам интересна эта тема, можете посмотреть, что вообще возможно при помощи переменных шрифтов https://v-fonts.com/ Я использовал проценты, так что #tagContainer может быть любого размера. <!DOCTYPE html> <html> <head> <title></title> <style> @font-face { src: url("https://cors-anywhere.herokuapp.com/https://v-fonts.com/assets/fonts/MetaVariableDemo-Set.woff2"); font-family: "FF Meta Variable"; font-style: normal; } body { margin: 0; } #tagContainer { position: relative; width: 100vw; height: 100vh; font-family: "FF Meta Variable"; overflow: hidden; margin: 0; background-color: black; text-shadow: 0 0 2em; } #tagContainer > * { position: absolute; mix-blend-mode: difference; mix-blend-mode: screen; transform: translate(-50%, -50%); } </style> <script> addEventListener("load", event => { var cloudElement = document.getElementById("tagContainer"); var tags = [ ["Javascript", 1634, 987], ["jQuery", 1111, 34], ["PHP", 1024, 1122], ["Asp.Net", 977, 1005], ["Photoshop", 594, 789], ["XML", 40, 666], ["Access", 55, 77], ["Java", 278, 277], ["MySQL", 155, 122] ]; const { min, max } = tags.reduce(({ min, max }, [, ...v]) => { const total = v.reduce((a, b) => a + b, 0); return { min: Math.min(min, total), max: Math.max(max, total) } }, { min: Infinity, max: -Infinity }); tags.forEach(([tag, ...v]) => { const total = v.reduce((a, b) => a + b, 0); const p = (total - min) / (max - min); const element = document.createElement("span"); element.style.cssText = ` font-variation-settings: "wght" ${100 + 800 * p}; font-size: ${1.5 + 2.5 * p}em; color: hsl(${180 + 960 * p}, 100%, 50%); top: ${25 + 50 * Math.random()}%; left: ${25 + 50 * Math.random()}%; `; element.textContent = tag; cloudElement.append(element); }) }); </script> </head> <body> <div id="tagContainer"></div> </body> </html> |
Malleys,
как всегда спасибо, но смущает инциализация min max (строка 58) и вычисление p строка 62. мне видится более точное вычисление этих параметров в посте №7 |
Ну да точно, конечно же нужно const p = (total - min) / (max - min), а не const p = total / (max - min) линейная интерполяция. Спасибо, что так внимательно посмотрели!
|
Часовой пояс GMT +3, время: 09:39. |