Skip to content

Instantly share code, notes, and snippets.

@Korko
Created February 7, 2014 11:37
Show Gist options
  • Save Korko/8861193 to your computer and use it in GitHub Desktop.
Save Korko/8861193 to your computer and use it in GitHub Desktop.
Dynamicaly generate a wheel with links in Javascript from a simple list.
/**
* Construct a circle with links all around it.
* @params links Array of links (JSON Objects with params name and link)
* @params r Integer Radius of the circle
* @params thumSize Integer Max width/height for the thumb
* @params fullSize Integer Max width/height for the image in the center
*
* The first element will be on the left and all others will be in clockwise
*/
var linksWheel = function(links, r, thumbSize, fullSize, innerText) {
// Constants
var prefix = 'linkCircle'+Math.round(Math.random()*100);
var angle = 2*Math.PI / links.length;
var content;
/**
* Method to attach the circle to a specific HTMLElement (append)
* @access public
*/
this.attach = function (divId) {
document.getElementById(divId).appendChild(content);
};
/**
* Try to resize the image to a width or height max
* And center it
*/
var resizeAndCenter = function(img, maxSize, carrier) {
if (!carrier) carrier = img;
if (!img.naturalWidth) img.naturalWidth = img.width;
if (!img.naturalHeight) img.naturalHeight = img.height;
var ratio;
if (img.naturalWidth > img.naturalHeight) {
img.style.width = maxSize + 'px';
ratio = maxSize / img.naturalWidth;
img.style.height = Math.round(ratio * img.naturalHeight) + 'px';
} else {
img.style.height = maxSize + 'px';
ratio = maxSize / img.naturalHeight;
img.style.width = Math.round(ratio * img.naturalWidth) + 'px';
}
carrier.style.left = Math.round(parseInt(carrier.style.left) - (ratio * img.naturalWidth)/2) + 'px';
carrier.style.top = Math.round(parseInt(carrier.style.top) - (ratio * img.naturalHeight)/2) + 'px';
};
/**
* Method to generate a link
* @access private
* @params link JSon Object width link informations
* @params i Integer Position of the link in all the others
*/
var generateLink = function(link, i) {
// Create link
var anchor = document.createElement('a');
anchor.setAttribute('href', link.link);
anchor.style.position = 'absolute';
anchor.style.textAlign = 'center';
anchor.style.width = thumbSize+'px';
anchor.style.height = thumbSize+'px';
// Create image (size will be compute after display)
var img = document.createElement('img');
img.setAttribute('src', link.img);
img.style.display = 'block';
img.setAttribute('title', link.name);
// As we need to display it to know the real height,
// add it really high and compute before display
anchor.style.top = -10000 + 'px';
img.onload = function() {
var x = Math.round((r - thumbSize/2) * Math.cos(i * angle));
var y = Math.round((r - thumbSize/2) * Math.sin(i * angle));
// Position Trick: The circle is not positionned in (0;0) but in (-r;-r) (top left) so add r for each coord
// Position Trick: In order to center, add margin
this.parentNode.style.left = x + r + 'px';
this.parentNode.style.top = y + r + 'px';
resizeAndCenter(this, thumbSize, this.parentNode);
};
if (fullSize) {
// On Mouse Over, display in full width the image
anchor.onmouseover = function() {
var div = document.createElement('div');
div.id = prefix + 'over';
div.style.width = fullSize+'px';
div.style.height = fullSize+'px';
div.style.position = 'absolute';
var img = document.createElement('img');
img.setAttribute('src', link.img);
// As we need to display it to know the real height,
// add it really high and compute before display
div.style.top = -10000 + 'px';
img.onload = function() {
this.parentNode.style.top = r + 'px';
this.parentNode.style.left = r + 'px';
resizeAndCenter(this, fullSize, this.parentNode);
};
div.appendChild(img);
content.appendChild(div);
// IE can put in cache img so never call onload.
if (img.complete) {
img.onload();
}
};
// On Mouse Out, remove the full width image
anchor.onmouseout = function() {
var img = document.getElementById(prefix + 'over');
if (img) content.removeChild(img);
};
}
// Add it
anchor.appendChild(img);
return anchor;
};
/**
* Constructor of this object
* @access private
*/
(function constructor(links) {
// Create container
content = document.createElement('div');
content.style.width = 2 * r + 'px';
content.style.height = 2 * r + 'px';
content.style.textAlign = 'center';
content.style.verticalAlign = 'middle';
content.style.lineHeight = 2 * r + 'px';
content.style.fontSize = 60 + 'px';
var text = document.createElement('span');
text.innerText = innerText;
content.appendChild(text);
var i = 0;
for (link in links) {
var anchor = generateLink(links[link], i, angle);
listen(anchor, {
'mouseover': function() {
text.style.display = 'none';
},
'mouseout': function() {
text.style.display = 'inline';
}
});
content.appendChild(anchor);
i++;
}
})(links);
};
function listen(o, events) {
for(var eventName in events) {
(o.addEventListener && o.addEventListener(eventName, events[eventName])) ||
(o.attachEvent && o.attachEvent('on'+eventName, events[eventName]));
}
}
<html>
<head>
<title>linksWheel test</title>
<script type="text/javascript" src="circle.js"></script>
<style type="text/css">
a img {border:none;}
a {outline:none;}
h1 {
text-align: left;
}
#home {
position: absolute;
width: 600px;
height: 600px;
top: 50%;
left: 50%;
margin-left: -300px;
margin-top: -300px;
}
#footer {
position: absolute;
bottom: 10px;
right: 10px;
text-align: right;
width: 100%;
}
</style>
</head>
<body>
<div id="home"></div>
<script type="text/javascript">
new linksWheel([
{ name: 'Lien Test 1', link: 'http://localhost/', img: 'imgurl'},
{ name: 'Lien Test 2', link: 'http://localhost/', img: 'imgurl'},
], 300, 128, 200, 'Korko').attach('home');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment