Задать вопрос
@EvgenyKabakov

Как сверстать блок облако тегов?

Всем доброго времени суток! Прошу подсказать, каким образом можно сверстать подобное дизайнерское решение?
Так называемое "облако тегов". По задумке, блок должен реагировать на наведение мыши, теги должны немного двигаться в стороны относительно своего текущего расположения. Плюс нужна анимация наведения мыши на конкретный тег - чтобы он становился больше. Какие есть варианты закодить такой блок? Может быть, какую-то библиотеку использовать можно?
6564fc413d21e692004771.jpeg
  • Вопрос задан
  • 509 просмотров
Подписаться 4 Средний 3 комментария
Решения вопроса 1
1/ а зачем - не очень удобно искать без иерархии и сортировки
2/ готовые решения - например, Tag cloud generator и т.д.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@UthvfyV
<script>var radius = 120;
var dtr = Math.PI/180;
var d=300;
 
var mcList = [];
var active = false;
var lasta = 1;
var lastb = 1;
var distr = true;
var tspeed=10;
var size=250;
 
var mouseX=0;
var mouseY=0;
 
var howElliptical=1;
 
var aA=null;
var oDiv=null;
 
window.onload=function ()
{
	var i=0;
	var oTag=null;
	
	oDiv=document.getElementById('div1');
	
	aA=oDiv.getElementsByTagName('a');
	
	for(i=0;i<aA.length;i++)
	{
		oTag={};
		
		oTag.offsetWidth=aA[i].offsetWidth;
		oTag.offsetHeight=aA[i].offsetHeight;
		
		mcList.push(oTag);
	}
	
	sineCosine( 0,0,0 );
	
	positionAll();
	
	oDiv.onmouseover=function ()
	{
		active=true;
	};
	
	oDiv.onmouseout=function ()
	{
		active=false;
	};
	
	oDiv.onmousemove=function (ev)
	{
		var oEvent=window.event || ev;
		
		mouseX=oEvent.clientX-(oDiv.offsetLeft+oDiv.offsetWidth/2);
		mouseY=oEvent.clientY-(oDiv.offsetTop+oDiv.offsetHeight/2);
		
		mouseX/=5;
		mouseY/=5;
	};
	
	setInterval(update, 30);
};
 
function update()
{
	var a;
	var b;
	
	if(active)
	{
		a = (-Math.min( Math.max( -mouseY, -size ), size ) / radius ) * tspeed;
		b = (Math.min( Math.max( -mouseX, -size ), size ) / radius ) * tspeed;
	}
	else
	{
		a = lasta * 0.98;
		b = lastb * 0.98;
	}
	
	lasta=a;
	lastb=b;
	
	if(Math.abs(a)<=0.01 && Math.abs(b)<=0.01)
	{
		return;
	}
	
	var c=0;
	sineCosine(a,b,c);
	for(var j=0;j<mcList.length;j++)
	{
		var rx1=mcList[j].cx;
		var ry1=mcList[j].cy*ca+mcList[j].cz*(-sa);
		var rz1=mcList[j].cy*sa+mcList[j].cz*ca;
		
		var rx2=rx1*cb+rz1*sb;
		var ry2=ry1;
		var rz2=rx1*(-sb)+rz1*cb;
		
		var rx3=rx2*cc+ry2*(-sc);
		var ry3=rx2*sc+ry2*cc;
		var rz3=rz2;
		
		mcList[j].cx=rx3;
		mcList[j].cy=ry3;
		mcList[j].cz=rz3;
		
		per=d/(d+rz3);
		
		mcList[j].x=(howElliptical*rx3*per)-(howElliptical*2);
		mcList[j].y=ry3*per;
		mcList[j].scale=per;
		mcList[j].alpha=per;
		
		mcList[j].alpha=(mcList[j].alpha-0.6)*(10/6);
	}
	
	doPosition();
	depthSort();
}
 
function depthSort()
{
	var i=0;
	var aTmp=[];
	
	for(i=0;i<aA.length;i++)
	{
		aTmp.push(aA[i]);
	}
	
	aTmp.sort
	(
		function (vItem1, vItem2)
		{
			if(vItem1.cz>vItem2.cz)
			{
				return -1;
			}
			else if(vItem1.cz<vItem2.cz)
			{
				return 1;
			}
			else
			{
				return 0;
			}
		}
	);
	
	for(i=0;i<aTmp.length;i++)
	{
		aTmp[i].style.zIndex=i;
	}
}
 
