Skip to content

Instantly share code, notes, and snippets.

@grigs
Created March 14, 2012 21:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save grigs/2039654 to your computer and use it in GitHub Desktop.
Save grigs/2039654 to your computer and use it in GitHub Desktop.
Apple’s Features.js -- prettified version of http://images.apple.com/v/ipad/a/scripts/features.js
AC.AmbientVR = Class.create({
__defaultOptions: {
imageIndexOffset: 0,
initialPos: 0,
throwable: false,
invert: false,
infiniteAxis: false,
grabRotateDistance: 780,
allowMobileScroll: true,
introSpins: 0,
fps: 30,
animateToPos: 0,
showOnScrollOptions: {
timeInView: 0.25
},
onGrabStart: Prototype.emptyFunction,
onGrabEnd: Prototype.emptyFunction,
onGotoPos: Prototype.emptyFunction,
onVisitorEngaged: Prototype.emptyFunction
},
initialize: function (k, j, i, m) {
if (typeof m !== "object") {
m = {}
}
this._options = Object.extend(Object.clone(this.__defaultOptions), m);
this._element = $(k);
this._hasAnimated = false;
this._swipe = this._element.down("command");
if (typeof this._swipe !== "undefined") {
if (AC.Detector.isMobile() || AC.Detector.isiPad()) {
var n = this._swipe.getAttribute("data-label-ios");
this._swipe.update(n);
this._swipe.setAttribute("label", n)
} else {
this._swipe.update(this._swipe.getAttribute("label"))
}
}
var h = this._element.getElementsBySelector('a[href="#replay"]');
if (h.length > 0) {
var l = this.__setupReplay.bind(this);
h.each(l)
}
this._ambient = new AC.Ambient.Content.Scroll.WithThreshold.AndTimer(this._element, this._options);
this._ambient.setDelegate(this);
this._vr = new AC.AmbientVR.VR(this._element, j, i, this._options);
this._vr.setDelegate({
onGrabStart: this.onGrabStart.bind(this),
onGrabEnd: this.onGrabEnd.bind(this),
onGotoPos: this.onGotoPos.bind(this)
});
if (this._vr.mobile && this._vr.options.mobileTotalFrames) {
this._options.animateToPos = Math.floor(this._options.animateToPos / (i / this._options.mobileTotalFrames))
}
Object.synthesize(this)
},
__setupReplay: function (b) {
if (typeof this.__boundOnReplayClick !== "function") {
this.__boundOnReplayClick = this.__onReplayClick.bindAsEventListener(this)
}
b.observe("click", this.__boundOnReplayClick)
},
__onReplayClick: function (b) {
b.stop();
this._vr.gotoPos([this._options.initialPos, 0]);
this._vr.animateToPos(this._options.animateToPos)
},
showSwipe: function (b) {
if (typeof this._swipe !== "undefined" && typeof b === "object" && Object.isElement(b.container) && this.__neverShowSwipeAgain !== true) {
b.container.addClassName("show-command")
}
},
hideSwipe: function (b) {
if (typeof this._swipe !== "undefined" && typeof b === "object" && Object.isElement(b.container) && this.__neverShowSwipeAgain !== true) {
b.container.removeClassName("show-command");
this.__neverShowSwipeAgain = true
}
},
showReplays: function (b) {
if (typeof b === "object" && Object.isElement(b.container)) {
b.container.addClassName("show-replays")
}
},
hideReplays: function (b) {
if (typeof b === "object" && Object.isElement(b.container)) {
b.container.removeClassName("show-replays")
}
},
onGrabStart: function (b) {
this.hideSwipe(b);
this._options.onGrabStart.apply(this, [b])
},
onGrabEnd: function (b) {
this._options.onGrabEnd.apply(this, [b])
},
onGotoPos: function (d, c) {
if ((this._options.initialPos < this._options.animateToPos && c[0] >= this._options.animateToPos) || (this._options.initialPos > this._options.animateToPos && c[0] <= this._options.animateToPos)) {
this.showSwipe(d);
this.showReplays(d)
} else {
this.hideReplays(d)
}
this._options.onGotoPos.apply(this, [d, c])
},
onVisitorEngaged: function (g, h, e, f) {
this._options.onVisitorEngaged.apply(this, [this._vr]);
if (!this._hasAnimated) {
this._vr.animateToPos(this._options.animateToPos);
this._hasAnimated = true
}
},
track: function (d) {
if (typeof this.__analytics === "undefined") {
this.__analytics = {};
this.__analytics.pageName = AC.Tracking.pageName()
}
var c = Object.extend({
prop3: this.__analytics.pageName + " - " + d
}, this.__analytics);
AC.Tracking.trackClick(c, this, "o", c.prop3)
}
});
AC.AmbientVR.VR = Class.create(AC.VR, {
animateToPos: function (b) {
if (typeof this.animateToInterval !== "undefined") {
clearInterval(this.animateToInterval)
}
this.animateToInterval = setInterval(this._animateToPos.bind(this, b), (1000 / this.options.fps))
}
});
AC.TrackBackground = Class.create({
initialize: function (c, d) {
this._element = $(c);
this._options = {
minimumPercentage: 0,
maximumPercentage: 100,
anchorTop: false
};
Object.extend(this._options, d || {});
if (!this._element) {
return
}
this._scroll = new AC.ShowOnScroll(c, {
threshold: 0.85,
timeInView: 0.5
});
this._scroll.setDelegate(this);
Event.observe(window, "resize", this.onWindowResize.bindAsEventListener(this));
this._containerHeight = parseInt(this._element.getStyle("height"));
this._elementOffset = this._element.cumulativeOffset().top;
this._viewportHeight = document.viewport.getDimensions().height;
Object.synthesize(this)
},
onWindowResize: function () {
this._viewportHeight = document.viewport.getDimensions().height
},
scrolledWhileInView: function (g, j, h) {
var k = document.viewport.getScrollOffsets().top;
var i = this._elementOffset - (k - this._viewportHeight);
var l = (i - (this._containerHeight / 2)) / (this._viewportHeight + this._containerHeight);
if (this._options.anchorTop) {
l = Math.min(Math.max(k / this._viewportHeight, 0), 1)
}
l = this._options.minimumPercentage + (l * (this._options.maximumPercentage - this._options.minimumPercentage));
this._element.setStyle({
backgroundPosition: "0 " + l + "%"
})
}
});
AC.TrackBackground.WithGallery = Class.create(AC.TrackBackground, {
initialize: function ($super, d) {
$super(d);
if (!this._element) {
return
}
var f = this._element.getElementsByClassName("gallery-content");
var e = this._element.down(".gallery-view");
this._swap = new AC.ViewMaster.Viewer(f, e, e.id, {
addSectionIdAsClassName: true,
manageZ: true,
shouldAnimateFadeIn: true,
silentTriggers: true,
animationDuration: 0.6
});
this._swap.setDelegate(this)
},
scrolledWhileInView: Prototype.emptyFunction,
visitorEngaged: function (h, g, e, f) {
if (this._swap.currentSection.id !== this._swap.orderedSections[1]) {
this._swap.show(this._swap.sectionWithId(this._swap.orderedSections[1]))
}
},
scrolledOutOfView: function (b) {
if (this._swap.currentSection.id !== this._swap.orderedSections[0]) {
this._swap.show(this._swap.sectionWithId(this._swap.orderedSections[0]))
}
},
shouldAnimateContentChange: function (e, f, d) {
if (d && d.id === this._swap.orderedSections[0]) {
return false
}
return true
}
});
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function (b) {
window.setTimeout(b, 1000 / 60)
}
})();
AC.BatteryClock = Class.create({
__defaultOptions: {
duration: 5,
radius: 40,
angleHours: 300,
angleMinutes: 3600,
animationTimingFunction: function (h, b, c, d) {
h /= d / 2;
if (h < 1) {
return c / 2 * h * h + b
}
h--;
return -c / 2 * (h * (h - 2) - 1) + b
},
fillStyle: "#19E063"
},
initialize: function (e, f, d) {
if ((AC.Detector.isMobile()) || (AC.Detector.isiPad()) || !AC.Detector.supportsThreeD()) {
return false
}
if (typeof d !== "object") {
d = {}
}
this._options = Object.extend(Object.clone(this.__defaultOptions), d);
this._hasAnimated = false;
this._elements = {};
this._elements.container = $(e);
this.__addImage("http://images.apple.com/v/ipad/a/features/images/clock_background.svg");
this._elements.hour_hand = this.__addImage("http://images.apple.com/v/ipad/a/features/images/clock_hour.svg");
this._elements.min_hand = this.__addImage("http://images.apple.com/v/ipad/a/features/images/clock_minute.svg");
this._elements.container.addClassName("enhanced");
this._canvas = document.createElement("canvas");
this._canvas.width = 80;
this._canvas.height = 80;
this._elements.container.appendChild(this._canvas);
this._context = this._canvas.getContext("2d");
this._showOnScroll = new AC.ShowOnScroll($(f));
this._showOnScroll.setDelegate(this);
Object.synthesize(this)
},
__addImage: function (c) {
var d = new Element("img");
d.src = c;
this._elements.container.appendChild(d);
return d
},
animate: function () {
var j = this;
var m = j._options.duration * 1000;
var n = 0;
var l = 0;
var q = 0;
var o = 0;
var p = new Date().getTime();
var r = {
x: j._canvas.width / 2,
y: j._canvas.height / 2
};
(function k() {
if (l < m) {
j._context.clearRect(0, 0, j._canvas.width, j._canvas.height);
l = new Date().getTime() - p;
q = j._options.animationTimingFunction(l, 0, j._options.angleHours, m);
o = j._options.animationTimingFunction(l, 0, j._options.angleMinutes, m);
n = (q * Math.PI / 180);
j._elements.hour_hand.setVendorPrefixStyle("transform", "rotate(" + q + "deg)");
j._elements.min_hand.setVendorPrefixStyle("transform", "rotate(" + o + "deg)");
j._context.beginPath();
j._context.fillStyle = j._options.fillStyle;
j._context.arc(r.x, r.y, j._options.radius - 0.75, 0, n, false);
j._context.lineTo(r.x, r.y);
j._context.fill();
j._context.closePath();
requestAnimFrame(k)
}
}());
j._hasAnimated = true
},
visitorEngaged: function () {
if (!this._hasAnimated) {
this.animate()
}
}
});
Event.onDOMReady(function () {
new AC.BatteryClock("ambient-battery-clock", $$("section.performance .grid3col .last")[0]);
if (document.getElementsByTagName("command").length > 0) {
if (!(AC.Detector.isMobile() || AC.Detector.isiPad())) {
var d = new AC.AmbientVR("ambient-lenses", "http://movies.apple.com/media/us/ipad/2012/camera-extrusion/camera_extrusion_###.jpg", 106, {
grabbable: false,
mobileTotalFrames: 53,
animateToPos: 105,
onGotoPos: function (b, a) {
if ((b.mobile && a[0] >= 41) || (!b.mobile && a[0] >= 82)) {
if (this._hasFadedInTickRight !== true) {
b.container.up().addClassName("show-tick-right");
this._hasFadedInTickRight = true
}
} else {
if (this._hasFadedInTickRight === true) {
b.container.up().removeClassName("show-tick-right");
this._hasFadedInTickRight = false
}
}
if ((b.mobile && a[0] >= 28) || (!b.mobile && a[0] >= 56)) {
if (this._hasFadedInTickLeft !== true) {
b.container.up().addClassName("show-tick-left");
this._hasFadedInTickLeft = true
}
} else {
if (this._hasFadedInTickLeft === true) {
b.container.up().removeClassName("show-tick-left");
this._hasFadedInTickLeft = false
}
}
if ((this._options.initialPos < this._options.animateToPos && a[0] >= this._options.animateToPos) || (this._options.initialPos > this._options.animateToPos && a[0] <= this._options.animateToPos)) {} else {
if (a[0] === 0) {
if (this.__trackStart === "replay") {
this.track("vr - lens - replay")
}
}
}
},
onVisitorEngaged: function (b, a) {
if (!this._hasAnimated) {
this.track("vr - lens - start")
}
this.__trackStart = "replay"
}
})
}
if (!(AC.Detector.isiPad() || AC.Detector.isMobile())) {
var e = new AC.AmbientVR("ambient-smartcover", "http://movies.apple.com/media/us/ipad/2012/smart-cover/features/smartcover_###.jpg", 46, {
initialPos: 45,
animateToPos: 0,
onGrabStart: function (a) {
if (this.__trackedInteracted !== true) {
this.track("vr - smartcover - interacted");
this.__trackedInteracted = true
}
},
onGrabEnd: function (a) {
if (a.currentPos[0] <= 14) {
a.animateToPos(0)
} else {
if (a.currentPos[0] <= 22) {
a.animateToPos(19)
} else {
a.animateToPos(45)
}
}
}
});
var f = e.element();
if (typeof f === "object" && Object.isElement(f)) {
f.addClassName("active")
}
}
}
if ((!(AC.Detector.isMobile() || AC.Detector.isiPad())) && ((!AC.Detector.isIE()) || AC.Detector.isIE8())) {
new AC.TrackBackground("ambient-hero-bg", {
anchorTop: true,
maximumPercentage: 50
});
new AC.TrackBackground("ambient-camera-bg");
new AC.TrackBackground("ambient-wireless-bg")
}
if (!(AC.Detector.isMobile() || AC.Detector.isiPad())) {
new AC.TrackBackground.WithGallery("ambient-airplay-bg")
} else {
$("gallery-airplay").setStyle("display:none");
$("gallery-airplay-second").setStyle("display:block")
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment