Update
BIN
education.png
Before Width: | Height: | Size: 3.4 KiB |
BIN
experience.png
Before Width: | Height: | Size: 3.5 KiB |
BIN
favicon.ico
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 106 KiB |
BIN
header2.png
Before Width: | Height: | Size: 136 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
BIN
illusions/black-cat.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
illusions/construction.gif
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
illusions/life.jpg
Normal file
After Width: | Height: | Size: 170 KiB |
367
illusions/london-skyline.svg
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
illusions/purple-cat.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
illusions/stars.jpg
Normal file
After Width: | Height: | Size: 775 KiB |
377
index.html
@ -1,219 +1,158 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1" ?>
|
<!--
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="fi" xml:lang="fi">
|
. . IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||||
|
.IMMMMMMMMMMMMMM8I . ... . =MMMM
|
||||||
<!--
|
:MMMMMMMMMZ . 7MMMMZ . 7MD . IMMD .
|
||||||
|
MMMMM. . . . .~ .M, . MMM .
|
||||||
. . IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
MMMM, N. .IDMMMO777ZNMMMMMO =MM . M:. NMM.
|
||||||
.IMMMMMMMMMMMMMM8I . ... . =MMMM
|
. ZMMM . . :7NMMDI= . MM IM MMM
|
||||||
:MMMMMMMMMZ . 7MMMMZ . 7MD . IMMD .
|
MMM IMM77IDMMM, . M8 ..MM M ,N MMM
|
||||||
MMMMM. . . . .~ .M, . MMM .
|
M8 M M . M ,O . 7. MM
|
||||||
MMMM, N. .IDMMMO777ZNMMMMMO =MM . M:. NMM.
|
.M8 D ,. ... M 7 MM
|
||||||
. ZMMM . . :7NMMDI= . MM IM MMM
|
MM. 7 = . ~MMMMMN, . 7MM
|
||||||
MMM IMM77IDMMM, . M8 ..MM M ,N MMM
|
MMM .. N. MMMMMMMMMMMMMMMO. MMM
|
||||||
M8 M M . M ,O . 7. MM
|
.MMM MMMMMMMMM+. ZMMMZ $MMMMMMMMMMM.. MMM
|
||||||
.M8 D ,. ... M 7 MM
|
MMMD. . ..ZMMM78MMMMMMMMM MMM. .. DMMMMMMMMMMM8MM MM7 . OMMMM .
|
||||||
MM. 7 = . ~MMMMMN, . 7MM
|
MMM MM:. . MMMMMMMMMMMMMMMMM IMM MMMMMMO .DMMMMM.. . . +O MMM.
|
||||||
MMM .. N. MMMMMMMMMMMMMMMO. MMM
|
.MMM ?D OMMMMM .,MMMMM+ MM MMMMMMMM. ?.MM..
|
||||||
.MMM MMMMMMMMM+. ZMMMZ $MMMMMMMMMMM.. MMM
|
MMM M :M. .7M8 MM . MMMN .. =MMMMM. . :MMM :.MMM.
|
||||||
MMMD. . ..ZMMM78MMMMMMMMM MMM. .. DMMMMMMMMMMM8MM MM7 . OMMMM .
|
MMM. 8. MMMMMMMMMZ. MM MMMMMMMMMMMM~ M MM. MM$
|
||||||
MMM MM:. . MMMMMMMMMMMMMMMMM IMM MMMMMMO .DMMMMM.. . . +O MMM.
|
.MMOM M . .. MMMMMM$ . MMM . MM .MM MM
|
||||||
.MMM ?D OMMMMM .,MMMMM+ MM MMMMMMMM. ?.MM..
|
NMMM M 8M O88I MMMM 7~ . . .:MMMMMM MM MM
|
||||||
MMM M :M. .7M8 MM . MMMN .. =MMMMM. . :MMM :.MMM.
|
MMM $ . MM . MMM~ ~MMMMMMM MMMMM=.7MMMM MM . MM
|
||||||
MMM. 8. MMMMMMMMMZ. MM MMMMMMMMMMMM~ M MM. MM$
|
NM7I M MMM: MMMMM MM MMMMMM . MMMZMMM.MM. 8 MM
|
||||||
.MMOM M . .. MMMMMM$ . MMM . MM .MM MM
|
MM MM .+MMMM =M M,MMD MMMMMMM $MM DMMMMMM.. ZMM. .MM .8..MMM.
|
||||||
NMMM M 8M O88I MMMM 7~ . . .:MMMMMM MM MM
|
MM? :M MMMMMM .. . . MM . . . MMM .MMMMMMMI=MM MMMM M N MMM
|
||||||
MMM $ . MM . MMM~ ~MMMMMMM MMMMM=.7MMMM MM . MM
|
.MM MMMMMMMMM 8MMMM .ZMMMMMM? . MMM. ,MMMMMM . =. MMM
|
||||||
NM7I M MMM: MMMMM MM MMMMMM . MMMZMMM.MM. 8 MM
|
MMM. MMMM MMMMMMM8 . MM . :MMMMMMMMM NMMMMMMMMMMM .MMM.
|
||||||
MM MM .+MMMM =M M,MMD MMMMMMM $MM DMMMMMM.. ZMM. .MM .8..MMM.
|
.MM IMMM= MM ?MMMMMMMMMMMMMMMMMMMMMMM8 . MM . MMMMMMM . MMN 8 MM8
|
||||||
MM? :M MMMMMM .. . . MM . . . MMM .MMMMMMMI=MM MMMM M N MMM
|
MM 7MMM MM .MM $MMMMM7 .MM.. .MM. MMMMMMMMMMD. MM~ MMM
|
||||||
.MM MMMMMMMMM 8MMMM .ZMMMMMM? . MMM. ,MMMMMM . =. MMM
|
7M ..=MMMMMMM?. MMI MMM MM . ?MMMMMMMMMM MM .MMI . MMM.
|
||||||
MMM. MMMM MMMMMMM8 . MM . :MMMMMMMMM NMMMMMMMMMMM .MMM.
|
M= MMMMMMMMMMMMMMN~ .8M= MM 7MMMMMMMMMMMM, MM8MMM .,MM
|
||||||
.MM IMMM= MM ?MMMMMMMMMMMMMMMMMMMMMMM8 . MM . MMMMMMM . MMN 8 MM8
|
M= MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM8 MMMM . MM.
|
||||||
MM 7MMM MM .MM $MMMMM7 .MM.. .MM. MMMMMMMMMMD. MM~ MMM
|
=M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM+ 8MM MMM$ MM
|
||||||
7M ..=MMMMMMM?. MMI MMM MM . ?MMMMMMMMMM MM .MMI . MMM.
|
.8M. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM . =MMMM. 7MM.
|
||||||
M= MMMMMMMMMMMMMMN~ .8M= MM 7MMMMMMMMMMMM, MM8MMM .,MM
|
MM MM.MM MM.ZMMMM7=MMMM . MM ZMM MMMMM MMM.
|
||||||
M= MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM8 MMMM . MM.
|
MM MMZMM ~MM MMM ..~MM MM MMMMMMM . $MM$
|
||||||
=M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM+ 8MM MMM$ MM
|
MM ~MMM, MMM MM=. MM MM MMMMMMZ .M7 .MM ~MMM
|
||||||
.8M. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM . =MMMM. 7MM.
|
,MM MMMMMMMMD. MM MM MMO~.7MMMMMMMM=.. NM.. MM DMMM
|
||||||
MM MM.MM MM.ZMMMM7=MMMM . MM ZMM MMMMM MMM.
|
MMI . =MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM~. .M?. ,MM =MMMM
|
||||||
MM MMZMM ~MM MMM ..~MM MM MMMMMMM . $MM$
|
MM. D. . .. . . . .M= . ZMD . MMMM
|
||||||
MM ~MMM, MMM MM=. MM MM MMMMMMZ .M7 .MM ~MMM
|
MM. M M . .8MMMMMMMMMMMMM. MZ MM? . =MMMM
|
||||||
,MM MMMMMMMMD. MM MM MMO~.7MMMMMMMM=.. NM.. MM DMMM
|
MM. I .MM ... .MM= .MM. ZMMMM
|
||||||
MMI . =MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM~. .M?. ,MM =MMMM
|
MM ,N . ,+777- -, ... ?MM MMMMM
|
||||||
MM. D. . .. . . . .M= . ZMD . MMMM
|
MM. MMO. .. . . . 7MO . ?MMMM
|
||||||
MM. M M . .8MMMMMMMMMMMMM. MZ MM? . =MMMM
|
MMZ .. .==~=. . . MMMM.
|
||||||
MM. I .MM ... .MM= .MM. ZMMMM
|
MM . . MMMM
|
||||||
MM ,N . ,+777- -, ... ?MM MMMMM
|
MMM .. MMMMMMMMMM
|
||||||
MM. MMO. .. . . . 7MO . ?MMMM
|
.MMM7 ZMMMMMMMMN:
|
||||||
MMZ .. .==~=. . . MMMM.
|
DMMMMMMMMMMMMMMMMMMMMMMMM? . .
|
||||||
MM . . MMMM
|
. 7MMMMMMMMMMMMZ. . ..
|
||||||
MMM .. MMMMMMMMMM
|
|
||||||
.MMM7 ZMMMMMMMMN:
|
-->
|
||||||
DMMMMMMMMMMMMMMMMMMMMMMMM? . .
|
|
||||||
. 7MMMMMMMMMMMMZ. . ..
|
<html>
|
||||||
|
|
||||||
-->
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
<head>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
|
||||||
<title>Martti Malmi</title>
|
<title>siri.us</title>
|
||||||
<link rel="shortcut icon" href="favicon.ico" />
|
<link rel="stylesheet" type="text/css" href="per.css">
|
||||||
<style type="text/css">
|
<link href='http://fonts.googleapis.com/css?family=Lato|Uncial+Antiqua|Slabo+27px' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
|
||||||
body {
|
<link rel="icon" type="image/x-icon" href="illusions/purple-cat.ico" />
|
||||||
text-align: center;
|
<script type="text/javascript" src="sorcery/instafeed.min.js"></script>
|
||||||
padding: 0px 0px 50px 0px;
|
<script type="text/javascript" src="sorcery/jquery-1.11.2.min.js"></script>
|
||||||
margin:0px;
|
<script type="text/javascript">
|
||||||
font: 12px/18px "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
|
$(document).ready(function() {
|
||||||
}
|
var $root = $('html, body');
|
||||||
|
$('a').click(function() {
|
||||||
div.main {
|
var href = $.attr(this, 'href');
|
||||||
text-align: left;
|
$root.animate({
|
||||||
margin: 30px auto;
|
scrollTop: $(href).offset().top
|
||||||
background-color: #FFFFFF;
|
}, 500, function () {
|
||||||
border-right: 0px solid #EEE;
|
window.location.hash = href;
|
||||||
border-left: 0px solid #EEE;
|
});
|
||||||
max-width: 800px;
|
return false;
|
||||||
padding: 0 5px;
|
});
|
||||||
}
|
});
|
||||||
|
</script>
|
||||||
a { color: #A22; text-decoration: none; }
|
</head>
|
||||||
a:hover { color: #A22; text-decoration: underline; }
|
<body>
|
||||||
|
|
||||||
img { border: 0px; }
|
<header>
|
||||||
|
<ul>
|
||||||
#pic img { float: left; margin-right: 25px; }
|
<li><a href="#cover"><span class="fa fa-star"></span></a></li>
|
||||||
#content { clear: both; padding-top: 20px; border-bottom: 1px solid #EEE; }
|
<!--<li><a href="#design">Design</a></li>-->
|
||||||
#header { color: #555; padding: 32px 0px; font-size: 18px; border-top: 1px solid #EEE; border-bottom: 1px solid #EEE; }
|
<li><a href="#photography">Photography</a></li>
|
||||||
#header li { margin: 0px 0px 10px 0px; }
|
<li><a href="#writing">Writing</a></li>
|
||||||
|
</ul>
|
||||||
h1 { font-size: 36px; margin: 50px 0px 20px 0px; }
|
</header>
|
||||||
h2 {
|
|
||||||
margin:0px;
|
<section id="cover">
|
||||||
float: left;
|
<div class="content layer" data-depth="0.00">
|
||||||
color: #000;
|
<h1>Sirius Business</h1>
|
||||||
font-size: 24px;
|
<div id="contact">
|
||||||
}
|
<ul>
|
||||||
|
<li><a href="https://twitter.com/marttimalmi"><span class="fa fa-twitter"></span></a></li>
|
||||||
ul { list-style-type: none; }
|
<li><a href="https://www.facebook.com/mmalmi"><span class="fa fa-facebook"></span></a></li>
|
||||||
li { margin: 0px 0px 18px 0px; }
|
<li><a href="https://www.linkedin.com/in/marttimalmi"><span class="fa fa-linkedin"></span></a></li>
|
||||||
|
<li><a href="https://instagram.com/mmalmi"><span class="fa fa-instagram"></span></a></li>
|
||||||
.clear { clear:both; }
|
<li><a href="mailto:sirius@iki.fi"><span class="fa fa-at"></span></a></li>
|
||||||
|
<li><a href="https://github.com/mmalmi"><span class="fa fa-github"></span></a></li>
|
||||||
.block { clear:both; margin-bottom: 60px; }
|
</ul>
|
||||||
.block ul { margin-left: 160px; }
|
</div>
|
||||||
.block ul b { margin-right: 5px; }
|
</div>
|
||||||
.block ul img { margin: 10px 0px;}
|
</section>
|
||||||
|
|
||||||
@media (max-width: 799px) {
|
<section id="photography">
|
||||||
#header { text-align:center; padding: 10px 0px; }
|
<h1>Photography <small>— AFK screenshots</small></h1>
|
||||||
#header ul { margin:0; padding:0;}
|
<div id="instafeed"></div>
|
||||||
#pic img { float:none; max-width:20%; margin:0; }
|
</section>
|
||||||
h2 { float:none; margin-left:5px; }
|
|
||||||
.block ul { margin-left:0px; }
|
<!--<section id="design">
|
||||||
img { max-width: 90%; }
|
<h1>Design <small>is the meaning of life</small></h1>
|
||||||
h2 img{max-width:100%;}
|
<div></div>
|
||||||
h1 { margin: 20px 0 }
|
</section> -->
|
||||||
}
|
|
||||||
|
<section id="writing">
|
||||||
|
<h1>Writing <small>is a art</small></h1>
|
||||||
</style>
|
|
||||||
|
<div>
|
||||||
</head>
|
<a class="twitter-timeline" href="https://twitter.com/marttimalmi" data-widget-id="592795935392030721">Twiittejä käyttäjältä @marttimalmi</a>
|
||||||
|
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
||||||
<body>
|
</div>
|
||||||
<div class="main">
|
|
||||||
<div id="header">
|
<p>
|
||||||
<div id="pic"><img alt="Lily!" src="lily.png"/></div>
|
<a href="http://speedtest.10fastfingers.com"><img src="illusions/1_wpm_score_DK.png" alt="Typing Test Score"></a>
|
||||||
<h1><img alt="Martti Malmi" src="title9.png" /></h1>
|
</p>
|
||||||
<ul>
|
|
||||||
<li>Software developer, digital culture enthusiast</li>
|
<p>
|
||||||
<li><a href="mailto:martti.malmi@aalto.fi">martti.malmi@aalto.fi</a> (<a href="mmalmi.pgp">PGP</a>)</li>
|
<a href="http://siriusbisnes.blogspot.fi">Blog: Sirius Business (in Finnish)</a>
|
||||||
<li><a href="https://github.com/mmalmi">GitHub</a>
|
</p>
|
||||||
<li><a href="http://fi.linkedin.com/pub/martti-malmi/11/25/102"><img alt="LinkedIn Profile" src="linkedin3.png"/></a></li>
|
|
||||||
</ul>
|
</section>
|
||||||
<div class="clear"></div>
|
|
||||||
</div>
|
<footer>
|
||||||
|
<!--<p>
|
||||||
<div id="content">
|
"Man who <span class="spoiler">puts dick in peanut butter</span> is fucking nuts." — Confucius
|
||||||
<div class="block">
|
</p>-->
|
||||||
<h2><img alt="Me" src="me.png"/></h2>
|
|
||||||
<ul>
|
<p>
|
||||||
<li>Born in Rovaniemi, Finland, 1988 A.D.</li>
|
<img src="illusions/construction.gif">
|
||||||
<li>I like playing guitar and keyboards, LAN parties, FPS and RTS games, indoor climbing, latino dances, imageboards, funny Youtube videos and bad action movies.</li>
|
</p>
|
||||||
<li>I also like Japan! Check out my 2011 travel blog <a href="http://morzenjapan.blogspot.com">Mårzen in Japan</a> (in Finnish).</li>
|
</footer>
|
||||||
<li>I'm interested in topics such as music, languages, cultural evolution, Internet memes, economics and society. As for technology, I'm more interested in its human implications than technical intricacies.</li>
|
|
||||||
<li>Open-minded <a href="http://en.wikipedia.org/wiki/INTP">INTP</a> personality.</li>
|
<script type="text/javascript">
|
||||||
<li><img src="fillari2-small.jpg" alt="Travelling in Fukuoka, Japan"/></li>
|
var userFeed = new Instafeed({
|
||||||
</ul>
|
get: 'user',
|
||||||
</div>
|
userId: 313386739,
|
||||||
|
accessToken: '313386739.9038401.550f95a9937643cc95fb5ec141e583cb'
|
||||||
<div class="block">
|
});
|
||||||
<h2><img alt="Education" src="education.png"/></h2>
|
userFeed.run();
|
||||||
<ul>
|
</script>
|
||||||
<li><b>2003</b> Finnish National Board of Education: Award from improving IT usage in educational institute (Mankkaa school).</li>
|
|
||||||
<li><b>2007</b> Ylioppilastutkinto (The Finnish Matriculation Examination), Olari high school.</li>
|
</body>
|
||||||
<li><b>2007 - 2009</b> Computer science studies at Helsinki University of Technology. Mostly programming courses.</li>
|
|
||||||
<li><b>2011</b> 9 weeks of Japanese studies at <a href="http://www.genkijacs.com/">GenkiJACS</a>, Fukuoka, Japan.</li>
|
|
||||||
</ul>
|
</html>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="block">
|
|
||||||
<h2><img alt="Experience" src="experience.png"/></h2>
|
|
||||||
<ul>
|
|
||||||
<li><b>2004</b> Verkkokauppa.com, junior high school traineeship. 2 weeks of mostly warehouse work, but my friend and I also spent a day coding a PHP script that parsed warehouse receipts and searched product codes for the listed items. The script saved a lot of manual work so they rewarded us with gift cards.</li>
|
|
||||||
<li><b>2007 - 2010</b> Various part time jobs at warehouses and construction sites.</li>
|
|
||||||
<li><b>2009 - 2011</b> Developer of the P2P virtual currency <a
|
|
||||||
href="http://www.bitcoin.org/">Bitcoin</a>. I was the first person to join the project and had the privilege to work with the infamous man of mystery, <a href="http://en.wikipedia.org/wiki/Satoshi_Nakamoto#Creator">Satoshi Nakamoto</a>. My tasks included community building, project organization, web design, web app development, server administration, C++ programming and documentation in English. Check out my interviews by <a href="http://www.businessinsider.com/bitcoins-martti-malmi-not-worried-about-liberty-reserve-2013-5">Business Insider</a>, <a href="http://www.iltasanomat.fi/digi/art-1288496063056.html">Ilta-Sanomat</a> (in Finnish) and <a href="http://www.talouselama.fi/uutiset/bitcoin+mullistaa+maksuliikennetta/a729735">Tietoviikko</a> (in Finnish).</li>
|
|
||||||
<li><b>8.3. - 30.6.2010</b> Siemens, trainee at the corporate communications department. Compilation of the company website content using a CMS. The work included presentation logic planning, illustration using Adobe Photoshop, proof-reading, co-working with product managers, some CMS user support and a lot of ctrl+c & ctrl+v.</li>
|
|
||||||
<li><b>9.9.2010 - 24.8.2011</b> <a href="http://www.whitevector.com/">Whitevector</a>, software developer. Worked in a small agile team that developed and maintained a social media monitoring and analysing product. Technologies used included Java (Eclipse IDE), Lucene, PostgreSQL and Ruby on Rails among others.</li>
|
|
||||||
<li><b>5.6.-31.7.2012</b> <a href="https://www.kuvaverkko.fi">Kuvaverkko</a>, Billing system upgrade project. PHP & MySQL development.</li>
|
|
||||||
<li><b>8.8.2012 -</b> <a href="http://sc5.fi">SC5</a>, Front & back-end web development.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="block">
|
|
||||||
<h2><img alt="Skills" src="skills.png"/></h2>
|
|
||||||
<ul>
|
|
||||||
<li>I'm good at writing grammatically correct English and Finnish and expressing things clearly. I can communicate basic things in Swedish and Japanese.</li>
|
|
||||||
<li>I have an eye for aesthetics in web sites and user interfaces. I can create layouts using Photoshop, CSS and HTML. I have played around a little with Qt, wxWidgets and Swing.</li>
|
|
||||||
<li>I have worked with Java, C++, Eclipse, SVN, Apache, SQL, RoR, Django, PHP, HTML5, JSON, XML and Javascript (JQuery, Mootools).</li>
|
|
||||||
<li>I have maintained hobby Linux servers since I was 14 and production servers since 2009.</li>
|
|
||||||
<li>I understand not only code, but also user experience and business aspects. In addition to thinking about <i>what</i> and <i>how</i> you do, it's good to know <i>why</i> you do things.</li>
|
|
||||||
<li>I'm good at speed typing!<br/>
|
|
||||||
<a href="http://speedtest.10fastfingers.com"><img src="1_wpm_score_DK.png" alt="Typing Test Score" /></a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="block">
|
|
||||||
<h2><img alt="Old stuff" src="work_samples.png"/></h2>
|
|
||||||
<ul>
|
|
||||||
<li><b>2007</b> Saving Princess Adeleine (<a href="adventure.jar">jar</a>/<a
|
|
||||||
href="adventure.exe">exe</a>), a simple
|
|
||||||
text-adventure game I made for a programming course. It was chosen as one
|
|
||||||
of the model solutions for the exercise. You can find a "cheater's
|
|
||||||
map" of the game world <a href="cheatermap.GIF">here</a>.</li>
|
|
||||||
<li><b>2008</b> <a href="tetris.html">Tetris</a>, a Java-applet.</li>
|
|
||||||
<li><b>2009</b> Mökki (<a href="moekki1.1.jar">jar</a>/<a href="samples/Moekki.html">source code</a>). A game where you
|
|
||||||
place sticks on a grid, and get a point and a new turn for each triangle you
|
|
||||||
complete. Can be played against the computer or another human player. Made
|
|
||||||
as a project work for the programming course T-106.1240 Ohjelmoinnin
|
|
||||||
jatkokurssi T1.</li>
|
|
||||||
<li><b>2010</b> Inverted Index (<a href="samples/InvertedIndex.html">source code</a>), a standalone Java program made as a work sample for a job application.</li>
|
|
||||||
<li><b>2012</b> <a href="http://www.flowdock.com">Flowdock</a> plugin for <a href="http://www.redmine.org">Redmine</a> (<a href="samples/RedmineFlowdockPlugin.html">source code</a>). Posts newly created issues and issue status updates from Redmine to Flowdock using the Flowdock API.</li>
|
|
||||||
<!-- <li><b>2012</b> <a href="https://eurobtc.com">EuroBTC</a> (<a href="samples/eurobtc.html">source code</a>), a service that lets you buy and sell bitcoins for cash in the snail mail. Written in PHP.</li> -->
|
|
||||||
<li><b>2012</b> <a href="samples/html5tetris.html">Neon Shade Tetris</a> (<a href="http://github.com/mmalmi/neonshadetetris">GitHub</a>), a JavaScript/HTML5 tetris game.</li>
|
|
||||||
<li><b>2012</b> <a href="gamewheel">Gamewheel</a> (<a href="http://github.com/mmalmi/gamewheel">GitHub</a>), wheel of fortune for choosing the next game at LAN parties.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="footer"><img alt="" src="lily-small3.png"/></div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
BIN
lily-small3.png
Before Width: | Height: | Size: 4.6 KiB |
BIN
linkedin3.png
Before Width: | Height: | Size: 511 B |
148
per.css
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Lato';
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
z-index: 1;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 1em 0;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 3em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
display: inline-block;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section h1 {
|
||||||
|
font-size: 3em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 small {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scroller {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
background-color: black;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
#cover h1 {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover {
|
||||||
|
font-size: 3em;
|
||||||
|
letter-spacing: 20;
|
||||||
|
//text-shadow: 0 0 1px black;
|
||||||
|
background: url(illusions/life.jpg) no-repeat center center;
|
||||||
|
background-size: cover;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover .content {
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover li {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#writing {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#writing a {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#writing a:hover {
|
||||||
|
color: #999999;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 150px 20px;
|
||||||
|
background: #fff url(illusions/london-skyline.svg) repeat-x center 0;
|
||||||
|
//background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #C262D3;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
}
|
||||||
|
|
||||||
|
.spoiler {
|
||||||
|
transition: background 3s ease;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spoiler:hover {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
BIN
skills.png
Before Width: | Height: | Size: 3.2 KiB |
2
sorcery/instafeed.min.js
vendored
Normal file
1584
sorcery/iscroll-infinite.js
Normal file
944
sorcery/iscroll-lite.js
Normal file
@ -0,0 +1,944 @@
|
|||||||
|
/*! iScroll v5.1.3 ~ (c) 2008-2014 Matteo Spinelli ~ http://cubiq.org/license */
|
||||||
|
(function (window, document, Math) {
|
||||||
|
var rAF = window.requestAnimationFrame ||
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.oRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame ||
|
||||||
|
function (callback) { window.setTimeout(callback, 1000 / 60); };
|
||||||
|
|
||||||
|
var utils = (function () {
|
||||||
|
var me = {};
|
||||||
|
|
||||||
|
var _elementStyle = document.createElement('div').style;
|
||||||
|
var _vendor = (function () {
|
||||||
|
var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
|
||||||
|
transform,
|
||||||
|
i = 0,
|
||||||
|
l = vendors.length;
|
||||||
|
|
||||||
|
for ( ; i < l; i++ ) {
|
||||||
|
transform = vendors[i] + 'ransform';
|
||||||
|
if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function _prefixStyle (style) {
|
||||||
|
if ( _vendor === false ) return false;
|
||||||
|
if ( _vendor === '' ) return style;
|
||||||
|
return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
me.getTime = Date.now || function getTime () { return new Date().getTime(); };
|
||||||
|
|
||||||
|
me.extend = function (target, obj) {
|
||||||
|
for ( var i in obj ) {
|
||||||
|
target[i] = obj[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
me.addEvent = function (el, type, fn, capture) {
|
||||||
|
el.addEventListener(type, fn, !!capture);
|
||||||
|
};
|
||||||
|
|
||||||
|
me.removeEvent = function (el, type, fn, capture) {
|
||||||
|
el.removeEventListener(type, fn, !!capture);
|
||||||
|
};
|
||||||
|
|
||||||
|
me.prefixPointerEvent = function (pointerEvent) {
|
||||||
|
return window.MSPointerEvent ?
|
||||||
|
'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10):
|
||||||
|
pointerEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
|
||||||
|
var distance = current - start,
|
||||||
|
speed = Math.abs(distance) / time,
|
||||||
|
destination,
|
||||||
|
duration;
|
||||||
|
|
||||||
|
deceleration = deceleration === undefined ? 0.0006 : deceleration;
|
||||||
|
|
||||||
|
destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
|
||||||
|
duration = speed / deceleration;
|
||||||
|
|
||||||
|
if ( destination < lowerMargin ) {
|
||||||
|
destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
|
||||||
|
distance = Math.abs(destination - current);
|
||||||
|
duration = distance / speed;
|
||||||
|
} else if ( destination > 0 ) {
|
||||||
|
destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
|
||||||
|
distance = Math.abs(current) + destination;
|
||||||
|
duration = distance / speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
destination: Math.round(destination),
|
||||||
|
duration: duration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _transform = _prefixStyle('transform');
|
||||||
|
|
||||||
|
me.extend(me, {
|
||||||
|
hasTransform: _transform !== false,
|
||||||
|
hasPerspective: _prefixStyle('perspective') in _elementStyle,
|
||||||
|
hasTouch: 'ontouchstart' in window,
|
||||||
|
hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed
|
||||||
|
hasTransition: _prefixStyle('transition') in _elementStyle
|
||||||
|
});
|
||||||
|
|
||||||
|
// This should find all Android browsers lower than build 535.19 (both stock browser and webview)
|
||||||
|
me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\/\d/.test(window.navigator.appVersion));
|
||||||
|
|
||||||
|
me.extend(me.style = {}, {
|
||||||
|
transform: _transform,
|
||||||
|
transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
|
||||||
|
transitionDuration: _prefixStyle('transitionDuration'),
|
||||||
|
transitionDelay: _prefixStyle('transitionDelay'),
|
||||||
|
transformOrigin: _prefixStyle('transformOrigin')
|
||||||
|
});
|
||||||
|
|
||||||
|
me.hasClass = function (e, c) {
|
||||||
|
var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
|
||||||
|
return re.test(e.className);
|
||||||
|
};
|
||||||
|
|
||||||
|
me.addClass = function (e, c) {
|
||||||
|
if ( me.hasClass(e, c) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newclass = e.className.split(' ');
|
||||||
|
newclass.push(c);
|
||||||
|
e.className = newclass.join(' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
me.removeClass = function (e, c) {
|
||||||
|
if ( !me.hasClass(e, c) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
|
||||||
|
e.className = e.className.replace(re, ' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
me.offset = function (el) {
|
||||||
|
var left = -el.offsetLeft,
|
||||||
|
top = -el.offsetTop;
|
||||||
|
|
||||||
|
// jshint -W084
|
||||||
|
while (el = el.offsetParent) {
|
||||||
|
left -= el.offsetLeft;
|
||||||
|
top -= el.offsetTop;
|
||||||
|
}
|
||||||
|
// jshint +W084
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: left,
|
||||||
|
top: top
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
me.preventDefaultException = function (el, exceptions) {
|
||||||
|
for ( var i in exceptions ) {
|
||||||
|
if ( exceptions[i].test(el[i]) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
me.extend(me.eventType = {}, {
|
||||||
|
touchstart: 1,
|
||||||
|
touchmove: 1,
|
||||||
|
touchend: 1,
|
||||||
|
|
||||||
|
mousedown: 2,
|
||||||
|
mousemove: 2,
|
||||||
|
mouseup: 2,
|
||||||
|
|
||||||
|
pointerdown: 3,
|
||||||
|
pointermove: 3,
|
||||||
|
pointerup: 3,
|
||||||
|
|
||||||
|
MSPointerDown: 3,
|
||||||
|
MSPointerMove: 3,
|
||||||
|
MSPointerUp: 3
|
||||||
|
});
|
||||||
|
|
||||||
|
me.extend(me.ease = {}, {
|
||||||
|
quadratic: {
|
||||||
|
style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
|
||||||
|
fn: function (k) {
|
||||||
|
return k * ( 2 - k );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
circular: {
|
||||||
|
style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
|
||||||
|
fn: function (k) {
|
||||||
|
return Math.sqrt( 1 - ( --k * k ) );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
back: {
|
||||||
|
style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
|
||||||
|
fn: function (k) {
|
||||||
|
var b = 4;
|
||||||
|
return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bounce: {
|
||||||
|
style: '',
|
||||||
|
fn: function (k) {
|
||||||
|
if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
|
||||||
|
return 7.5625 * k * k;
|
||||||
|
} else if ( k < ( 2 / 2.75 ) ) {
|
||||||
|
return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
|
||||||
|
} else if ( k < ( 2.5 / 2.75 ) ) {
|
||||||
|
return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
|
||||||
|
} else {
|
||||||
|
return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
elastic: {
|
||||||
|
style: '',
|
||||||
|
fn: function (k) {
|
||||||
|
var f = 0.22,
|
||||||
|
e = 0.4;
|
||||||
|
|
||||||
|
if ( k === 0 ) { return 0; }
|
||||||
|
if ( k == 1 ) { return 1; }
|
||||||
|
|
||||||
|
return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
me.tap = function (e, eventName) {
|
||||||
|
var ev = document.createEvent('Event');
|
||||||
|
ev.initEvent(eventName, true, true);
|
||||||
|
ev.pageX = e.pageX;
|
||||||
|
ev.pageY = e.pageY;
|
||||||
|
e.target.dispatchEvent(ev);
|
||||||
|
};
|
||||||
|
|
||||||
|
me.click = function (e) {
|
||||||
|
var target = e.target,
|
||||||
|
ev;
|
||||||
|
|
||||||
|
if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
|
||||||
|
ev = document.createEvent('MouseEvents');
|
||||||
|
ev.initMouseEvent('click', true, true, e.view, 1,
|
||||||
|
target.screenX, target.screenY, target.clientX, target.clientY,
|
||||||
|
e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
|
||||||
|
0, null);
|
||||||
|
|
||||||
|
ev._constructed = true;
|
||||||
|
target.dispatchEvent(ev);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return me;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function IScroll (el, options) {
|
||||||
|
this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
|
||||||
|
this.scroller = this.wrapper.children[0];
|
||||||
|
this.scrollerStyle = this.scroller.style; // cache style for better performance
|
||||||
|
|
||||||
|
this.options = {
|
||||||
|
|
||||||
|
// INSERT POINT: OPTIONS
|
||||||
|
|
||||||
|
startX: 0,
|
||||||
|
startY: 0,
|
||||||
|
scrollY: true,
|
||||||
|
directionLockThreshold: 5,
|
||||||
|
momentum: true,
|
||||||
|
|
||||||
|
bounce: true,
|
||||||
|
bounceTime: 600,
|
||||||
|
bounceEasing: '',
|
||||||
|
|
||||||
|
preventDefault: true,
|
||||||
|
preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },
|
||||||
|
|
||||||
|
HWCompositing: true,
|
||||||
|
useTransition: true,
|
||||||
|
useTransform: true
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( var i in options ) {
|
||||||
|
this.options[i] = options[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize options
|
||||||
|
this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
|
||||||
|
|
||||||
|
this.options.useTransition = utils.hasTransition && this.options.useTransition;
|
||||||
|
this.options.useTransform = utils.hasTransform && this.options.useTransform;
|
||||||
|
|
||||||
|
this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
|
||||||
|
this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
|
||||||
|
|
||||||
|
// If you want eventPassthrough I have to lock one of the axes
|
||||||
|
this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
|
||||||
|
this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
|
||||||
|
|
||||||
|
// With eventPassthrough we also need lockDirection mechanism
|
||||||
|
this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
|
||||||
|
this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
|
||||||
|
|
||||||
|
this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
|
||||||
|
|
||||||
|
this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
|
||||||
|
|
||||||
|
if ( this.options.tap === true ) {
|
||||||
|
this.options.tap = 'tap';
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSERT POINT: NORMALIZATION
|
||||||
|
|
||||||
|
// Some defaults
|
||||||
|
this.x = 0;
|
||||||
|
this.y = 0;
|
||||||
|
this.directionX = 0;
|
||||||
|
this.directionY = 0;
|
||||||
|
this._events = {};
|
||||||
|
|
||||||
|
// INSERT POINT: DEFAULTS
|
||||||
|
|
||||||
|
this._init();
|
||||||
|
this.refresh();
|
||||||
|
|
||||||
|
this.scrollTo(this.options.startX, this.options.startY);
|
||||||
|
this.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
IScroll.prototype = {
|
||||||
|
version: '5.1.3',
|
||||||
|
|
||||||
|
_init: function () {
|
||||||
|
this._initEvents();
|
||||||
|
|
||||||
|
// INSERT POINT: _init
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function () {
|
||||||
|
this._initEvents(true);
|
||||||
|
|
||||||
|
this._execEvent('destroy');
|
||||||
|
},
|
||||||
|
|
||||||
|
_transitionEnd: function (e) {
|
||||||
|
if ( e.target != this.scroller || !this.isInTransition ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._transitionTime();
|
||||||
|
if ( !this.resetPosition(this.options.bounceTime) ) {
|
||||||
|
this.isInTransition = false;
|
||||||
|
this._execEvent('scrollEnd');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_start: function (e) {
|
||||||
|
// React to left mouse button only
|
||||||
|
if ( utils.eventType[e.type] != 1 ) {
|
||||||
|
if ( e.button !== 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
var point = e.touches ? e.touches[0] : e,
|
||||||
|
pos;
|
||||||
|
|
||||||
|
this.initiated = utils.eventType[e.type];
|
||||||
|
this.moved = false;
|
||||||
|
this.distX = 0;
|
||||||
|
this.distY = 0;
|
||||||
|
this.directionX = 0;
|
||||||
|
this.directionY = 0;
|
||||||
|
this.directionLocked = 0;
|
||||||
|
|
||||||
|
this._transitionTime();
|
||||||
|
|
||||||
|
this.startTime = utils.getTime();
|
||||||
|
|
||||||
|
if ( this.options.useTransition && this.isInTransition ) {
|
||||||
|
this.isInTransition = false;
|
||||||
|
pos = this.getComputedPosition();
|
||||||
|
this._translate(Math.round(pos.x), Math.round(pos.y));
|
||||||
|
this._execEvent('scrollEnd');
|
||||||
|
} else if ( !this.options.useTransition && this.isAnimating ) {
|
||||||
|
this.isAnimating = false;
|
||||||
|
this._execEvent('scrollEnd');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startX = this.x;
|
||||||
|
this.startY = this.y;
|
||||||
|
this.absStartX = this.x;
|
||||||
|
this.absStartY = this.y;
|
||||||
|
this.pointX = point.pageX;
|
||||||
|
this.pointY = point.pageY;
|
||||||
|
|
||||||
|
this._execEvent('beforeScrollStart');
|
||||||
|
},
|
||||||
|
|
||||||
|
_move: function (e) {
|
||||||
|
if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.options.preventDefault ) { // increases performance on Android? TODO: check!
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
var point = e.touches ? e.touches[0] : e,
|
||||||
|
deltaX = point.pageX - this.pointX,
|
||||||
|
deltaY = point.pageY - this.pointY,
|
||||||
|
timestamp = utils.getTime(),
|
||||||
|
newX, newY,
|
||||||
|
absDistX, absDistY;
|
||||||
|
|
||||||
|
this.pointX = point.pageX;
|
||||||
|
this.pointY = point.pageY;
|
||||||
|
|
||||||
|
this.distX += deltaX;
|
||||||
|
this.distY += deltaY;
|
||||||
|
absDistX = Math.abs(this.distX);
|
||||||
|
absDistY = Math.abs(this.distY);
|
||||||
|
|
||||||
|
// We need to move at least 10 pixels for the scrolling to initiate
|
||||||
|
if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you are scrolling in one direction lock the other
|
||||||
|
if ( !this.directionLocked && !this.options.freeScroll ) {
|
||||||
|
if ( absDistX > absDistY + this.options.directionLockThreshold ) {
|
||||||
|
this.directionLocked = 'h'; // lock horizontally
|
||||||
|
} else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
|
||||||
|
this.directionLocked = 'v'; // lock vertically
|
||||||
|
} else {
|
||||||
|
this.directionLocked = 'n'; // no lock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.directionLocked == 'h' ) {
|
||||||
|
if ( this.options.eventPassthrough == 'vertical' ) {
|
||||||
|
e.preventDefault();
|
||||||
|
} else if ( this.options.eventPassthrough == 'horizontal' ) {
|
||||||
|
this.initiated = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltaY = 0;
|
||||||
|
} else if ( this.directionLocked == 'v' ) {
|
||||||
|
if ( this.options.eventPassthrough == 'horizontal' ) {
|
||||||
|
e.preventDefault();
|
||||||
|
} else if ( this.options.eventPassthrough == 'vertical' ) {
|
||||||
|
this.initiated = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltaX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltaX = this.hasHorizontalScroll ? deltaX : 0;
|
||||||
|
deltaY = this.hasVerticalScroll ? deltaY : 0;
|
||||||
|
|
||||||
|
newX = this.x + deltaX;
|
||||||
|
newY = this.y + deltaY;
|
||||||
|
|
||||||
|
// Slow down if outside of the boundaries
|
||||||
|
if ( newX > 0 || newX < this.maxScrollX ) {
|
||||||
|
newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
|
||||||
|
}
|
||||||
|
if ( newY > 0 || newY < this.maxScrollY ) {
|
||||||
|
newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
|
||||||
|
this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
|
||||||
|
|
||||||
|
if ( !this.moved ) {
|
||||||
|
this._execEvent('scrollStart');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moved = true;
|
||||||
|
|
||||||
|
this._translate(newX, newY);
|
||||||
|
|
||||||
|
/* REPLACE START: _move */
|
||||||
|
|
||||||
|
if ( timestamp - this.startTime > 300 ) {
|
||||||
|
this.startTime = timestamp;
|
||||||
|
this.startX = this.x;
|
||||||
|
this.startY = this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* REPLACE END: _move */
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_end: function (e) {
|
||||||
|
if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
var point = e.changedTouches ? e.changedTouches[0] : e,
|
||||||
|
momentumX,
|
||||||
|
momentumY,
|
||||||
|
duration = utils.getTime() - this.startTime,
|
||||||
|
newX = Math.round(this.x),
|
||||||
|
newY = Math.round(this.y),
|
||||||
|
distanceX = Math.abs(newX - this.startX),
|
||||||
|
distanceY = Math.abs(newY - this.startY),
|
||||||
|
time = 0,
|
||||||
|
easing = '';
|
||||||
|
|
||||||
|
this.isInTransition = 0;
|
||||||
|
this.initiated = 0;
|
||||||
|
this.endTime = utils.getTime();
|
||||||
|
|
||||||
|
// reset if we are outside of the boundaries
|
||||||
|
if ( this.resetPosition(this.options.bounceTime) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollTo(newX, newY); // ensures that the last position is rounded
|
||||||
|
|
||||||
|
// we scrolled less than 10 pixels
|
||||||
|
if ( !this.moved ) {
|
||||||
|
if ( this.options.tap ) {
|
||||||
|
utils.tap(e, this.options.tap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.options.click ) {
|
||||||
|
utils.click(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._execEvent('scrollCancel');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
|
||||||
|
this._execEvent('flick');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start momentum animation if needed
|
||||||
|
if ( this.options.momentum && duration < 300 ) {
|
||||||
|
momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };
|
||||||
|
momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };
|
||||||
|
newX = momentumX.destination;
|
||||||
|
newY = momentumY.destination;
|
||||||
|
time = Math.max(momentumX.duration, momentumY.duration);
|
||||||
|
this.isInTransition = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSERT POINT: _end
|
||||||
|
|
||||||
|
if ( newX != this.x || newY != this.y ) {
|
||||||
|
// change easing function when scroller goes out of the boundaries
|
||||||
|
if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
|
||||||
|
easing = utils.ease.quadratic;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollTo(newX, newY, time, easing);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._execEvent('scrollEnd');
|
||||||
|
},
|
||||||
|
|
||||||
|
_resize: function () {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
clearTimeout(this.resizeTimeout);
|
||||||
|
|
||||||
|
this.resizeTimeout = setTimeout(function () {
|
||||||
|
that.refresh();
|
||||||
|
}, this.options.resizePolling);
|
||||||
|
},
|
||||||
|
|
||||||
|
resetPosition: function (time) {
|
||||||
|
var x = this.x,
|
||||||
|
y = this.y;
|
||||||
|
|
||||||
|
time = time || 0;
|
||||||
|
|
||||||
|
if ( !this.hasHorizontalScroll || this.x > 0 ) {
|
||||||
|
x = 0;
|
||||||
|
} else if ( this.x < this.maxScrollX ) {
|
||||||
|
x = this.maxScrollX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !this.hasVerticalScroll || this.y > 0 ) {
|
||||||
|
y = 0;
|
||||||
|
} else if ( this.y < this.maxScrollY ) {
|
||||||
|
y = this.maxScrollY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( x == this.x && y == this.y ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollTo(x, y, time, this.options.bounceEasing);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: function () {
|
||||||
|
this.enabled = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
enable: function () {
|
||||||
|
this.enabled = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh: function () {
|
||||||
|
var rf = this.wrapper.offsetHeight; // Force reflow
|
||||||
|
|
||||||
|
this.wrapperWidth = this.wrapper.clientWidth;
|
||||||
|
this.wrapperHeight = this.wrapper.clientHeight;
|
||||||
|
|
||||||
|
/* REPLACE START: refresh */
|
||||||
|
|
||||||
|
this.scrollerWidth = this.scroller.offsetWidth;
|
||||||
|
this.scrollerHeight = this.scroller.offsetHeight;
|
||||||
|
|
||||||
|
this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
|
||||||
|
this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
|
||||||
|
|
||||||
|
/* REPLACE END: refresh */
|
||||||
|
|
||||||
|
this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
|
||||||
|
this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
|
||||||
|
|
||||||
|
if ( !this.hasHorizontalScroll ) {
|
||||||
|
this.maxScrollX = 0;
|
||||||
|
this.scrollerWidth = this.wrapperWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !this.hasVerticalScroll ) {
|
||||||
|
this.maxScrollY = 0;
|
||||||
|
this.scrollerHeight = this.wrapperHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.endTime = 0;
|
||||||
|
this.directionX = 0;
|
||||||
|
this.directionY = 0;
|
||||||
|
|
||||||
|
this.wrapperOffset = utils.offset(this.wrapper);
|
||||||
|
|
||||||
|
this._execEvent('refresh');
|
||||||
|
|
||||||
|
this.resetPosition();
|
||||||
|
|
||||||
|
// INSERT POINT: _refresh
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
on: function (type, fn) {
|
||||||
|
if ( !this._events[type] ) {
|
||||||
|
this._events[type] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this._events[type].push(fn);
|
||||||
|
},
|
||||||
|
|
||||||
|
off: function (type, fn) {
|
||||||
|
if ( !this._events[type] ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = this._events[type].indexOf(fn);
|
||||||
|
|
||||||
|
if ( index > -1 ) {
|
||||||
|
this._events[type].splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_execEvent: function (type) {
|
||||||
|
if ( !this._events[type] ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = 0,
|
||||||
|
l = this._events[type].length;
|
||||||
|
|
||||||
|
if ( !l ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; i < l; i++ ) {
|
||||||
|
this._events[type][i].apply(this, [].slice.call(arguments, 1));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollBy: function (x, y, time, easing) {
|
||||||
|
x = this.x + x;
|
||||||
|
y = this.y + y;
|
||||||
|
time = time || 0;
|
||||||
|
|
||||||
|
this.scrollTo(x, y, time, easing);
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollTo: function (x, y, time, easing) {
|
||||||
|
easing = easing || utils.ease.circular;
|
||||||
|
|
||||||
|
this.isInTransition = this.options.useTransition && time > 0;
|
||||||
|
|
||||||
|
if ( !time || (this.options.useTransition && easing.style) ) {
|
||||||
|
this._transitionTimingFunction(easing.style);
|
||||||
|
this._transitionTime(time);
|
||||||
|
this._translate(x, y);
|
||||||
|
} else {
|
||||||
|
this._animate(x, y, time, easing.fn);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollToElement: function (el, time, offsetX, offsetY, easing) {
|
||||||
|
el = el.nodeType ? el : this.scroller.querySelector(el);
|
||||||
|
|
||||||
|
if ( !el ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pos = utils.offset(el);
|
||||||
|
|
||||||
|
pos.left -= this.wrapperOffset.left;
|
||||||
|
pos.top -= this.wrapperOffset.top;
|
||||||
|
|
||||||
|
// if offsetX/Y are true we center the element to the screen
|
||||||
|
if ( offsetX === true ) {
|
||||||
|
offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
|
||||||
|
}
|
||||||
|
if ( offsetY === true ) {
|
||||||
|
offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.left -= offsetX || 0;
|
||||||
|
pos.top -= offsetY || 0;
|
||||||
|
|
||||||
|
pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
|
||||||
|
pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;
|
||||||
|
|
||||||
|
time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
|
||||||
|
|
||||||
|
this.scrollTo(pos.left, pos.top, time, easing);
|
||||||
|
},
|
||||||
|
|
||||||
|
_transitionTime: function (time) {
|
||||||
|
time = time || 0;
|
||||||
|
|
||||||
|
this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';
|
||||||
|
|
||||||
|
if ( !time && utils.isBadAndroid ) {
|
||||||
|
this.scrollerStyle[utils.style.transitionDuration] = '0.001s';
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSERT POINT: _transitionTime
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_transitionTimingFunction: function (easing) {
|
||||||
|
this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
|
||||||
|
|
||||||
|
// INSERT POINT: _transitionTimingFunction
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_translate: function (x, y) {
|
||||||
|
if ( this.options.useTransform ) {
|
||||||
|
|
||||||
|
/* REPLACE START: _translate */
|
||||||
|
|
||||||
|
this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
|
||||||
|
|
||||||
|
/* REPLACE END: _translate */
|
||||||
|
|
||||||
|
} else {
|
||||||
|
x = Math.round(x);
|
||||||
|
y = Math.round(y);
|
||||||
|
this.scrollerStyle.left = x + 'px';
|
||||||
|
this.scrollerStyle.top = y + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
|
||||||
|
// INSERT POINT: _translate
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_initEvents: function (remove) {
|
||||||
|
var eventType = remove ? utils.removeEvent : utils.addEvent,
|
||||||
|
target = this.options.bindToWrapper ? this.wrapper : window;
|
||||||
|
|
||||||
|
eventType(window, 'orientationchange', this);
|
||||||
|
eventType(window, 'resize', this);
|
||||||
|
|
||||||
|
if ( this.options.click ) {
|
||||||
|
eventType(this.wrapper, 'click', this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !this.options.disableMouse ) {
|
||||||
|
eventType(this.wrapper, 'mousedown', this);
|
||||||
|
eventType(target, 'mousemove', this);
|
||||||
|
eventType(target, 'mousecancel', this);
|
||||||
|
eventType(target, 'mouseup', this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( utils.hasPointer && !this.options.disablePointer ) {
|
||||||
|
eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
|
||||||
|
eventType(target, utils.prefixPointerEvent('pointermove'), this);
|
||||||
|
eventType(target, utils.prefixPointerEvent('pointercancel'), this);
|
||||||
|
eventType(target, utils.prefixPointerEvent('pointerup'), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( utils.hasTouch && !this.options.disableTouch ) {
|
||||||
|
eventType(this.wrapper, 'touchstart', this);
|
||||||
|
eventType(target, 'touchmove', this);
|
||||||
|
eventType(target, 'touchcancel', this);
|
||||||
|
eventType(target, 'touchend', this);
|
||||||
|
}
|
||||||
|
|
||||||
|
eventType(this.scroller, 'transitionend', this);
|
||||||
|
eventType(this.scroller, 'webkitTransitionEnd', this);
|
||||||
|
eventType(this.scroller, 'oTransitionEnd', this);
|
||||||
|
eventType(this.scroller, 'MSTransitionEnd', this);
|
||||||
|
},
|
||||||
|
|
||||||
|
getComputedPosition: function () {
|
||||||
|
var matrix = window.getComputedStyle(this.scroller, null),
|
||||||
|
x, y;
|
||||||
|
|
||||||
|
if ( this.options.useTransform ) {
|
||||||
|
matrix = matrix[utils.style.transform].split(')')[0].split(', ');
|
||||||
|
x = +(matrix[12] || matrix[4]);
|
||||||
|
y = +(matrix[13] || matrix[5]);
|
||||||
|
} else {
|
||||||
|
x = +matrix.left.replace(/[^-\d.]/g, '');
|
||||||
|
y = +matrix.top.replace(/[^-\d.]/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return { x: x, y: y };
|
||||||
|
},
|
||||||
|
|
||||||
|
_animate: function (destX, destY, duration, easingFn) {
|
||||||
|
var that = this,
|
||||||
|
startX = this.x,
|
||||||
|
startY = this.y,
|
||||||
|
startTime = utils.getTime(),
|
||||||
|
destTime = startTime + duration;
|
||||||
|
|
||||||
|
function step () {
|
||||||
|
var now = utils.getTime(),
|
||||||
|
newX, newY,
|
||||||
|
easing;
|
||||||
|
|
||||||
|
if ( now >= destTime ) {
|
||||||
|
that.isAnimating = false;
|
||||||
|
that._translate(destX, destY);
|
||||||
|
|
||||||
|
if ( !that.resetPosition(that.options.bounceTime) ) {
|
||||||
|
that._execEvent('scrollEnd');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
now = ( now - startTime ) / duration;
|
||||||
|
easing = easingFn(now);
|
||||||
|
newX = ( destX - startX ) * easing + startX;
|
||||||
|
newY = ( destY - startY ) * easing + startY;
|
||||||
|
that._translate(newX, newY);
|
||||||
|
|
||||||
|
if ( that.isAnimating ) {
|
||||||
|
rAF(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isAnimating = true;
|
||||||
|
step();
|
||||||
|
},
|
||||||
|
handleEvent: function (e) {
|
||||||
|
switch ( e.type ) {
|
||||||
|
case 'touchstart':
|
||||||
|
case 'pointerdown':
|
||||||
|
case 'MSPointerDown':
|
||||||
|
case 'mousedown':
|
||||||
|
this._start(e);
|
||||||
|
break;
|
||||||
|
case 'touchmove':
|
||||||
|
case 'pointermove':
|
||||||
|
case 'MSPointerMove':
|
||||||
|
case 'mousemove':
|
||||||
|
this._move(e);
|
||||||
|
break;
|
||||||
|
case 'touchend':
|
||||||
|
case 'pointerup':
|
||||||
|
case 'MSPointerUp':
|
||||||
|
case 'mouseup':
|
||||||
|
case 'touchcancel':
|
||||||
|
case 'pointercancel':
|
||||||
|
case 'MSPointerCancel':
|
||||||
|
case 'mousecancel':
|
||||||
|
this._end(e);
|
||||||
|
break;
|
||||||
|
case 'orientationchange':
|
||||||
|
case 'resize':
|
||||||
|
this._resize();
|
||||||
|
break;
|
||||||
|
case 'transitionend':
|
||||||
|
case 'webkitTransitionEnd':
|
||||||
|
case 'oTransitionEnd':
|
||||||
|
case 'MSTransitionEnd':
|
||||||
|
this._transitionEnd(e);
|
||||||
|
break;
|
||||||
|
case 'wheel':
|
||||||
|
case 'DOMMouseScroll':
|
||||||
|
case 'mousewheel':
|
||||||
|
this._wheel(e);
|
||||||
|
break;
|
||||||
|
case 'keydown':
|
||||||
|
this._key(e);
|
||||||
|
break;
|
||||||
|
case 'click':
|
||||||
|
if ( !e._constructed ) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
IScroll.utils = utils;
|
||||||
|
|
||||||
|
if ( typeof module != 'undefined' && module.exports ) {
|
||||||
|
module.exports = IScroll;
|
||||||
|
} else {
|
||||||
|
window.IScroll = IScroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
})(window, document, Math);
|
2038
sorcery/iscroll-probe.js
Normal file
2195
sorcery/iscroll-zoom.js
Normal file
2011
sorcery/iscroll.js
Normal file
4
sorcery/jquery-1.11.2.min.js
vendored
Normal file
564
sorcery/jquery.parallax.js
Normal file
@ -0,0 +1,564 @@
|
|||||||
|
//============================================================
|
||||||
|
//
|
||||||
|
// The MIT License
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014 Matthew Wagerfield - @wagerfield
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any
|
||||||
|
// person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the
|
||||||
|
// Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
// sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice
|
||||||
|
// shall be included in all copies or substantial portions
|
||||||
|
// of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
|
||||||
|
// OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
|
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||||
|
// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
// OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery || Zepto Parallax Plugin
|
||||||
|
* @author Matthew Wagerfield - @wagerfield
|
||||||
|
* @description Creates a parallax effect between an array of layers,
|
||||||
|
* driving the motion from the gyroscope output of a smartdevice.
|
||||||
|
* If no gyroscope is available, the cursor position is used.
|
||||||
|
*/
|
||||||
|
;(function($, window, document, undefined) {
|
||||||
|
|
||||||
|
// Strict Mode
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
var NAME = 'parallax';
|
||||||
|
var MAGIC_NUMBER = 30;
|
||||||
|
var DEFAULTS = {
|
||||||
|
relativeInput: false,
|
||||||
|
clipRelativeInput: false,
|
||||||
|
calibrationThreshold: 100,
|
||||||
|
calibrationDelay: 500,
|
||||||
|
supportDelay: 500,
|
||||||
|
calibrateX: false,
|
||||||
|
calibrateY: true,
|
||||||
|
invertX: true,
|
||||||
|
invertY: true,
|
||||||
|
limitX: false,
|
||||||
|
limitY: false,
|
||||||
|
scalarX: 10.0,
|
||||||
|
scalarY: 10.0,
|
||||||
|
frictionX: 0.1,
|
||||||
|
frictionY: 0.1,
|
||||||
|
originX: 0.5,
|
||||||
|
originY: 0.5
|
||||||
|
};
|
||||||
|
|
||||||
|
function Plugin(element, options) {
|
||||||
|
|
||||||
|
// DOM Context
|
||||||
|
this.element = element;
|
||||||
|
|
||||||
|
// Selections
|
||||||
|
this.$context = $(element).data('api', this);
|
||||||
|
this.$layers = this.$context.find('.layer');
|
||||||
|
|
||||||
|
// Data Extraction
|
||||||
|
var data = {
|
||||||
|
calibrateX: this.$context.data('calibrate-x') || null,
|
||||||
|
calibrateY: this.$context.data('calibrate-y') || null,
|
||||||
|
invertX: this.$context.data('invert-x') || null,
|
||||||
|
invertY: this.$context.data('invert-y') || null,
|
||||||
|
limitX: parseFloat(this.$context.data('limit-x')) || null,
|
||||||
|
limitY: parseFloat(this.$context.data('limit-y')) || null,
|
||||||
|
scalarX: parseFloat(this.$context.data('scalar-x')) || null,
|
||||||
|
scalarY: parseFloat(this.$context.data('scalar-y')) || null,
|
||||||
|
frictionX: parseFloat(this.$context.data('friction-x')) || null,
|
||||||
|
frictionY: parseFloat(this.$context.data('friction-y')) || null,
|
||||||
|
originX: parseFloat(this.$context.data('origin-x')) || null,
|
||||||
|
originY: parseFloat(this.$context.data('origin-y')) || null
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete Null Data Values
|
||||||
|
for (var key in data) {
|
||||||
|
if (data[key] === null) delete data[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compose Settings Object
|
||||||
|
$.extend(this, DEFAULTS, options, data);
|
||||||
|
|
||||||
|
// States
|
||||||
|
this.calibrationTimer = null;
|
||||||
|
this.calibrationFlag = true;
|
||||||
|
this.enabled = false;
|
||||||
|
this.depths = [];
|
||||||
|
this.raf = null;
|
||||||
|
|
||||||
|
// Element Bounds
|
||||||
|
this.bounds = null;
|
||||||
|
this.ex = 0;
|
||||||
|
this.ey = 0;
|
||||||
|
this.ew = 0;
|
||||||
|
this.eh = 0;
|
||||||
|
|
||||||
|
// Element Center
|
||||||
|
this.ecx = 0;
|
||||||
|
this.ecy = 0;
|
||||||
|
|
||||||
|
// Element Range
|
||||||
|
this.erx = 0;
|
||||||
|
this.ery = 0;
|
||||||
|
|
||||||
|
// Calibration
|
||||||
|
this.cx = 0;
|
||||||
|
this.cy = 0;
|
||||||
|
|
||||||
|
// Input
|
||||||
|
this.ix = 0;
|
||||||
|
this.iy = 0;
|
||||||
|
|
||||||
|
// Motion
|
||||||
|
this.mx = 0;
|
||||||
|
this.my = 0;
|
||||||
|
|
||||||
|
// Velocity
|
||||||
|
this.vx = 0;
|
||||||
|
this.vy = 0;
|
||||||
|
|
||||||
|
// Callbacks
|
||||||
|
this.onMouseMove = this.onMouseMove.bind(this);
|
||||||
|
this.onDeviceOrientation = this.onDeviceOrientation.bind(this);
|
||||||
|
this.onOrientationTimer = this.onOrientationTimer.bind(this);
|
||||||
|
this.onCalibrationTimer = this.onCalibrationTimer.bind(this);
|
||||||
|
this.onAnimationFrame = this.onAnimationFrame.bind(this);
|
||||||
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
|
|
||||||
|
// Initialise
|
||||||
|
this.initialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.transformSupport = function(value) {
|
||||||
|
var element = document.createElement('div');
|
||||||
|
var propertySupport = false;
|
||||||
|
var propertyValue = null;
|
||||||
|
var featureSupport = false;
|
||||||
|
var cssProperty = null;
|
||||||
|
var jsProperty = null;
|
||||||
|
for (var i = 0, l = this.vendors.length; i < l; i++) {
|
||||||
|
if (this.vendors[i] !== null) {
|
||||||
|
cssProperty = this.vendors[i][0] + 'transform';
|
||||||
|
jsProperty = this.vendors[i][1] + 'Transform';
|
||||||
|
} else {
|
||||||
|
cssProperty = 'transform';
|
||||||
|
jsProperty = 'transform';
|
||||||
|
}
|
||||||
|
if (element.style[jsProperty] !== undefined) {
|
||||||
|
propertySupport = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(value) {
|
||||||
|
case '2D':
|
||||||
|
featureSupport = propertySupport;
|
||||||
|
break;
|
||||||
|
case '3D':
|
||||||
|
if (propertySupport) {
|
||||||
|
var body = document.body || document.createElement('body');
|
||||||
|
var documentElement = document.documentElement;
|
||||||
|
var documentOverflow = documentElement.style.overflow;
|
||||||
|
if (!document.body) {
|
||||||
|
documentElement.style.overflow = 'hidden';
|
||||||
|
documentElement.appendChild(body);
|
||||||
|
body.style.overflow = 'hidden';
|
||||||
|
body.style.background = '';
|
||||||
|
}
|
||||||
|
body.appendChild(element);
|
||||||
|
element.style[jsProperty] = 'translate3d(1px,1px,1px)';
|
||||||
|
propertyValue = window.getComputedStyle(element).getPropertyValue(cssProperty);
|
||||||
|
featureSupport = propertyValue !== undefined && propertyValue.length > 0 && propertyValue !== "none";
|
||||||
|
documentElement.style.overflow = documentOverflow;
|
||||||
|
body.removeChild(element);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return featureSupport;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.ww = null;
|
||||||
|
Plugin.prototype.wh = null;
|
||||||
|
Plugin.prototype.wcx = null;
|
||||||
|
Plugin.prototype.wcy = null;
|
||||||
|
Plugin.prototype.wrx = null;
|
||||||
|
Plugin.prototype.wry = null;
|
||||||
|
Plugin.prototype.portrait = null;
|
||||||
|
Plugin.prototype.desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i);
|
||||||
|
Plugin.prototype.vendors = [null,['-webkit-','webkit'],['-moz-','Moz'],['-o-','O'],['-ms-','ms']];
|
||||||
|
Plugin.prototype.motionSupport = !!window.DeviceMotionEvent;
|
||||||
|
Plugin.prototype.orientationSupport = !!window.DeviceOrientationEvent;
|
||||||
|
Plugin.prototype.orientationStatus = 0;
|
||||||
|
Plugin.prototype.transform2DSupport = Plugin.prototype.transformSupport('2D');
|
||||||
|
Plugin.prototype.transform3DSupport = Plugin.prototype.transformSupport('3D');
|
||||||
|
Plugin.prototype.propertyCache = {};
|
||||||
|
|
||||||
|
Plugin.prototype.initialise = function() {
|
||||||
|
|
||||||
|
// Configure Styles
|
||||||
|
if (this.$context.css('position') === 'static') {
|
||||||
|
this.$context.css({
|
||||||
|
position:'relative'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardware Accelerate Context
|
||||||
|
this.accelerate(this.$context);
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
this.updateLayers();
|
||||||
|
this.updateDimensions();
|
||||||
|
this.enable();
|
||||||
|
this.queueCalibration(this.calibrationDelay);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.updateLayers = function() {
|
||||||
|
|
||||||
|
// Cache Layer Elements
|
||||||
|
this.$layers = this.$context.find('.layer');
|
||||||
|
this.depths = [];
|
||||||
|
|
||||||
|
// Configure Layer Styles
|
||||||
|
this.$layers.css({
|
||||||
|
position:'absolute',
|
||||||
|
display:'block',
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
});
|
||||||
|
this.$layers.first().css({
|
||||||
|
position:'relative'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hardware Accelerate Layers
|
||||||
|
this.accelerate(this.$layers);
|
||||||
|
|
||||||
|
// Cache Depths
|
||||||
|
this.$layers.each($.proxy(function(index, element) {
|
||||||
|
this.depths.push($(element).data('depth') || 0);
|
||||||
|
}, this));
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.updateDimensions = function() {
|
||||||
|
this.ww = window.innerWidth;
|
||||||
|
this.wh = window.innerHeight;
|
||||||
|
this.wcx = this.ww * this.originX;
|
||||||
|
this.wcy = this.wh * this.originY;
|
||||||
|
this.wrx = Math.max(this.wcx, this.ww - this.wcx);
|
||||||
|
this.wry = Math.max(this.wcy, this.wh - this.wcy);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.updateBounds = function() {
|
||||||
|
this.bounds = this.element.getBoundingClientRect();
|
||||||
|
this.ex = this.bounds.left;
|
||||||
|
this.ey = this.bounds.top;
|
||||||
|
this.ew = this.bounds.width;
|
||||||
|
this.eh = this.bounds.height;
|
||||||
|
this.ecx = this.ew * this.originX;
|
||||||
|
this.ecy = this.eh * this.originY;
|
||||||
|
this.erx = Math.max(this.ecx, this.ew - this.ecx);
|
||||||
|
this.ery = Math.max(this.ecy, this.eh - this.ecy);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.queueCalibration = function(delay) {
|
||||||
|
clearTimeout(this.calibrationTimer);
|
||||||
|
this.calibrationTimer = setTimeout(this.onCalibrationTimer, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.enable = function() {
|
||||||
|
if (!this.enabled) {
|
||||||
|
this.enabled = true;
|
||||||
|
if (this.orientationSupport) {
|
||||||
|
this.portrait = null;
|
||||||
|
window.addEventListener('deviceorientation', this.onDeviceOrientation);
|
||||||
|
setTimeout(this.onOrientationTimer, this.supportDelay);
|
||||||
|
} else {
|
||||||
|
this.cx = 0;
|
||||||
|
this.cy = 0;
|
||||||
|
this.portrait = false;
|
||||||
|
window.addEventListener('mousemove', this.onMouseMove);
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', this.onWindowResize);
|
||||||
|
this.raf = requestAnimationFrame(this.onAnimationFrame);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.disable = function() {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.enabled = false;
|
||||||
|
if (this.orientationSupport) {
|
||||||
|
window.removeEventListener('deviceorientation', this.onDeviceOrientation);
|
||||||
|
} else {
|
||||||
|
window.removeEventListener('mousemove', this.onMouseMove);
|
||||||
|
}
|
||||||
|
window.removeEventListener('resize', this.onWindowResize);
|
||||||
|
cancelAnimationFrame(this.raf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.calibrate = function(x, y) {
|
||||||
|
this.calibrateX = x === undefined ? this.calibrateX : x;
|
||||||
|
this.calibrateY = y === undefined ? this.calibrateY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.invert = function(x, y) {
|
||||||
|
this.invertX = x === undefined ? this.invertX : x;
|
||||||
|
this.invertY = y === undefined ? this.invertY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.friction = function(x, y) {
|
||||||
|
this.frictionX = x === undefined ? this.frictionX : x;
|
||||||
|
this.frictionY = y === undefined ? this.frictionY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.scalar = function(x, y) {
|
||||||
|
this.scalarX = x === undefined ? this.scalarX : x;
|
||||||
|
this.scalarY = y === undefined ? this.scalarY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.limit = function(x, y) {
|
||||||
|
this.limitX = x === undefined ? this.limitX : x;
|
||||||
|
this.limitY = y === undefined ? this.limitY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.origin = function(x, y) {
|
||||||
|
this.originX = x === undefined ? this.originX : x;
|
||||||
|
this.originY = y === undefined ? this.originY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.clamp = function(value, min, max) {
|
||||||
|
value = Math.max(value, min);
|
||||||
|
value = Math.min(value, max);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.css = function(element, property, value) {
|
||||||
|
var jsProperty = this.propertyCache[property];
|
||||||
|
if (!jsProperty) {
|
||||||
|
for (var i = 0, l = this.vendors.length; i < l; i++) {
|
||||||
|
if (this.vendors[i] !== null) {
|
||||||
|
jsProperty = $.camelCase(this.vendors[i][1] + '-' + property);
|
||||||
|
} else {
|
||||||
|
jsProperty = property;
|
||||||
|
}
|
||||||
|
if (element.style[jsProperty] !== undefined) {
|
||||||
|
this.propertyCache[property] = jsProperty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
element.style[jsProperty] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.accelerate = function($element) {
|
||||||
|
for (var i = 0, l = $element.length; i < l; i++) {
|
||||||
|
var element = $element[i];
|
||||||
|
this.css(element, 'transform', 'translate3d(0,0,0)');
|
||||||
|
this.css(element, 'transform-style', 'preserve-3d');
|
||||||
|
this.css(element, 'backface-visibility', 'hidden');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.setPosition = function(element, x, y) {
|
||||||
|
x += 'px';
|
||||||
|
y += 'px';
|
||||||
|
if (this.transform3DSupport) {
|
||||||
|
this.css(element, 'transform', 'translate3d('+x+','+y+',0)');
|
||||||
|
} else if (this.transform2DSupport) {
|
||||||
|
this.css(element, 'transform', 'translate('+x+','+y+')');
|
||||||
|
} else {
|
||||||
|
element.style.left = x;
|
||||||
|
element.style.top = y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.onOrientationTimer = function(event) {
|
||||||
|
if (this.orientationSupport && this.orientationStatus === 0) {
|
||||||
|
this.disable();
|
||||||
|
this.orientationSupport = false;
|
||||||
|
this.enable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.onCalibrationTimer = function(event) {
|
||||||
|
this.calibrationFlag = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.onWindowResize = function(event) {
|
||||||
|
this.updateDimensions();
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.onAnimationFrame = function() {
|
||||||
|
this.updateBounds();
|
||||||
|
var dx = this.ix - this.cx;
|
||||||
|
var dy = this.iy - this.cy;
|
||||||
|
if ((Math.abs(dx) > this.calibrationThreshold) || (Math.abs(dy) > this.calibrationThreshold)) {
|
||||||
|
this.queueCalibration(0);
|
||||||
|
}
|
||||||
|
if (this.portrait) {
|
||||||
|
this.mx = this.calibrateX ? dy : this.iy;
|
||||||
|
this.my = this.calibrateY ? dx : this.ix;
|
||||||
|
} else {
|
||||||
|
this.mx = this.calibrateX ? dx : this.ix;
|
||||||
|
this.my = this.calibrateY ? dy : this.iy;
|
||||||
|
}
|
||||||
|
this.mx *= this.ew * (this.scalarX / 100);
|
||||||
|
this.my *= this.eh * (this.scalarY / 100);
|
||||||
|
if (!isNaN(parseFloat(this.limitX))) {
|
||||||
|
this.mx = this.clamp(this.mx, -this.limitX, this.limitX);
|
||||||
|
}
|
||||||
|
if (!isNaN(parseFloat(this.limitY))) {
|
||||||
|
this.my = this.clamp(this.my, -this.limitY, this.limitY);
|
||||||
|
}
|
||||||
|
this.vx += (this.mx - this.vx) * this.frictionX;
|
||||||
|
this.vy += (this.my - this.vy) * this.frictionY;
|
||||||
|
for (var i = 0, l = this.$layers.length; i < l; i++) {
|
||||||
|
var depth = this.depths[i];
|
||||||
|
var layer = this.$layers[i];
|
||||||
|
var xOffset = this.vx * depth * (this.invertX ? -1 : 1);
|
||||||
|
var yOffset = this.vy * depth * (this.invertY ? -1 : 1);
|
||||||
|
this.setPosition(layer, xOffset, yOffset);
|
||||||
|
}
|
||||||
|
this.raf = requestAnimationFrame(this.onAnimationFrame);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.onDeviceOrientation = function(event) {
|
||||||
|
|
||||||
|
// Validate environment and event properties.
|
||||||
|
if (!this.desktop && event.beta !== null && event.gamma !== null) {
|
||||||
|
|
||||||
|
// Set orientation status.
|
||||||
|
this.orientationStatus = 1;
|
||||||
|
|
||||||
|
// Extract Rotation
|
||||||
|
var x = (event.beta || 0) / MAGIC_NUMBER; // -90 :: 90
|
||||||
|
var y = (event.gamma || 0) / MAGIC_NUMBER; // -180 :: 180
|
||||||
|
|
||||||
|
// Detect Orientation Change
|
||||||
|
var portrait = window.innerHeight > window.innerWidth;
|
||||||
|
if (this.portrait !== portrait) {
|
||||||
|
this.portrait = portrait;
|
||||||
|
this.calibrationFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Calibration
|
||||||
|
if (this.calibrationFlag) {
|
||||||
|
this.calibrationFlag = false;
|
||||||
|
this.cx = x;
|
||||||
|
this.cy = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Input
|
||||||
|
this.ix = x;
|
||||||
|
this.iy = y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.onMouseMove = function(event) {
|
||||||
|
|
||||||
|
// Cache mouse coordinates.
|
||||||
|
var clientX = event.clientX;
|
||||||
|
var clientY = event.clientY;
|
||||||
|
|
||||||
|
// Calculate Mouse Input
|
||||||
|
if (!this.orientationSupport && this.relativeInput) {
|
||||||
|
|
||||||
|
// Clip mouse coordinates inside element bounds.
|
||||||
|
if (this.clipRelativeInput) {
|
||||||
|
clientX = Math.max(clientX, this.ex);
|
||||||
|
clientX = Math.min(clientX, this.ex + this.ew);
|
||||||
|
clientY = Math.max(clientY, this.ey);
|
||||||
|
clientY = Math.min(clientY, this.ey + this.eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate input relative to the element.
|
||||||
|
this.ix = (clientX - this.ex - this.ecx) / this.erx;
|
||||||
|
this.iy = (clientY - this.ey - this.ecy) / this.ery;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Calculate input relative to the window.
|
||||||
|
this.ix = (clientX - this.wcx) / this.wrx;
|
||||||
|
this.iy = (clientY - this.wcy) / this.wry;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var API = {
|
||||||
|
enable: Plugin.prototype.enable,
|
||||||
|
disable: Plugin.prototype.disable,
|
||||||
|
updateLayers: Plugin.prototype.updateLayers,
|
||||||
|
calibrate: Plugin.prototype.calibrate,
|
||||||
|
friction: Plugin.prototype.friction,
|
||||||
|
invert: Plugin.prototype.invert,
|
||||||
|
scalar: Plugin.prototype.scalar,
|
||||||
|
limit: Plugin.prototype.limit,
|
||||||
|
origin: Plugin.prototype.origin
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn[NAME] = function (value) {
|
||||||
|
var args = arguments;
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this);
|
||||||
|
var plugin = $this.data(NAME);
|
||||||
|
if (!plugin) {
|
||||||
|
plugin = new Plugin(this, value);
|
||||||
|
$this.data(NAME, plugin);
|
||||||
|
}
|
||||||
|
if (API[value]) {
|
||||||
|
plugin[value].apply(plugin, Array.prototype.slice.call(args, 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
})(window.jQuery || window.Zepto, window, document);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request Animation Frame Polyfill.
|
||||||
|
* @author Tino Zijdel
|
||||||
|
* @author Paul Irish
|
||||||
|
* @see https://gist.github.com/paulirish/1579671
|
||||||
|
*/
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
var lastTime = 0;
|
||||||
|
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
||||||
|
|
||||||
|
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||||
|
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
|
||||||
|
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.requestAnimationFrame) {
|
||||||
|
window.requestAnimationFrame = function(callback, element) {
|
||||||
|
var currTime = new Date().getTime();
|
||||||
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||||
|
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
|
||||||
|
timeToCall);
|
||||||
|
lastTime = currTime + timeToCall;
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.cancelAnimationFrame) {
|
||||||
|
window.cancelAnimationFrame = function(id) {
|
||||||
|
clearTimeout(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}());
|
1
sorcery/jquery.parallax.min.js
vendored
Normal file
561
sorcery/parallax.js
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
//============================================================
|
||||||
|
//
|
||||||
|
// The MIT License
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014 Matthew Wagerfield - @wagerfield
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any
|
||||||
|
// person obtaining a copy of this software and associated
|
||||||
|
// documentation files (the "Software"), to deal in the
|
||||||
|
// Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
// sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice
|
||||||
|
// shall be included in all copies or substantial portions
|
||||||
|
// of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
|
||||||
|
// OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
|
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||||
|
// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
// OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parallax.js
|
||||||
|
* @author Matthew Wagerfield - @wagerfield
|
||||||
|
* @description Creates a parallax effect between an array of layers,
|
||||||
|
* driving the motion from the gyroscope output of a smartdevice.
|
||||||
|
* If no gyroscope is available, the cursor position is used.
|
||||||
|
*/
|
||||||
|
;(function(window, document, undefined) {
|
||||||
|
|
||||||
|
// Strict Mode
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
var NAME = 'Parallax';
|
||||||
|
var MAGIC_NUMBER = 30;
|
||||||
|
var DEFAULTS = {
|
||||||
|
relativeInput: false,
|
||||||
|
clipRelativeInput: false,
|
||||||
|
calibrationThreshold: 100,
|
||||||
|
calibrationDelay: 500,
|
||||||
|
supportDelay: 500,
|
||||||
|
calibrateX: false,
|
||||||
|
calibrateY: true,
|
||||||
|
invertX: true,
|
||||||
|
invertY: true,
|
||||||
|
limitX: false,
|
||||||
|
limitY: false,
|
||||||
|
scalarX: 10.0,
|
||||||
|
scalarY: 10.0,
|
||||||
|
frictionX: 0.1,
|
||||||
|
frictionY: 0.1,
|
||||||
|
originX: 0.5,
|
||||||
|
originY: 0.5
|
||||||
|
};
|
||||||
|
|
||||||
|
function Parallax(element, options) {
|
||||||
|
|
||||||
|
// DOM Context
|
||||||
|
this.element = element;
|
||||||
|
this.layers = element.getElementsByClassName('layer');
|
||||||
|
|
||||||
|
// Data Extraction
|
||||||
|
var data = {
|
||||||
|
calibrateX: this.data(this.element, 'calibrate-x'),
|
||||||
|
calibrateY: this.data(this.element, 'calibrate-y'),
|
||||||
|
invertX: this.data(this.element, 'invert-x'),
|
||||||
|
invertY: this.data(this.element, 'invert-y'),
|
||||||
|
limitX: this.data(this.element, 'limit-x'),
|
||||||
|
limitY: this.data(this.element, 'limit-y'),
|
||||||
|
scalarX: this.data(this.element, 'scalar-x'),
|
||||||
|
scalarY: this.data(this.element, 'scalar-y'),
|
||||||
|
frictionX: this.data(this.element, 'friction-x'),
|
||||||
|
frictionY: this.data(this.element, 'friction-y'),
|
||||||
|
originX: this.data(this.element, 'origin-x'),
|
||||||
|
originY: this.data(this.element, 'origin-y')
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete Null Data Values
|
||||||
|
for (var key in data) {
|
||||||
|
if (data[key] === null) delete data[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compose Settings Object
|
||||||
|
this.extend(this, DEFAULTS, options, data);
|
||||||
|
|
||||||
|
// States
|
||||||
|
this.calibrationTimer = null;
|
||||||
|
this.calibrationFlag = true;
|
||||||
|
this.enabled = false;
|
||||||
|
this.depths = [];
|
||||||
|
this.raf = null;
|
||||||
|
|
||||||
|
// Element Bounds
|
||||||
|
this.bounds = null;
|
||||||
|
this.ex = 0;
|
||||||
|
this.ey = 0;
|
||||||
|
this.ew = 0;
|
||||||
|
this.eh = 0;
|
||||||
|
|
||||||
|
// Element Center
|
||||||
|
this.ecx = 0;
|
||||||
|
this.ecy = 0;
|
||||||
|
|
||||||
|
// Element Range
|
||||||
|
this.erx = 0;
|
||||||
|
this.ery = 0;
|
||||||
|
|
||||||
|
// Calibration
|
||||||
|
this.cx = 0;
|
||||||
|
this.cy = 0;
|
||||||
|
|
||||||
|
// Input
|
||||||
|
this.ix = 0;
|
||||||
|
this.iy = 0;
|
||||||
|
|
||||||
|
// Motion
|
||||||
|
this.mx = 0;
|
||||||
|
this.my = 0;
|
||||||
|
|
||||||
|
// Velocity
|
||||||
|
this.vx = 0;
|
||||||
|
this.vy = 0;
|
||||||
|
|
||||||
|
// Callbacks
|
||||||
|
this.onMouseMove = this.onMouseMove.bind(this);
|
||||||
|
this.onDeviceOrientation = this.onDeviceOrientation.bind(this);
|
||||||
|
this.onOrientationTimer = this.onOrientationTimer.bind(this);
|
||||||
|
this.onCalibrationTimer = this.onCalibrationTimer.bind(this);
|
||||||
|
this.onAnimationFrame = this.onAnimationFrame.bind(this);
|
||||||
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
|
|
||||||
|
// Initialise
|
||||||
|
this.initialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
Parallax.prototype.extend = function() {
|
||||||
|
if (arguments.length > 1) {
|
||||||
|
var master = arguments[0];
|
||||||
|
for (var i = 1, l = arguments.length; i < l; i++) {
|
||||||
|
var object = arguments[i];
|
||||||
|
for (var key in object) {
|
||||||
|
master[key] = object[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.data = function(element, name) {
|
||||||
|
return this.deserialize(element.getAttribute('data-'+name));
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.deserialize = function(value) {
|
||||||
|
if (value === "true") {
|
||||||
|
return true;
|
||||||
|
} else if (value === "false") {
|
||||||
|
return false;
|
||||||
|
} else if (value === "null") {
|
||||||
|
return null;
|
||||||
|
} else if (!isNaN(parseFloat(value)) && isFinite(value)) {
|
||||||
|
return parseFloat(value);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.camelCase = function(value) {
|
||||||
|
return value.replace(/-+(.)?/g, function(match, character){
|
||||||
|
return character ? character.toUpperCase() : '';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.transformSupport = function(value) {
|
||||||
|
var element = document.createElement('div');
|
||||||
|
var propertySupport = false;
|
||||||
|
var propertyValue = null;
|
||||||
|
var featureSupport = false;
|
||||||
|
var cssProperty = null;
|
||||||
|
var jsProperty = null;
|
||||||
|
for (var i = 0, l = this.vendors.length; i < l; i++) {
|
||||||
|
if (this.vendors[i] !== null) {
|
||||||
|
cssProperty = this.vendors[i][0] + 'transform';
|
||||||
|
jsProperty = this.vendors[i][1] + 'Transform';
|
||||||
|
} else {
|
||||||
|
cssProperty = 'transform';
|
||||||
|
jsProperty = 'transform';
|
||||||
|
}
|
||||||
|
if (element.style[jsProperty] !== undefined) {
|
||||||
|
propertySupport = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(value) {
|
||||||
|
case '2D':
|
||||||
|
featureSupport = propertySupport;
|
||||||
|
break;
|
||||||
|
case '3D':
|
||||||
|
if (propertySupport) {
|
||||||
|
var body = document.body || document.createElement('body');
|
||||||
|
var documentElement = document.documentElement;
|
||||||
|
var documentOverflow = documentElement.style.overflow;
|
||||||
|
if (!document.body) {
|
||||||
|
documentElement.style.overflow = 'hidden';
|
||||||
|
documentElement.appendChild(body);
|
||||||
|
body.style.overflow = 'hidden';
|
||||||
|
body.style.background = '';
|
||||||
|
}
|
||||||
|
body.appendChild(element);
|
||||||
|
element.style[jsProperty] = 'translate3d(1px,1px,1px)';
|
||||||
|
propertyValue = window.getComputedStyle(element).getPropertyValue(cssProperty);
|
||||||
|
featureSupport = propertyValue !== undefined && propertyValue.length > 0 && propertyValue !== "none";
|
||||||
|
documentElement.style.overflow = documentOverflow;
|
||||||
|
body.removeChild(element);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return featureSupport;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.ww = null;
|
||||||
|
Parallax.prototype.wh = null;
|
||||||
|
Parallax.prototype.wcx = null;
|
||||||
|
Parallax.prototype.wcy = null;
|
||||||
|
Parallax.prototype.wrx = null;
|
||||||
|
Parallax.prototype.wry = null;
|
||||||
|
Parallax.prototype.portrait = null;
|
||||||
|
Parallax.prototype.desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i);
|
||||||
|
Parallax.prototype.vendors = [null,['-webkit-','webkit'],['-moz-','Moz'],['-o-','O'],['-ms-','ms']];
|
||||||
|
Parallax.prototype.motionSupport = !!window.DeviceMotionEvent;
|
||||||
|
Parallax.prototype.orientationSupport = !!window.DeviceOrientationEvent;
|
||||||
|
Parallax.prototype.orientationStatus = 0;
|
||||||
|
Parallax.prototype.transform2DSupport = Parallax.prototype.transformSupport('2D');
|
||||||
|
Parallax.prototype.transform3DSupport = Parallax.prototype.transformSupport('3D');
|
||||||
|
Parallax.prototype.propertyCache = {};
|
||||||
|
|
||||||
|
Parallax.prototype.initialise = function() {
|
||||||
|
|
||||||
|
// Configure Context Styles
|
||||||
|
if (this.transform3DSupport) this.accelerate(this.element);
|
||||||
|
var style = window.getComputedStyle(this.element);
|
||||||
|
if (style.getPropertyValue('position') === 'static') {
|
||||||
|
this.element.style.position = 'relative';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
this.updateLayers();
|
||||||
|
this.updateDimensions();
|
||||||
|
this.enable();
|
||||||
|
this.queueCalibration(this.calibrationDelay);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.updateLayers = function() {
|
||||||
|
|
||||||
|
// Cache Layer Elements
|
||||||
|
this.layers = this.element.getElementsByClassName('layer');
|
||||||
|
this.depths = [];
|
||||||
|
|
||||||
|
// Configure Layer Styles
|
||||||
|
for (var i = 0, l = this.layers.length; i < l; i++) {
|
||||||
|
var layer = this.layers[i];
|
||||||
|
if (this.transform3DSupport) this.accelerate(layer);
|
||||||
|
layer.style.position = i ? 'absolute' : 'relative';
|
||||||
|
layer.style.display = 'block';
|
||||||
|
layer.style.left = 0;
|
||||||
|
layer.style.top = 0;
|
||||||
|
|
||||||
|
// Cache Layer Depth
|
||||||
|
this.depths.push(this.data(layer, 'depth') || 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.updateDimensions = function() {
|
||||||
|
this.ww = window.innerWidth;
|
||||||
|
this.wh = window.innerHeight;
|
||||||
|
this.wcx = this.ww * this.originX;
|
||||||
|
this.wcy = this.wh * this.originY;
|
||||||
|
this.wrx = Math.max(this.wcx, this.ww - this.wcx);
|
||||||
|
this.wry = Math.max(this.wcy, this.wh - this.wcy);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.updateBounds = function() {
|
||||||
|
this.bounds = this.element.getBoundingClientRect();
|
||||||
|
this.ex = this.bounds.left;
|
||||||
|
this.ey = this.bounds.top;
|
||||||
|
this.ew = this.bounds.width;
|
||||||
|
this.eh = this.bounds.height;
|
||||||
|
this.ecx = this.ew * this.originX;
|
||||||
|
this.ecy = this.eh * this.originY;
|
||||||
|
this.erx = Math.max(this.ecx, this.ew - this.ecx);
|
||||||
|
this.ery = Math.max(this.ecy, this.eh - this.ecy);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.queueCalibration = function(delay) {
|
||||||
|
clearTimeout(this.calibrationTimer);
|
||||||
|
this.calibrationTimer = setTimeout(this.onCalibrationTimer, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.enable = function() {
|
||||||
|
if (!this.enabled) {
|
||||||
|
this.enabled = true;
|
||||||
|
if (this.orientationSupport) {
|
||||||
|
this.portrait = null;
|
||||||
|
window.addEventListener('deviceorientation', this.onDeviceOrientation);
|
||||||
|
setTimeout(this.onOrientationTimer, this.supportDelay);
|
||||||
|
} else {
|
||||||
|
this.cx = 0;
|
||||||
|
this.cy = 0;
|
||||||
|
this.portrait = false;
|
||||||
|
window.addEventListener('mousemove', this.onMouseMove);
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', this.onWindowResize);
|
||||||
|
this.raf = requestAnimationFrame(this.onAnimationFrame);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.disable = function() {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.enabled = false;
|
||||||
|
if (this.orientationSupport) {
|
||||||
|
window.removeEventListener('deviceorientation', this.onDeviceOrientation);
|
||||||
|
} else {
|
||||||
|
window.removeEventListener('mousemove', this.onMouseMove);
|
||||||
|
}
|
||||||
|
window.removeEventListener('resize', this.onWindowResize);
|
||||||
|
cancelAnimationFrame(this.raf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.calibrate = function(x, y) {
|
||||||
|
this.calibrateX = x === undefined ? this.calibrateX : x;
|
||||||
|
this.calibrateY = y === undefined ? this.calibrateY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.invert = function(x, y) {
|
||||||
|
this.invertX = x === undefined ? this.invertX : x;
|
||||||
|
this.invertY = y === undefined ? this.invertY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.friction = function(x, y) {
|
||||||
|
this.frictionX = x === undefined ? this.frictionX : x;
|
||||||
|
this.frictionY = y === undefined ? this.frictionY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.scalar = function(x, y) {
|
||||||
|
this.scalarX = x === undefined ? this.scalarX : x;
|
||||||
|
this.scalarY = y === undefined ? this.scalarY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.limit = function(x, y) {
|
||||||
|
this.limitX = x === undefined ? this.limitX : x;
|
||||||
|
this.limitY = y === undefined ? this.limitY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.origin = function(x, y) {
|
||||||
|
this.originX = x === undefined ? this.originX : x;
|
||||||
|
this.originY = y === undefined ? this.originY : y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.clamp = function(value, min, max) {
|
||||||
|
value = Math.max(value, min);
|
||||||
|
value = Math.min(value, max);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.css = function(element, property, value) {
|
||||||
|
var jsProperty = this.propertyCache[property];
|
||||||
|
if (!jsProperty) {
|
||||||
|
for (var i = 0, l = this.vendors.length; i < l; i++) {
|
||||||
|
if (this.vendors[i] !== null) {
|
||||||
|
jsProperty = this.camelCase(this.vendors[i][1] + '-' + property);
|
||||||
|
} else {
|
||||||
|
jsProperty = property;
|
||||||
|
}
|
||||||
|
if (element.style[jsProperty] !== undefined) {
|
||||||
|
this.propertyCache[property] = jsProperty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
element.style[jsProperty] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.accelerate = function(element) {
|
||||||
|
this.css(element, 'transform', 'translate3d(0,0,0)');
|
||||||
|
this.css(element, 'transform-style', 'preserve-3d');
|
||||||
|
this.css(element, 'backface-visibility', 'hidden');
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.setPosition = function(element, x, y) {
|
||||||
|
x += 'px';
|
||||||
|
y += 'px';
|
||||||
|
if (this.transform3DSupport) {
|
||||||
|
this.css(element, 'transform', 'translate3d('+x+','+y+',0)');
|
||||||
|
} else if (this.transform2DSupport) {
|
||||||
|
this.css(element, 'transform', 'translate('+x+','+y+')');
|
||||||
|
} else {
|
||||||
|
element.style.left = x;
|
||||||
|
element.style.top = y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.onOrientationTimer = function(event) {
|
||||||
|
if (this.orientationSupport && this.orientationStatus === 0) {
|
||||||
|
this.disable();
|
||||||
|
this.orientationSupport = false;
|
||||||
|
this.enable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.onCalibrationTimer = function(event) {
|
||||||
|
this.calibrationFlag = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.onWindowResize = function(event) {
|
||||||
|
this.updateDimensions();
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.onAnimationFrame = function() {
|
||||||
|
this.updateBounds();
|
||||||
|
var dx = this.ix - this.cx;
|
||||||
|
var dy = this.iy - this.cy;
|
||||||
|
if ((Math.abs(dx) > this.calibrationThreshold) || (Math.abs(dy) > this.calibrationThreshold)) {
|
||||||
|
this.queueCalibration(0);
|
||||||
|
}
|
||||||
|
if (this.portrait) {
|
||||||
|
this.mx = this.calibrateX ? dy : this.iy;
|
||||||
|
this.my = this.calibrateY ? dx : this.ix;
|
||||||
|
} else {
|
||||||
|
this.mx = this.calibrateX ? dx : this.ix;
|
||||||
|
this.my = this.calibrateY ? dy : this.iy;
|
||||||
|
}
|
||||||
|
this.mx *= this.ew * (this.scalarX / 100);
|
||||||
|
this.my *= this.eh * (this.scalarY / 100);
|
||||||
|
if (!isNaN(parseFloat(this.limitX))) {
|
||||||
|
this.mx = this.clamp(this.mx, -this.limitX, this.limitX);
|
||||||
|
}
|
||||||
|
if (!isNaN(parseFloat(this.limitY))) {
|
||||||
|
this.my = this.clamp(this.my, -this.limitY, this.limitY);
|
||||||
|
}
|
||||||
|
this.vx += (this.mx - this.vx) * this.frictionX;
|
||||||
|
this.vy += (this.my - this.vy) * this.frictionY;
|
||||||
|
for (var i = 0, l = this.layers.length; i < l; i++) {
|
||||||
|
var layer = this.layers[i];
|
||||||
|
var depth = this.depths[i];
|
||||||
|
var xOffset = this.vx * depth * (this.invertX ? -1 : 1);
|
||||||
|
var yOffset = this.vy * depth * (this.invertY ? -1 : 1);
|
||||||
|
this.setPosition(layer, xOffset, yOffset);
|
||||||
|
}
|
||||||
|
this.raf = requestAnimationFrame(this.onAnimationFrame);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.onDeviceOrientation = function(event) {
|
||||||
|
|
||||||
|
// Validate environment and event properties.
|
||||||
|
if (!this.desktop && event.beta !== null && event.gamma !== null) {
|
||||||
|
|
||||||
|
// Set orientation status.
|
||||||
|
this.orientationStatus = 1;
|
||||||
|
|
||||||
|
// Extract Rotation
|
||||||
|
var x = (event.beta || 0) / MAGIC_NUMBER; // -90 :: 90
|
||||||
|
var y = (event.gamma || 0) / MAGIC_NUMBER; // -180 :: 180
|
||||||
|
|
||||||
|
// Detect Orientation Change
|
||||||
|
var portrait = this.wh > this.ww;
|
||||||
|
if (this.portrait !== portrait) {
|
||||||
|
this.portrait = portrait;
|
||||||
|
this.calibrationFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Calibration
|
||||||
|
if (this.calibrationFlag) {
|
||||||
|
this.calibrationFlag = false;
|
||||||
|
this.cx = x;
|
||||||
|
this.cy = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Input
|
||||||
|
this.ix = x;
|
||||||
|
this.iy = y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parallax.prototype.onMouseMove = function(event) {
|
||||||
|
|
||||||
|
// Cache mouse coordinates.
|
||||||
|
var clientX = event.clientX;
|
||||||
|
var clientY = event.clientY;
|
||||||
|
|
||||||
|
// Calculate Mouse Input
|
||||||
|
if (!this.orientationSupport && this.relativeInput) {
|
||||||
|
|
||||||
|
// Clip mouse coordinates inside element bounds.
|
||||||
|
if (this.clipRelativeInput) {
|
||||||
|
clientX = Math.max(clientX, this.ex);
|
||||||
|
clientX = Math.min(clientX, this.ex + this.ew);
|
||||||
|
clientY = Math.max(clientY, this.ey);
|
||||||
|
clientY = Math.min(clientY, this.ey + this.eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate input relative to the element.
|
||||||
|
this.ix = (clientX - this.ex - this.ecx) / this.erx;
|
||||||
|
this.iy = (clientY - this.ey - this.ecy) / this.ery;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Calculate input relative to the window.
|
||||||
|
this.ix = (clientX - this.wcx) / this.wrx;
|
||||||
|
this.iy = (clientY - this.wcy) / this.wry;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expose Parallax
|
||||||
|
window[NAME] = Parallax;
|
||||||
|
|
||||||
|
})(window, document);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request Animation Frame Polyfill.
|
||||||
|
* @author Tino Zijdel
|
||||||
|
* @author Paul Irish
|
||||||
|
* @see https://gist.github.com/paulirish/1579671
|
||||||
|
*/
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
var lastTime = 0;
|
||||||
|
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
||||||
|
|
||||||
|
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||||
|
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
|
||||||
|
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.requestAnimationFrame) {
|
||||||
|
window.requestAnimationFrame = function(callback, element) {
|
||||||
|
var currTime = new Date().getTime();
|
||||||
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||||
|
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
|
||||||
|
timeToCall);
|
||||||
|
lastTime = currTime + timeToCall;
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.cancelAnimationFrame) {
|
||||||
|
window.cancelAnimationFrame = function(id) {
|
||||||
|
clearTimeout(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}());
|
1
sorcery/parallax.min.js
vendored
Normal file
BIN
title9.png
Before Width: | Height: | Size: 9.6 KiB |
BIN
work_samples.png
Before Width: | Height: | Size: 3.7 KiB |