function positionAll()
{
	var phi=0;
	var theta=0;
	var max=mcList.length;
	var i=0;
	
	var aTmp=[];
	var oFragment=document.createDocumentFragment();
	
	// Случайная сортировка
	for(i=0;i<aA.length;i++)
	{
		aTmp.push(aA[i]);
	}
	
	aTmp.sort
	(
		function ()
		{
			return Math.random()<0.5?1:-1;
		}
	);
	
	for(i=0;i<aTmp.length;i++)
	{
		oFragment.appendChild(aTmp[i]);
	}
	
	oDiv.appendChild(oFragment);
	
	for( var i=1; i<max+1; i++){
		if( distr )
		{
			phi = Math.acos(-1+(2*i-1)/max);
			theta = Math.sqrt(max*Math.PI)*phi;
		}
		else
		{
			phi = Math.random()*(Math.PI);
			theta = Math.random()*(2*Math.PI);
		}
		 // Преобразование координат
		mcList[i-1].cx = radius * Math.cos(theta)*Math.sin(phi);
		mcList[i-1].cy = radius * Math.sin(theta)*Math.sin(phi);
		mcList[i-1].cz = radius * Math.cos(phi);
		
		aA[i-1].style.left=mcList[i-1].cx+oDiv.offsetWidth/2-mcList[i-1].offsetWidth/2+'px';
		aA[i-1].style.top=mcList[i-1].cy+oDiv.offsetHeight/2-mcList[i-1].offsetHeight/2+'px';
	}
}
 
function doPosition()
{
	var l=oDiv.offsetWidth/2;
	var t=oDiv.offsetHeight/2;
	for(var i=0;i<mcList.length;i++)
	{
		aA[i].style.left=mcList[i].cx+l-mcList[i].offsetWidth/2+'px';
		aA[i].style.top=mcList[i].cy+t-mcList[i].offsetHeight/2+'px';
		
		aA[i].style.fontSize=Math.ceil(12*mcList[i].scale/2)+8+'px';
		
		aA[i].style.filter="alpha(opacity="+100*mcList[i].alpha+")";
		aA[i].style.opacity=mcList[i].alpha;
	}
}
 
function sineCosine( a, b, c)
{
	sa = Math.sin(a * dtr);
	ca = Math.cos(a * dtr);
	sb = Math.sin(b * dtr);
	cb = Math.cos(b * dtr);
	sc = Math.sin(c * dtr);
	cc = Math.cos(c * dtr);
}</script>

<style>#div1 {
	position:relative;
	width:450px;
	height:450px;
	margin: 20px auto 0;
}
#div1 a {
	position:absolute;
	top:0px;
	left:0px;
	font-family: Microsoft YaHei;
	color:#fff; 
	font-weight:bold;
	text-decoration:none;
	padding: 3px 6px;
}
#div1 a:hover {
	border: 1px solid #eee;
	background: #000;
}
#div1 .blue {
	color:blue;
}
#div1 .red {
	color:red;
}
#div1 .yellow {
	color:yellow;
}
 
p {
	font: 16px Microsoft YaHei;
	text-align: center;
	color: #ba0c0c;
}
p a {
	font-size: 14px;
	color: #ba0c0c;
}
p a:hover {
	color: red;
}</style>

<div id="div1">
	 <a href=""> Пример 1 </a>
	 <a href="" class="red"> Пример два </a>
	 <a href=""> Пример три </a>
	 <a href=""> Пример </a>
	 <a href="" class="blue"> Пример </a>
	 <a href=""> Пример </a>
	 <a href="" class="red"> Пример </a>
	 <a href="" class="yellow"> Пример </a>
	 <a href=""> Пример </a>
	 <a href="" class="red"> Пример </a>
	 <a href=""> Пример </a>
	 <a href="" class="blue"> Пример </a>
	 <a href=""> Пример </a>
	 <a href="" class="red"> Пример </a>
	 <a href="" class="blue"> Пример </a>
	 <a href=""> Пример </a>
	 <a href="" class="blue"> Пример </a>
	 <a href=""> Пример </a>
	 <a href=""> Пример </a>
	 <a href="" class="yellow"> Пример </a>
	 <a href=""> Пример </a>
</div>
Ответ написан
Комментировать
@subbaka
Приветствую! Скажите пожалуйста, удалось найти решение? Тоже есть потребность. Как я понял ранее таких штук на java было пруд пруди, сейчас не могу найти.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
Rocket Смоленск
от 80 000 до 130 000 ₽
div. Ставрополь
от 40 000 до 90 000 ₽
Wanted. Санкт-Петербург
До 220 000 ₽