Created
March 25, 2009 14:18
-
-
Save hisasann/85489 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){ | |
/* | |
* jMerrygoround jQuery Plugin version 1.0 | |
* http://lab.hisasann.com/jmerrygoround/ | |
* | |
* Copyright (c) 2009 hisasann http://hisasann.com/ | |
* Dual licensed under the MIT and GPL licenses. | |
*/ | |
var | |
// 画像ロケーション情報 | |
offset = [], | |
// オプション | |
options = { | |
radiusX: 200, // Radius X point | |
radiusY: 30, // Radius Y point | |
centerX: 250, // Position adjustment left | |
centerY: 100, // Position adjustment top | |
width: 140, // Image height | |
height: 100, // Image width | |
action: "click", // Animation action | |
motion: "normal", // Click action motion | |
duration: 800, // Easing speed | |
easing: "swing", // Animation type | |
nextId: "#next", // Next button element id | |
prevId: "#prev", // Prev button element id | |
targetElem: "img", // Merrygoround target element | |
reflection: false // Reflection flag | |
}, | |
// Merrygoroundさせたいエレメント | |
$imgs, | |
// Merrygoround対象のエレメントを持つ親オブジェクト | |
$this; | |
$.jMerrygoround = function(targetId, opts){ | |
$.extend(options, opts); | |
$imgs = $(targetId).find(options.targetElem); | |
$this = $(targetId); | |
setup(); | |
} | |
$.fn.jMerrygoround = function(opts){ | |
$.extend(options, opts); | |
$imgs = $(this).find(options.targetElem); | |
$this = $(this); | |
setup(); | |
} | |
// Setup!! | |
function setup() { | |
// リフレクション画像の表示枠 | |
if(options.reflection) | |
$this.append("<div id='reflection'></div>"); | |
// フラッシュ | |
(options.targetElem == "img" ? | |
$($imgs).fadeIn(500) : | |
$($imgs).find("img").fadeIn(500)); | |
$($imgs).each(function(index){ | |
// id指定 | |
$(this).attr("id", "img" + index); | |
// 画像のポジションを計算します | |
slider(index, $(this), true, false); | |
// リフレクション画像の作成 | |
createReflector(options.targetElem == "img" ? | |
$(this)[0] : | |
$(this).find("img")[0], $(this).attr("id"), offset[index]); | |
}); | |
// actionに合わせたイベント指定 | |
$.fn.jMerrygoround[options.action](); | |
} | |
var speed = 0; | |
function slider(index, elem, isBuff, isSpeedup){ | |
var numSlots = $($imgs).size(), | |
_a, _t, _l, _s, _h, _w, zindex, opacity; | |
_a = index * ((Math.PI * 2) / numSlots); | |
if(isSpeedup) | |
_a += speed; | |
_t = Math.sin(_a) * options.radiusY + options.centerY; | |
_l = Math.cos(_a) * options.radiusX + options.centerX; | |
_s = (_t / ((options.centerY) + options.radiusY)); | |
_w = elem.width() * (options.width / elem.width()); | |
_h = elem.height() * (options.height / elem.height()); | |
zindex = 2000 + Math.floor(_w * _s); | |
opacity = (Math.floor((_w * _s) / 10) / 10) - 0.2; | |
// 画像ロケーション情報の保存 | |
// actionをclickにした場合に使用 | |
if(isBuff) | |
offset[index] = { | |
top: _t - 70, left: _l, | |
width: _w * _s, height: _h * _s, | |
zIndex: zindex, opacity: opacity | |
} | |
elem.css({ | |
position: "absolute", top: _t - 70, left: _l, | |
width: (_w * _s) + "px", height: (_h * _s) + "px", | |
zIndex: zindex, | |
opacity: opacity | |
}); | |
} | |
// リフレクションしたcanvasを取得 | |
// via http://lab.hisasann.com/reflector/ | |
var _opacity = 0.5, _height = 0.5; | |
function createReflector(elem, id, offset){ | |
if(!options.reflection) | |
return; | |
var reflector; | |
var refHeight = Math.floor(elem.height * _height); | |
var refWidth = elem.width; | |
var canvas = document.createElement("canvas") | |
if(canvas.getContext){ // not IE | |
canvas.id = id + "can"; | |
canvas.style.position = "absolute"; | |
canvas.style.top = offset.top + offset.height - 1 + "px"; | |
canvas.style.left = offset.left + "px"; | |
canvas.style.height = refHeight + "px"; | |
canvas.style.width = refWidth + "px"; | |
canvas.height = refHeight; | |
canvas.width = refWidth; | |
var ctx = canvas.getContext("2d") | |
with(ctx){ | |
save(); | |
translate(0, elem.height); | |
scale(1,-1); | |
drawImage(elem, 0, 0, elem.width, elem.height); | |
restore(); | |
var gradient = createLinearGradient(0, 0, 0, refHeight); | |
gradient.addColorStop(1, "rgba(0, 0, 0, 1)"); | |
gradient.addColorStop(0, "rgba(0, 0, 0, " + _opacity + ")"); | |
globalCompositeOperation = "destination-out"; | |
fillStyle = gradient; | |
fillRect(0, 0, refWidth, refHeight); | |
fill(); | |
} | |
reflector = canvas; | |
}else{ // IE | |
var reflection = document.createElement("img"); | |
reflection.id = id + "can"; | |
with(reflection){ | |
src = elem.src; | |
style.position = "absolute"; | |
style.top = offset.top + offset.height - 1 + "px"; | |
style.left = offset.left + "px"; | |
style.width = refWidth + "px"; | |
style.height = elem.height + "px"; | |
style.display = "block"; | |
style.marginBottom = "-"+(elem.height - refHeight)+"px"; | |
style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+(_opacity*100)+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+(_height*100)+')'; | |
} | |
reflector = reflection; | |
} | |
$(reflector).appendTo("#reflection"); | |
} | |
// auto animation | |
$.fn.jMerrygoround.auto = function() { | |
var interval, | |
width = $this.width() / 2, | |
offsetX = $this.offset().left; | |
interval = setInterval(function(){ | |
$($imgs).each(function(index){ | |
slider(index, $(this), true, true); | |
reflectCSS($(this), offset[index]); | |
}); | |
speed += 0.05; | |
}, 10); | |
} | |
// mouseover animation | |
$.fn.jMerrygoround.mouseover = function() { | |
var interval, | |
width = $this.width() / 2, | |
offsetX = $this.offset().left; | |
$this.mouseover(function(e){ | |
interval = setInterval(function(){ | |
$($imgs).each(function(index){ | |
slider(index, $(this), true, true); | |
reflectCSS($(this), offset[index]); | |
}); | |
speed += ((e.pageX - offsetX) - width) / 1500; | |
}, 10); | |
}); | |
$this.mouseout(function(e){ | |
clearInterval(interval); | |
interval = null; | |
}); | |
} | |
// mousedown animation | |
$.fn.jMerrygoround.mousedown = function() { | |
var interval = null; | |
// next | |
$(options.nextId).mousedown(function(e){ | |
interval = setInterval(function(){ | |
speed += 0.1; | |
$($imgs).each(function(index){ | |
slider(index, $(this), true, true); | |
reflectCSS($(this), offset[index]); | |
}); | |
}, 10); | |
}).mouseup(function(e){ | |
clearInterval(interval); | |
interval = null; | |
}).mouseout(function(e){ | |
clearInterval(interval); | |
interval = null; | |
}); | |
// prev | |
$(options.prevId).mousedown(function(e){ | |
interval = setInterval(function(){ | |
speed -= 0.1; | |
$($imgs).each(function(index){ | |
slider(index, $(this), true, true); | |
reflectCSS($(this), offset[index]); | |
}); | |
}, 10); | |
}).mouseup(function(e){ | |
clearInterval(interval); | |
interval = null; | |
}).mouseout(function(e){ | |
clearInterval(interval); | |
interval = null; | |
}); | |
} | |
// click animation | |
var nowIndex = 0; | |
$.fn.jMerrygoround.click = function(){ | |
// next | |
$(options.nextId).mousedown(function(){ | |
// 一周したら元のインデックスに戻る | |
if(nowIndex >= $($imgs).size()) | |
nowIndex = 1; | |
else | |
nowIndex++; | |
$($imgs).each(function(index) { | |
$.fn.jMerrygoround.click[options.motion]($(this), offset[calcIndex(nowIndex + index)], index); | |
reflectAnime($(this), offset[calcIndex(nowIndex + index)]); | |
}); | |
}); | |
// prev | |
$(options.prevId).click(function(){ | |
// 一周したら元のインデックスに戻る | |
if(nowIndex <= -$($imgs).size()) | |
nowIndex = -1; | |
else | |
nowIndex--; | |
$($imgs).each(function(index) { | |
$.fn.jMerrygoround.click[options.motion]($(this), offset[calcIndex(nowIndex + index)], index); | |
reflectAnime($(this), offset[calcIndex(nowIndex + index)]); | |
}); | |
}); | |
} | |
// click animation - normal | |
$.fn.jMerrygoround.click.normal = function(elem, offset, index){ | |
elem.css({ | |
zIndex: offset.zIndex, | |
opacity: offset.opacity | |
}).animate( | |
{ | |
left: offset.left + 'px', | |
top: offset.top + 'px', | |
width: offset.width + 'px', | |
height: offset.height + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){}} | |
); | |
}; | |
// click animation - spiral | |
$.fn.jMerrygoround.click.spiral = function(elem, offset, index){ | |
elem.animate( | |
{ | |
top: index * offset.height / 4 - options.centerY + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){ | |
setTimeout(function() { | |
elem.css({ | |
zIndex: offset.zIndex, | |
opacity: offset.opacity | |
}).animate( | |
{ | |
left: offset.left + 'px', | |
top: offset.top + 'px', | |
width: offset.width + 'px', | |
height: offset.height + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){}} | |
); | |
}, Math.random() * options.duration); | |
}} | |
); | |
} | |
// click animation - shake | |
$.fn.jMerrygoround.click.shake = function(elem, offset, index){ | |
setTimeout(function() { | |
elem.animate( | |
{ | |
left: Math.sin(index) * options.radiusX + options.centerX + 'px', | |
top: Math.cos(index) * options.radiusY + options.centerY + 'px', | |
opacity: 0.6 | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){ | |
elem.css({ | |
zIndex: offset.zIndex, | |
opacity: offset.opacity | |
}).animate( | |
{ | |
left: offset.left + 'px', | |
top: offset.top + 'px', | |
width: offset.width + 'px', | |
height: offset.height + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){}} | |
); | |
}} | |
); | |
}, Math.random() * options.duration); | |
} | |
// click animation - grow | |
$.fn.jMerrygoround.click.grow = function(elem, offset, index){ | |
elem.animate( | |
{ | |
width: Math.random() * options.width + 'px', | |
height: Math.random() * options.height + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){ | |
elem.css({ | |
zIndex: offset.zIndex, | |
opacity: offset.opacity | |
}).animate( | |
{ | |
left: offset.left + 'px', | |
top: offset.top + 'px', | |
width: offset.width + 'px', | |
height: offset.height + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){}} | |
); | |
}} | |
); | |
} | |
// click animation - delay | |
$.fn.jMerrygoround.click.delay = function(elem, offset, index){ | |
setTimeout(function() { | |
elem.animate( | |
{ | |
left: offset.left + 'px', | |
top: offset.top + 'px', | |
width: offset.width + 'px', | |
height: offset.height + 'px' | |
}, | |
{queue: true, duration: options.duration, easing: options.easing, complete: function(){ | |
$(this).css({ | |
zIndex: offset.zIndex, | |
opacity: offset.opacity | |
}); | |
}} | |
); | |
}, Math.random() * options.duration); | |
} | |
// リフレクション用CSS設定 | |
function reflectCSS(elem, offset) { | |
if(!options.reflection) | |
return; | |
$("#" + elem.attr("id") + "can").css({ | |
left: offset.left + 'px', | |
top: offset.top + offset.height - 1 + 'px', | |
width: offset.width + 'px', | |
height: $.browser.msie ? offset.height : Math.floor(offset.height * _height) + 'px' | |
}); | |
} | |
// リフレクション用アニメーション | |
function reflectAnime(elem, offset) { | |
if(!options.reflection) | |
return; | |
$("#" + elem.attr("id") + "can").animate({ | |
left: offset.left + 'px', | |
top: offset.top + offset.height - 1 + 'px', | |
width: offset.width + 'px', | |
height: $.browser.msie ? offset.height : Math.floor(offset.height * _height) + 'px' | |
}, options.duration, options.easing); | |
} | |
function calcIndex(x){ | |
var ret = 0; | |
if(x < 0) | |
ret = x + offset.length; | |
else if(x >= offset.length) | |
ret = x - offset.length; | |
else | |
ret = x; | |
return ret; | |
} | |
// Thank you enjoy!! | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment