这是一款基于HTML5的焦点图动画,它和其他焦点图不同的地方在于,它播放的不仅仅是图片,而是可以自定义控制的网页元素。它不仅在图片间切换有过渡动画效果,而且在切换时图片中的元素也将出现动画效果,比如图中的文字移动、打散、重新组合等。这款HTML5动画图片播放器算得上是高端大气上档次。
在线演示 这里列出的是这个焦点图相关的核心CSS代码。 下面是这个焦点图插件的代码。 下面是页面调用的JS代码: 本文链接:http://www.codeceo.com/article/html5-element-image-player.htmlCSS代码:
.slider section {display: none;}.slider section.first {display: block;}.slider-sections, .slider-sections section {width: 861px; height: 335px;}.slider-sections {margin: 0 auto; position: relative;}.slider-sections section {position: absolute; top: 0; left: 0px; }.header-content h2 { font:400 32px/1.2 "microsoft yahei", Tahoma, arial, sans-serif; color: #fff; margin: 0 0 26px;
}.header-content p { margin: 0 0 30px;
}.header-content .centered-content{ padding-top: 30px; padding-bottom: 10px;
}.button { float: left; width: auto !important; list-style: none;
} .button a, .button button, .button input { /* Standard black button */
font-size: 15px; /*font-family: 'lucida sans',arial,helvetica,sans-serif;*/
line-height: 18px; color: #fff !important; text-decoration: none; padding: 5px 14px 6px 13px; display: block; width: auto; position: relative; z-index: 2; border: none; -moz-border-radius: 3px; border-radius: 3px; cursor: pointer; background: #313131; /* Old browsers */
background: -moz-linear-gradient(top, #313131 0%, #222222 100%); /* FF3.6+ */
background: -webkit-linear-gradient(top, #313131 0%,#222222 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #313131 0%,#222222 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #313131 0%,#222222 100%); /* IE10+ */
background: linear-gradient(top, #313131 0%,#222222 100%); /* W3C */
-webkit-transition: all 0.3s ease; -moz-transition: all 0.3s ease; -o-transition: all 0.3s ease; transition: all 0.3s ease;
} .button a:hover, .button input:hover, .button button:hover, .button a:focus, .button input:focus, .button button:focus
{ background: #464646; /* Old browsers */
background: -moz-linear-gradient(top, #464646 0%, #393939 100%); /* FF3.6+ */
background: -webkit-linear-gradient(top, #464646 0%,#393939 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #464646 0%,#393939 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #464646 0%,#393939 100%); /* IE10+ */
background: linear-gradient(top, #464646 0%,#393939 100%); /* W3C */
} header .header-content .button a, #content .button a:hover
{ text-decoration: none;
}.header-content .beta-ribbons { position: absolute;
height: 120px; width: 85px; text-indent: -200px; overflow: hidden; background: url(../images/kendo-ribbons.png) no-repeat 0 0;
}.header-content .beta-ribbons.ribbon-1 { background-position: -170px 0; top: -3px; right: -145px;
}.header-content p.copy .beta-ribbons.ribbon-1 { top: -135px; left: 900px;
}.header-content .beta-ribbons.ribbon-4 { background-position: -255px 0; left: -62px; top: -30px; z-index: 10; text-indent: -2000px;
}
JavaScript代码:
/**
* @author Alexander Farkas
* v. 1.22
*/(function ($){ if (!document.defaultView || !document.defaultView.getComputedStyle)
{ // IE6-IE8
var oldCurCSS = $.curCSS;
$.curCSS = function (elem, name, force) { if (name === 'background-position')
{
name = 'backgroundPosition';
} if (name !== 'backgroundPosition' || !elem.currentStyle || elem.currentStyle[name])
{ return oldCurCSS.apply(this, arguments);
} var style = elem.style; if (!force && style && style[name])
{ return style[name];
} return oldCurCSS(elem, 'backgroundPositionX', force) + ' ' + oldCurCSS(elem, 'backgroundPositionY', force);
};
} var oldAnim = $.fn.animate;
$.fn.animate = function (prop) { if ('background-position' in prop)
{
prop.backgroundPosition = prop['background-position']; delete prop['background-position'];
} if ('backgroundPosition' in prop)
{
prop.backgroundPosition = '(' + prop.backgroundPosition;
} return oldAnim.apply(this, arguments);
}; function toArray(strg) {
strg = strg.replace(/left|top/g, '0px');
strg = strg.replace(/right|bottom/g, '100%');
strg = strg.replace(/([0-9\.]+)(\s|\)|$)/g, "$1px$2"); var res = strg.match(/(-?[0-9\.]+)(px|\%|em|pt)\s(-?[0-9\.]+)(px|\%|em|pt)/); return [parseFloat(res[1], 10), res[2], parseFloat(res[3], 10), res[3]];
}
$.fx.step.backgroundPosition = function (fx) { if (!fx.bgPosReady)
{ var start = $.curCSS(fx.elem, 'backgroundPosition'); if (!start)
{//FF2 no inline-style fallback
start = '0px 0px';
}
start = toArray(start);
fx.start = [start[0], start[2]]; var end = toArray(fx.end);
fx.end = [end[0], end[2]];
fx.unit = [end[1], end[3]];
fx.bgPosReady = true;
} //return;
var nowPosX = [];
nowPosX[0] = ((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0] + fx.unit[0];
nowPosX[1] = ((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1] + fx.unit[1];
fx.elem.style.backgroundPosition = nowPosX[0] + ' ' + nowPosX[1];
};
})(jQuery);/*
tlrkSlider
example usage:
$("#slider").tlrkSlider({
autoStart: false,
elements: {
"img": {delay: 10},
"h2": {delay: 500},
".copy": {delay: 800},
".button": {delay: 1000}
}
});
to go to a specific frame:
$("#slider").tlrkSlider("go", position);
"position" can have one of the following values:
"next", "prev", "first", "last", "+1", "-1" or a numeric value
to start/stop the automatic loop:
$("#slider").tlrkSlider("start");
$("#slider").tlrkSlider("stop");
to change the delay between automatic transitions:
$("#slider").tlrkSlider("option", "delayAnimation", 1000);
to change any option:
$("#slider").tlrkSlider("option", option_name, option_value);
Changing the "elements" object is not tested.
Changing the following options: "navigation", "navigationClass", "framesSelector", "autoStart" won't have any effect for now.
They are used only during the initialization.
$("#slider").data("tlrkSlider") will return the plugin instance and the methods/properties can be accessed from there.
The plugin contructor defaults are accessable through TlrkSlider.defaults
The function that actually sweep the elements in/out can be overriden from
TlrkSlider.prototype._animationIn and TlrkSlider.prototype._animationOut
See sweepIn/sweepOut
*/;(function( $, window, document, undefined ){ // utility function that generates the "dots" navigation
function generateNavigation($el, count, config) { var i, html = "",
width = count * 24;
html += "<ol class='" + config.navigationClass + "' style='margin-left: -" + width/2 + "px; width: " + width + "px'>"; for (i = 0; i < count; i++) {
html += "<li><a " + (i === 0 ? "class='selected'" : "" ) + " href='#" + (i) + "'>slide</a></li>";
}
html += "</ol>";
$el.append(html);
} function sweepOut($el, windowWidth) { var dfr = $.Deferred(),
pos = $el.position(),
width = $el.width(),
delta, final,
options = $el.data("tlrkAnimOptions");
windowWidth = windowWidth || $(window).width(); // check if the windowWidth is passed, if not - get it
delta = windowWidth - pos.left;
final = -(delta);
setTimeout(function(){
$el.animate({left: final, opacity: "toggle"}, options.speed, options.easing, function(){
dfr.resolve();
});
}, options.delay); return dfr.promise();
} function sweepIn($el, windowWidth, frameLeft) { var dfr = $.Deferred(),
options = $el.data("tlrkAnimOptions"),
positionData = $el.data("tlrkOriginalPos"),
final = positionData.position.left,
rightEdge;
windowWidth = windowWidth || $(window).width(); // check if the windowWidth is passed, if not - get it
$el.css({opacity: 0, display: "block"}); // move it outside the right edge of the screen
$el.css("left", function(current){ return current + windowWidth - frameLeft;
});
setTimeout(function(){
$el.animate({left: final, opacity: 1}, options.speed, options.easing, function(){
dfr.resolve();
});
}, options.delay); return dfr.promise();
} // two pass function that first iterates all the elements and gets their position/width/height
// and then sets their position to absolute
function absolutize($elements) { // todo - move it to separate function and do it just once
// gather the original position/dimension data for all elements
$elements.each(function(){ var $t = $(this); if ($t.data("tlrkOriginalPos")) return
$t.data("tlrkOriginalPos", {
position: $t.position(),
width: $t.width(),
height: $t.height(),
css_pos: $t.css("position"),
css_left: $t.css("left"),
css_top: $t.css("top"),
css_width: $t.css("width") || "auto",
css_height: $t.css("height") || "auto"
});
}); // set the absolute position
$elements.each(function(){ var $t = $(this),
opos = $t.data("tlrkOriginalPos");
$t.css({
position: "absolute",
left: opos.position.left,
top: opos.position.top,
width: opos.width,
height: opos.height
});
});
} function restoreFrameElements($elements) {
$elements.each(function(){ var $t = $(this),
opos = $t.data("tlrkOriginalPos"); if (!opos) return
$t.css({
position: opos.css_pos,
left: opos.css_left,
top: opos.css_top,
width: opos.css_width,
height: opos.css_height
});
});
} var TlrkSlider = function( elem, options ){ this.elem = elem; this.$elem = $(elem); this.options = options;
}; // the plugin prototype
TlrkSlider.prototype = {
defaults: {
defaultElementOptions: {
speed: 1200,
easing: "easeInOutBack", // interval before the element starts moving when the fadeIn/Out functions are called
// it's a good idea to give different delays for the different elements
// if all have the same delay they'll start moving all together
delay: 100
}, // dispose elements are these that are not included in the elements object
// but affect the document flow and will be fadedIn/Out
disposeDelay: 100, // delay for the dispose elements
disposeSpeed: 1000, // how quickly they'll fadeOut/In
delayBetweenTransition: 1000, // time between starting fadeOut and fadeIn
delayAnimation: 7000, // time between auto changing the current frame
loop: true, // if true when clicking next on the last frame the slider jumps to the first one
autoStart: true, // start the automatic looping through the frames on init
framesSelector: "section", // selector for the frames inside the slider
elements: { "p": {delay: 100, speed: 1000, easing: "easeInOutBack"}
},
navigation: true, // the dots navigation on the bottom
navigationClass: "slider-nav", // callbacks
// another way to "catch" these events is with
// $(-slider-element-).bind("animationStart")
animationStart: null,
animationEnd: null
},
init: function() { var c, e, element, $element,
that = this,
$firstFrame;
c = this.config = $.extend({}, this.defaults, this.options); this.elem.style.position = "relative"; // make the wrapping element relative
// basics
this.$frames = this.$elem.find(c.framesSelector); this.framesCount = this.$frames.length; this.currentFrame = 0; this.queue = []; this._$elementsByFrame = {}; this._$disposeElementsByFrame = {}; for (i = 0; i < this.framesCount; i++) { this._$elementsByFrame[i] = this._getFrameElements(i); // cache the $elements by frame
this._$disposeElementsByFrame[i] = this._getDisposeFrameElements(i); // cache the rest of the tree for each frame
} if (c.navigation) {
generateNavigation(this.$elem, this.framesCount, c); this.$navigation = this.$elem.find("."+c.navigationClass);
} // bindings
this.$elem.find(".slider-nav").delegate("a", "click", function(e){ var frame = this.getAttribute("href").split("#")[1];
that.go.call(that, frame); return false;
}); this.$elem // internal bindings for the callbacks
.bind("animationStart", function(){ if ($.isFunction(c.animationStart)) {c.animationStart.apply(that, arguments);}
})
.bind("animationEnd", function(){ if ($.isFunction(c.animationEnd)) {c.animationEnd.apply(that, arguments);}
})
; // start animation?
if (c.autoStart) { this.start();
} else { this.running = false;
} return this;
},
start: function(instant) { var that = this; if (this.timer) { // we'll clear the current timer
window.clearTimeout(this.timer);
} this.running = true; if (instant) {
that.nextFrame();
} else { this.timer = window.setTimeout(function(){ that.nextFrame.call(that) }, that.config.delayAnimation);
}
},
stop: function() { if (!this.running) return; // we are not running
this.running = false; window.clearTimeout(this.timer);
}, // main function for changing frames
selectFrame: function(frame, dfr) { var c = this.config, // shorthand for the config
that = this,
dfr = dfr || $.Deferred(),
dFadeIn = $.Deferred(),
dFadeOut = $.Deferred(); if (isNaN(frame) || frame < 0 || frame > this.framesCount || frame === this.currentFrame) {
dfr.reject(); return dfr.promise();
} // clear the animation loop interval if the animation is running
if (this.running && this.timer) {
window.clearTimeout(this.timer);
} // check if we are currenly running an animation.
if (this.animated && this.queue.length > 0) { // wait for the last item in the queue to finish
this.queue[this.queue.length-1].done(function(){
that.selectFrame(frame, dfr); // and call again the selectFrame
}) return dfr.promise();
} this.animated = true; this.$elem.trigger("animationStart", [this, frame]); this.queue.push(dfr); // fade the frames
dFadeOut = this._fadeOutFrame(this.currentFrame); // hide the fadetout frame
dFadeOut.done(function(){
that.$frames.eq(that.currentFrame).hide();
}); window.setTimeout(function(){ // then wait delayBetweenTransition and fadeIn the new frame
dFadeIn = that._fadeInFrame.call(that, frame).done(function(){ // when both the fadeIn and fadeOut are done we'll resolve the selectFrame promise
$.when(dFadeOut, dFadeIn).done(function(){
that.animated = false;
that.queue.shift();
that.$elem.trigger("animationEnd", [that]);
that.currentFrame = frame;
dfr.resolve();
});
});
}, c.delayBetweenTransition); // navigation html change
if (this.config.navigation) { this.$navigation.find(".selected").removeClass("selected").end()
.find("a").eq(frame).addClass("selected");
}
dfr.done(function(){ // we'll resume the loop animation after the transitions are done
if (that.running) {
that.start();
}
}); return dfr.promise();
},
_fadeFrame: function(frame, callback, direction) { var dfr = $.Deferred(),
$frame = this.$frames.eq(frame),
$elements = this._$elementsByFrame[frame],
windowWidth = $(window).width(), // cache it before the animations, so we don't have to check it for each element
i, len,
that = this,
elementAnimations = [],
$disposeElements = this._$disposeElementsByFrame[frame],
$affectedElements,
frameLeft = $frame.offset().left;
direction = direction || "out"; if (!$.isFunction(callback)) return; // do nothing if there's no callback passed
$affectedElements = $elements.add($disposeElements); // position absolute the animation and dispose elements
absolutize($affectedElements); // toggle the dispose elements
if ($disposeElements.length > 0) { window.setTimeout(function(){
$disposeElements[direction === "out" ? "fadeOut" : "fadeIn"](that.config.disposeSpeed);
}, this.config.disposeDelay);
} // invoke the callback for each element
// the callback must return a promise
$elements.each(function(){
elementAnimations.push( callback.call(that, $(this), windowWidth, frameLeft) );
}); // wait for all the elements to finish their animation
$.when.apply(this, elementAnimations).done(function(){ //restoreFrameElements($affectedElements); // and restore the elements' position
dfr.resolve(); // resolve the fade function
}); return dfr.promise();
},
_fadeOutFrame: function(frame) { var dfr = $.Deferred(),
$frame = this.$frames.eq(frame),
$disposeElements = this._$disposeElementsByFrame[frame]; this._fadeFrame(frame, this._animationOut, "out").done(function(){
dfr.resolve();
}) return dfr.promise();
},
_fadeInFrame: function(frame) { var dfr = $.Deferred(),
$frame = this.$frames.eq(frame),
$elements = this._$elementsByFrame[frame]; this._restoreFrame(frame);
$frame.show(); this._fadeFrame(frame, this._animationIn, "in").done(function(){
dfr.resolve();
}); return dfr.promise();
},
_restoreFrame: function(frame){ if (!frame) return
restoreFrameElements( this._$elementsByFrame[frame].add(this._$disposeElementsByFrame[frame]) );
},
nextFrame: function() { var frame = this.currentFrame+1,
dfr = $.Deferred(); if (frame > this.framesCount-1) { if (this.config.loop) {
frame = 0;
} else {
dfr.reject();
}
}; this.selectFrame(frame).done(function(){
dfr.resolve();
}); return dfr.promise();
},
prevFrame: function() { var frame = this.currentFrame-1,
dfr = $.Deferred(); if (frame < 0) { if (this.config.loop) {
frame = this.framesCount-1;
} else {
dfr.reject(); return dfr.promise();
}
} this.selectFrame(frame).done(function(){
dfr.resolve();
}); return dfr.promise();
},
go: function(str) { // shorthand
switch (str) { case "next": case "+1": this.nextFrame(); break; case "prev": case "-1": this.prevFrame(); break; case "first": this.selectFrame(0); break; case "last": this.selectFrame(this.framesCount-1); break; default: if (isNaN(str)) return; this.selectFrame(Number(str));
}
}, // returns jquery collection of animation elements
_getFrameElements: function(frame) {
var $frame = this.$frames.eq(frame),
elements = this.config.elements,
e, elementOptions,
$found, $frameElements = $([]); for (e in elements) {
elementOptions = elements[e];
$found = $frame.find(e);
$found.addClass("t-frame-element").data("tlrkAnimOptions", $.extend({}, this.defaults.defaultElementOptions, elementOptions ));
$frameElements = $frameElements.add($found);
} return $frameElements;
}, // returns jquery collection of elements that have to be faded out
// i.e. elements on the same level as the animation elements
// that doesn't contain other animation elements
_getDisposeFrameElements: function(frame) { var $disposeElements = $([]),
$frame = this.$frames.eq(frame),
$elements = this._$elementsByFrame[frame];
$elements.each(function(){ var $t = $(this),
$siblings = $t.siblings().not(".t-frame-element");
$siblings.each(function(){ var $t = $(this); // check if the node is not already marked and doesn't contains other frame elements
if (!$t.hasClass("t-frame-dispose") && $t.find(".t-frame-element").length === 0) {
$t.addClass("t-frame-dispose");
$disposeElements = $disposeElements.add($t);
}
});
}); return $disposeElements;
}, // expose the internal animationIn/Out functions that are called for each element in the frame
// two arguments are passed - the $element which have to be animated and the window width
_animationIn: sweepIn,
_animationOut: sweepOut
}
TlrkSlider.defaults = TlrkSlider.prototype.defaults;
$.fn.tlrkSlider = function(options) { var otherArgs = Array.prototype.slice.call(arguments, 1); return this.each(function() { var $el = $(this),
pluginData = $el.data("tlrkSlider"); if (!pluginData) { // check if the slider is already attached
pluginData = new TlrkSlider(this, options).init();
$el.data("tlrkSlider", pluginData); return;
} //change the options or call a method
if (typeof options === "string") { // setting / getting option(s)
if (options === "option") { if (typeof otherArgs[0] === "string" && typeof otherArgs[1] !== "undefined") { // set an option value
pluginData.config[otherArgs[0]] = otherArgs[1];
} if (typeof otherArgs[0] === "object") { // extend the config with new options
pluginData.config = $.extend(pluginData.config, otherArgs[0]);
}
} else { // call a method?
try {
pluginData[options].apply(pluginData, otherArgs);
} catch(ex) { throw "Error calling a plugin method (" + ex + ")";
}
}
}
});
}; window.TlrkSlider = TlrkSlider;
})( jQuery, window , document );
$(document).ready(function(){ var $backgrounds = $(".header-content").find(".parallax-bg"),
LAYER_OFFSET = 30,
PRLX_SPEED = 1500,
$slider;
$slider = $("#slider").tlrkSlider({
autoStart: true,
animationStart: function(ev, slider, step){ var max_steps = this.framesCount;
$backgrounds.each(function(idx, el){ var pos = (step * (100 / max_steps)) + (LAYER_OFFSET * idx);
$(this).animate({"backgroundPosition": pos + "% 0"}, PRLX_SPEED);
});
},
elements: { "img": {delay: 10}, "h2": {delay: 500}, ".copy": {delay: 800}, ".button": {delay: 1000}
}
});
$(".header-content")
.hover( function(){$(this).find(".slider-prev, .slider-next").show();}, function(){$(this).find(".slider-prev, .slider-next").hide();}
)
.find(".slider-prev").click(function(){$slider.tlrkSlider("go", "prev"); return false; }).end()
.find(".slider-next").click(function(){$slider.tlrkSlider("go", "next"); return false; });
});
本文作者:码农网 – 小峰
共同學習,寫下你的評論
評論加載中...
作者其他優質文章