この記事で使うイベントやメソッドなど
setTimeout()
setInterval()
clearInterval()
location.href
リンク元のhrefの値に./redirect.html?page=result.html&anchor=demo
のように、?でパラメータを付与します。pageの値がリンク先、anchorがリンク先の特定のアンカーへ飛ばす必要がある場合に付与します。anchorが不要の場合は?page=result.html
のみにします。
まずは箱と値(変数の設定)を用意します。
cntはリダイレクトするまでの秒数(ミリ秒)でdispCntは1000で割って秒数に変換します。queryPrmはパラメータを格納する変数(配列)です。
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
クエリを取得して変数に入れます。クエリはlocation.search
で取得出来ます。substring(1)で文字を切り出し、split('&')でパラメータごとに切り分けます。
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
var query = location.search.substring(1).split('&');
queryには複数の値が入っている場合があるので、forループを使って先ほど用意した箱queryPrmに格納して行きます。
queryにはpage=result.html, anchor=demoのような形で値が入っているので = で分解し、=の前の値をハッシュとした連想配列にします。
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
var query = location.search.substring(1).split('&');
for(i = 0; query[i]; i++) {
var hashes = query[i].split('='); // =の前をハッシュとする
queryPrm[hashes[0]] = hashes[1]; // 連想配列に入れる
}
これでqueryPrm.page(queryPrm['page'])がリンク先で、queryPrm.anchor(queryPrm['anchor'])があった場合はリンク先のアンカーとして設定出来ました。変数linkUrlにリンク先として格納します。queryPrm['anchor']がある場合と無い場合でリンク先が異なるのでif文で分岐します。
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
var query = location.search.substring(1).split('&');
for(i = 0; query[i]; i++) {
var hashes = query[i].split('='); // =の前をハッシュとする
queryPrm[hashes[0]] = hashes[1]; // 連想配列に入れる
}
var linkUrl = queryPrm.page;
if(queryPrm.anchor) {
linkUrl = queryPrm.page + '#' + queryPrm.anchor; // anchorがある場合
}
指定した秒後に何か処理を行いたい場合はsetTimeoutメソッドを利用します。setTimeoutの使い方はこんな感じです。
// #1
setTimeout(メソッド, ミリ秒数);
// #2
setTimeout(function() {
Do something
}, ミリ秒数)
#1のパターンは予めあるメソッドを利用する場合に利用します。今回は#2のパターンを利用して、指定した秒後にfunction() {}
にかかれた処理を行うようにします。
JavaScriptで特定のURLにリダイレクトするにはlocation.href = URL
と書きます。ですので、下記のようなコードになります。
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
var query = location.search.substring(1).split('&');
for(i = 0; query[i]; i++) {
var hashes = query[i].split('='); // =の前をハッシュとする
queryPrm[hashes[0]] = hashes[1]; // 連想配列に入れる
}
var linkUrl = queryPrm.page;
if(queryPrm.anchor) {
linkUrl = queryPrm.page + '#' + queryPrm.anchor; // anchorがある場合
}
setTimeout(function() {
location.href = linkUrl;
}, cnt);
それではカウントダウン表示するメソッド、countDown()を作ります。パラメータにミリ秒数を渡すとその間だけカウントダウン表示するようにします。
function countDown(cnt) {
Do someting
}
指定した時間、ある処理を繰り返したい場合はsetIntervalメソッドを利用します。使い方はsetTimeoutと似ており、メソッドとミリ秒数をパラメータとすれば指定したミリ秒数の間処理を繰り返してくれます。
ここでは変数timerにsetIntervalで行う処理を格納しておきます。
function countDown(cnt) {
var timer = setInterval(function () {
Do someting
}, 1000);
}
繰り返す処理は、パラメータcntをデクリメント(--)、idがcountの内容をcntの値で書き換え(innerHTML)、cntが0になったら処理を終了(clearInterval)します。
function countDown(cnt) {
var timer = setInterval(function () {
cnt --; // cntをデクリメント
document.getElementById('count').innerHTML = cnt;
if(cnt == 0) {
clearInterval(timer); // cntが0になったら処理を終了
}
}, 1000);
}
これで指定した秒数をカウントダウン表示するメソッドcountDownが出来たので、このメソッドを呼び出します。
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
var query = location.search.substring(1).split('&');
for(i = 0; query[i]; i++) {
var hashes = query[i].split('='); // =の前をハッシュとする
queryPrm[hashes[0]] = hashes[1]; // 連想配列に入れる
}
var linkUrl = queryPrm.page;
if(queryPrm.anchor) {
linkUrl = queryPrm.page + '#' + queryPrm.anchor; // anchorがある場合
}
setTimeout(function() {
location.href = linkUrl;
}, cnt);
countDown(dispCnt);
function countDown(cnt) {
var timer = setInterval(function () {
cnt --;
document.getElementById('count').innerHTML = cnt;
if(cnt == 0) {
clearInterval(timer);
}
}, 1000);
}
ここは非常に簡単です。getElementByIdで所得したhrefをlinkUrlで上書きします。
var clickElem = document.getElementById('go-page');
clickElem.href = linkUrl;
これで完成です。完成したコードは下記のようになります。
リンク元HTMLコード
<div class="page">
<h1>Redirect Demo</h1>
<p><a href="./redirect.html?page=result.html&anchor=demo" target="_blank">ここをクリック</a></p>
</div>
リダイレクト側コード
<div class="page">
<h1>Redirect Demo</h1>
<p><span id="count">3</span>秒後に別ページにリダイレクトします。</p>
<button><a href="./" id="go-page">すぐに移動する</a></button>
</div>
<script>
var cnt = 3000;
var dispCnt = cnt / 1000;
var queryPrm = new Array;
var query = location.search.substring(1).split('&');
for(i = 0; query[i]; i++) {
var hashes = query[i].split('=');
queryPrm[hashes[0]] = hashes[1];
}
var linkUrl = queryPrm.page;
if(queryPrm.anchor) {
linkUrl = queryPrm.page + '#' + queryPrm.anchor;
}
setTimeout(function() {
location.href = linkUrl;
}, cnt);
countDown(dispCnt);
function countDown(cnt) {
var timer = setInterval(function () {
cnt --;
document.getElementById('count').innerHTML = cnt;
if(cnt == 0) {
clearInterval(timer);
}
}, 1000);
}
var clickElem = document.getElementById('go-page');
clickElem.href = linkUrl;
</script>
]]>
MAMP3を下記サイトよりダウンロードしてインストール。
MAMP
XcodeはApp Storeからインストール。Command Line ToolsはXcodeを開いて[ Xcode ]→[ Open Developer Tool ]→[ More Developer Tools ]とたどり、ブラウザが開くのでCommand Line Tools(OSX Mavericks) for Xcodeをクリックしてインストール。
ターミナルからインストールする場合は下記コマンド。
xcode-select --install
X11(XQuartz)を下記サイトよりダウンロードしてインストール。
XQuartz
Homebrewにしようと思ったのですが、やっぱり慣れてるMacPortsにしました。ダウンロードしてインストールして初期化します。
MacPorts
echo 'export PATH=$PATH:/opt/local/bin:/opt/local/sbin/' >> ~/.bashrc echo 'export MANPATH=$MANPATH:/opt/local/man' >> ~/.bashrc echo 'source ~/.bashrc' >> ~/.bash_profile sudo port -d selfupdate sudo port -d sync
MovableTypeで使用するImageMagickはPerl版なのでPerlMagickをインストール
sudo port install perlmagick
Perlのパス(/usr/bin/perl)をMacPortsのディレクトリ(/opt/local/bin/)に置き換えます。
cd /usr/bin/ sudo mv perl perl.bak sudo ln -s /opt/local/bin/perl /usr/bin/perl
ここから毎度@BUNさんのMac OS Xのローカル環境(MAMP+MacPorts)で Movable Typeを動かしてみよう - 準備編を参考に
sudo port install p5-dbi sudo port install p5-dbd-mysql sudo port install p5-dbd-sqlite sudo port install p5-dbd-sqlite2 sudo port install p5-dbd-pg
sudo port install p5-gd sudo port install p5-crypt-dsa sudo port install p5-archive-zip sudo port install p5-xml-atom sudo port install p5-mail-sendmail
MAMPのhttpd.confを編集します。572行目ぐらいのhttpd-vhosts.confを有効にします。
Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
これでhttpd.confではなく、httpd-hosts.confにVirtualHostの設定を書くことが出来ます。あとはこのブログの過去記事VirualHostの設定を参考に。
仮想環境はOracleのVirtualBoxを利用することにします。ブラウザ確認だけならmodern.ieを入れるだけで良いと判断したので...
VirtualBox & modern.ieのインストールはStocker.jpさんのMacでも無料でIE確認するためのModern.IEが想像以上に快適だったを参考にさせて頂きました。
modern.ieはWindows8 - IE11を入れて、IE11〜8までの確認はDevelopper Toolで確認することにしました。
以上で新しいMacでローカル環境構築終了です。
]]>この記事で使うイベントやメソッドなど
.next();
.append();
.text();
.split();
$('.foo').each(function() { Do Something });
.getTime()
new Date()で現在の日付、時刻のオブジェクトを生成することが出来ます。よく使うDateオブジェクトのメソッドを紹介しておきます。
var today = new Date(); // 現在の日付、時刻のオブジェクト生成
var yy = today.getFullYear(); // 現在の年号を4桁で取得
var mm = today.getMonth(); // 現在の月を取得(0〜11)
var dd = today.getDate(); // 現在の日を取得
var day = today.getDay(); // 現在の曜日を取得(0〜6)
Dateオブジェクトに年月日のパラメータを与えると、その年月日のDateオブジェクトが生成されます。注意する点は、Dateオブジェクトでの月は0〜11と言う点です。0が1月、1が2月なので、getMonthで取得した値に1を足すと正確な月になります。なのでnew Date()
のパラメータに月を与える時は1を引いた数にします。
var setDay = new Date(2014, 3, 1); // 2014年4月1日のDateオブジェクト生成
JavaScriptの日時は1970年1月1日0時からのミリ秒数として計られています(それ以前はマイナスの数値)。1日は86,400,000ミリ秒で計算されます。
Dateオブジェクトを生成した後、.getTime()メソッドを利用すると、指定した年月日の経過ミリ秒数が求まります。
var today = new Date(); // 現在の日付、時刻のオブジェクト生成
var sec = today.getTime(); // 現在の年月日を経過ミリ秒数で取得
以上の知識があれば、今回のJavaScriptで自動的にNEWマークを追加する事が出来ます。
実装する考え方ですが、
以上で実装出来ます。
HTML Code
<dl class="box__info">
<dt>2014-03-29</dt>
<dd><a href="javascript:;">○○○を更新しました</a></dd>
<dl>
それではJavaScriptのコードを作っていきます。
まずはNEWマークを付ける日数をミリ秒数に変換、現在の年月日のDateオブジェクトを生成してミリ秒数に変換します。
JavaScript Code
$(function() {
var distance = 3 * 86400000; // 3日間のミリ秒数で求める
var today = new Date(); // 現在の年月日のDateオブジェクトを生成
var baseTime = today.getTime(); // 現在の年月日のミリ秒数を求める
});
次にdtに記述された日数をフックにするため.text()を利用して取得します。今回は年月日の区切り記号にハイフンを利用しているので、.split('-')で分割し、配列に入れます。これらはdtの数だけ繰り返さなければならないのでeachメソッドを利用して繰り返します。
JavaScript Code
$(function() {
var distance = 3 * 86400000; // 3日間のミリ秒数で求める
var today = new Date(); // 現在の年月日のDateオブジェクトを生成
var baseTime = today.getTime(); // 現在の年月日のミリ秒数を求める
$('dl.box__info dt').each(function() {
var textVal = $(this).text(); // dtに記述された年月日を取得
var dateArr = textVal.split('-'); // 年月日に分けて配列に入れる
});
});
所得した年月日を利用してDateオブジェクトを生成し、ミリ秒数を求めます。そして、現在の日時との差分を取って3日経っているかを調べ、条件と一致していればNEWマークを付けます。
JavaScript Code
$(function() {
var distance = 3 * 86400000; // 3日間のミリ秒数で求める
var today = new Date(); // 現在の年月日のDateオブジェクトを生成
var baseTime = today.getTime(); // 現在の年月日のミリ秒数を求める
$('dl.box__info dt').each(function() {
var textVal = $(this).text(); // dtに記述された年月日を取得
var dateArr = textVal.split('-'); // 年月日に分けて配列に入れる
var entryDay = new Date(dateArr[0], dateArr[1]-1, dateArr[2]); // dtに記述された年月日のDateオブジェクトを生成
var entryTime = entryDay.getTime(); // ミリ秒数を求める
var dist = baseTime - entryTime; // 現在の年月日(ミリ秒数)との差分
// 3日経っていなければNEWマークを付ける
if(dist <= distance) {
$(this).next('dd').append('<i class="icon__new">NEW</i>');
}
});
});
以上です。非常に簡単に実装出来ますね。応用すればいろいろなパターンに利用出来ると思います。
それにしてもNEWマークいらねー。
プラグイン版はGithubに置いてあります。
Graphic:Web Design Hot
]]>Project │ ├─node_module │ │ Gruntfile.coffee │ package.json │ └─htdocs │ │ index.html │ ├─css │ style.min.css │ ├─img │ sprite-xxxx.png │ img-photo01.jpg │ ├─js │ project-name.js │ └─src ├─sass │ style.scss │ ├─css │ style.css │ ├─img │ │ sprite-xxxx.png │ │ img-photo01.jpg │ │ │ └─src │ icon-aaa.png │ icon-bbb.png │ └─js aaa.js bbb.js
srcフォルダが作業フォルダになります(srcフォルダは公開しない前提)。Gruntで自動化する流れと使用するモジュールは以下のようになります。
Grantfile.coffeeは以下のようになります(.jsより.coffeeの方が見やすいのでCoffeeScriptで書いています)。
module.exports = (grunt) -> grunt.loadNpmTasks 'grunt-contrib-watch' grunt.loadNpmTasks 'grunt-contrib-compass' grunt.loadNpmTasks 'grunt-contrib-uglify' grunt.loadNpmTasks 'grunt-contrib-concat' grunt.loadNpmTasks 'grunt-contrib-cssmin' grunt.loadNpmTasks 'grunt-contrib-imagemin' grunt.loadNpmTasks 'grunt-pngmin' grunt.loadNpmTasks 'grunt-styleguide' grunt.initConfig pkg: grunt.file.readJSON 'package.json' paths: srcDir: 'htdocs/src/' distDir: 'htdocs/' # Sassをコンパイル compass: dev: options: httpPath: '/' basePath: '<%= paths.srcDir %>' cssDir: 'css/' sassDir: 'sass/' imagesDir: 'img/' javascriptDir: 'js/' environment: 'development' # CSSを圧縮 cssmin: minify: expand: true cwd: '<%= paths.srcDir %>css/' src: '**/*.css' dest: '<%= paths.distDir %>css/' # JPEG, GIF画像を圧縮 imagemin: dynamic: options: optimizationLevel: 3 files: [ expand: true cwd: '<%= paths.srcDir %>img/' src: '**/*.{jpg, gif}' dest: '<%= paths.distDir %>img/' ] # PNG画像を圧縮 pngmin: compile: options: ext: '.png' files: [ expand: true cwd: '<%= paths.srcDir %>img/' src: '**/*.png' dest: '<%= paths.distDir %>img/' ] # JSファイルを結合 concat: files: src: ['<%= paths.srcDir %>js/*.js'] dest: '<%= paths.distDir %>js/<%= pkg.name %>.js' # JSファイルを圧縮 uglify: options: banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' compose: src: '<%= paths.distDir %>js/<%= pkg.name %>.js' dest: '<%= paths.distDir %>js/<%= pkg.name %>.min.js' # タスクをWatch watch: css: files: ['<%= paths.srcDir %>sass/*.scss', '<%= paths.srcDir %>css/*.css'] tasks: ['compass:dev', 'cssmin'] image: files: ['<%= paths.srcDir %>img/**/*.{png,jpg,gif}'] tasks: ['imagemin:dynamic', 'pngmin'] js: files: ['<%= paths.srcDir %>js/*.js', '<%= paths.distDir %>js/<%= pkg.name %>.js'] tasks: ['concat', 'uglify:compose'] grunt.registerTask 'default', ['watch']
パスは何らかで変更になった場合一括で変わってほしいので、変数に入れています。srcDirが作業フォルダへのパス、distDirが公開フォルダへのパスです。
config.rbに書いていた内容をgrunt-contrib-compassのoptionで設定していますが、config.rbと微妙に名前が違います(sassdirがsassDirなど)。ハマったのがprojectpathでgrunt側だとbasePathになるんですね。
いやぁ...やっぱり自動化って素敵!
]]>通常の環境ではnpm install -g grunt-cli
と叩けば問題無いのですが、プロキシ環境下ではエラーが出てインストール出来ません。
色々とググって試したのですが、全然うまく行きませんでした...が、下記の方法でインストール出来ました。
npm config set registry http://registry.npmjs.org/ npm config set proxy http://proxy.mycompany.com:8080 npm config set https-proxy https://proxy.mycompany.com:8080
proxy.mycompany.comにはプロキシサーバーのURL、:8080にはポート番号を入れます。
これでnpm install -g grunt-cli
と叩いてインストール出来ました。
Sass
main {
margin-bottom: 3em;
p {
line-height: 1.4;
margin-bottom: 1em;
}
}
CSS
main {
margin-bottom: 3em;
}
main p {
line-height: 1.4;
margin-bottom: 1em;
}
Sassの最もベーシックな書き方だと思います。ネストで書くことによって見通しの良いCSSが書けますが、ネストのしすぎに注意。かえって見辛いコードになる可能性もあります。
Sass
a {
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.box {
margin-bottom: 2em;
background-color: #999;
.top & {
background-color: #eee;
}
&.info {
background-color: #fff;
}
}
CSS
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.box {
margin-bottom: 2em;
background-color: #999;
}
.top .box {
background-color: #eee;
}
.box.info {
background-color: #fff;
}
擬似セレクタの場合は&:hoverのように書きます。親セレクタを参照したい場合は.top &のように「参照する親セレクタ &」と書きます。&の後にセレクタを続ければ連結セレクタで出力します。
Sass
$base-margin: 3em;
div {
margin-bottom: $base-margin;
p {
line-height: 1.4;
margin-bottom: $base-margin / 2;
}
}
CSS
div {
margin-bottom: 3em;
}
div p {
line-height: 1.4;
margin-bottom: 1.5em;
}
ベースとなるカラーコードやmarginの値を変数に入れると便利です。変数は演算もできます。
小数点以下の処理を丸めたい場合はround()で四捨五入、ceil()で切り上げ、floor()で切り捨てとなります。
Sass
$base-margin: 5em;
div.round {
margin-bottom: round($base-margin / 2);
}
div.ceil {
margin-bottom: ceil($base-margin / 2);
}
div.floor {
margin-bottom: floor($base-margin / 2);
}
CSS
div.round {
margin-bottom: 3em;
}
div.ceil {
margin-bottom: 3em;
}
div.floor {
margin-bottom: 2em;
}
平澤さんのブログに非常にわかりやすい記事があります。変数と演算で効率的に
Sass
@mixin clearfix {
*zoom: 1; // lte ie7
&:after {
content: '';
display: block;
clear: both;
}
}
.cf {
@include clearfix;
}
CSS
.cf {
*zoom: 1;
}
.cf:after {
content: '';
display: block;
clear: both;
}
@mixinは複数のプロパティをまとめて1つのプロパティのように扱います。@mixin mixin名 { prop: value; } を セレクタ { @include mixin名; } で呼び出します。
@mixinはパラメータを設定して柔軟に呼び出す事ができます。その場合は、@mixin mixin名(パラメータ) { prop: パラメータ; } をセレクタ { @include mixin名(パラメータ); } で呼び出します。
Compassなんかを使ってる場合、下のサンプルコードのようにCSS Sprite用のmixinとか作っておくと便利。
Sass
//スプライト画像の作成
$s1: sprite-map("/img/sprite/*.png", $spacing:20px, $layout: vertical);
//$name スプライト前の画像名
//$sorutes sprite-mapを指定
@mixin sprite-background($name, $sprites) {
background: sprite-url($s1)no-repeat;
background-position: sprite-position($sprites, $name);
width: image-width(sprite-file($sprites, $name));
height: image-height(sprite-file($sprites, $name));
}
//mixin呼び出し
.icon-config {
@include sprite-background("Evernote", $s1);
}
CSS
.icon-Evernote {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -52px;
width: 32px;
height: 32px;
}
/img/spreite/にpng画像を放り込んでおいてスプライト用のmixinを呼び出せば自動でスプライト画像を書き出してくれるのでもうCompass抜きでCSSスプライトは考えられません...
Sass
.box-main {
margin: 1em;
padding: 0.5em 1em;
border: 1px solid #999;
background-color: #ddd;
}
.box-sub {
@extend .box-main;
background-color: #eee;
}
CSS
.box-main, .box-sub {
margin: 1em;
padding: 0.5em 1em;
border: 1px solid #999;
background-color: #ddd;
}
.box-sub {
background-color: #eee;
}
セレクタを継承してまとめて記述してくれます。けれども後述のプレースホルダを使った方が余計な記述が減る場合も。
Sass
//このセレクタは@extendで呼び出されない限り出力されない
%box-style {
margin: 1em;
padding: 0.5em 1em;
border: 1px solid #999;
}
.box-main {
@extend %box-style;
background-color: #ddd;
}
.box-sub {
@extend %box-style;
background-color: #999;
}
CSS
.box-main, .box-sub {
margin: 1em;
padding: 0.5em 1em;
border: 1px solid #999;
background-color: #ddd;
}
.box-sub {
background-color: #999;
}
プレースホルダは%セレクタ名で記述します。@extend %セレクタ名で呼び出されない限り、CSSは出力されません。
先述のextendはあくまでも継承ですので、継承元のセレクタに継承したくないプロパティがあっても当然のように継承してしまうので、余計なCSSが増える可能性があります。
ですのでプレースホルダで共通のプロパティを用意して、それぞれのセレクタで個別のプロパティを書いたほうが効率が良いです。
Sass
$ie7: false;
@if($ie7) {
//$ie7: trueの場合
.box {
display: inline-block;
*display: inline;
*zoom: 1;
}
} @else {
.box {
display: inline-block;
}
}
CSS
.box {
display: inline-block;
}
Sassはプログラミング言語でよく使われる条件分岐であるif〜elseを利用できます。サンプルコードでは変数$ie7でIE7をサポートするかしないか(true/false)で.boxのプロパティを変えています。
if関数に関しては昨年のAdvent CalendarのSassのif関数が参考になります。
Sass
//スプライト画像の作成
$s1: sprite-map("/img/sprite/*.png", $spacing:20px, $layout: vertical);
//$name スプライト前の画像名
//$sorutes sprite-mapを指定
@mixin sprite-background($name, $sprites) {
background: sprite-url($s1)no-repeat;
background-position: sprite-position($sprites, $name);
width: image-width(sprite-file($sprites, $name));
height: image-height(sprite-file($sprites, $name));
}
//アイコン名を配列にセット
$socialList : Evernote, Facebook, Flickr, Github;
//length(配列名)で配列の長さを取得 nth(配列名, n)で配列名のn番目の要素を取得
@for $i from 1 through length($socialList){
.icon-#{nth($socialList, $i)} {
@include sprite-background(#{nth($socialList, $i)}, $s1);
}
}
CSS
.icon-Evernote {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -52px;
width: 32px;
height: 32px;
}
.icon-Facebook {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -156px;
width: 32px;
height: 32px;
}
.icon-Flickr {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -104px;
width: 32px;
height: 32px;
}
.icon-Github {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 0;
width: 32px;
height: 32px;
}
if文同様、for文もプログラミング言語でよく使われます。サンプルコードでは先述のCSSスプライト用mixinを呼び出す箇所でfor文を使えば非常に短いコードで書けます。
サンプルコードではwidth, height, backgroundが重複していますが、mixinを分けてプレースホルダでincludeして...と言った書き方にすればさらにきれいなCSSを出力できます。
配列と値の取得に関してはSass(Scss)配列と値の取得が参考になります。
Sass
//スプライト画像の作成
$s1: sprite-map("/img/sprite/*.png", $spacing:20px, $layout: vertical);
//$name スプライト前の画像名
//$sorutes sprite-mapを指定
@mixin sprite-background($name, $sprites) {
background: sprite-url($s1)no-repeat;
background-position: sprite-position($sprites, $name);
width: image-width(sprite-file($sprites, $name));
height: image-height(sprite-file($sprites, $name));
}
@each $socialList in Evernote, Facebook, Flickr, Github {
.icon-#{$socialList} {
@include sprite-background($socialList, $s1);
}
}
CSS
.icon-Evernote {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -52px;
width: 32px;
height: 32px;
}
.icon-Facebook {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -156px;
width: 32px;
height: 32px;
}
.icon-Flickr {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 -104px;
width: 32px;
height: 32px;
}
.icon-Github {
background: url(/img/sprite-scc43fbc7aa.png) no-repeat;
background-position: 0 0;
width: 32px;
height: 32px;
}
ループ処理はfor文以外にeach文も使えます。先述のfor文をeachに置き換えるとかなりわかりやすいコードで書けます。
for文では繰り返す数を指定しなければならないのですが、each文は配列の値分だけ繰り返してくれるので、length()やnth()と言ったfunctionを使わないですみます。
ベンダープリフィックスを付加するmixinのサンプルでeach文はよく見かけますね。不要なベンダープリフィックスはmixinの方で削除すればいいのでとても便利です。
Sass
$prefixPattern: '-webkit-', '-moz-', '-ms-', '-o-', '';
@mixin prefix($prop, $value) {
@each $prefix in $prefixPattern {
#{$prefix}#{$prop}: $value;
}
}
.round-corner {
@include prefix(border-radius, 5px);
}
.transition {
@include prefix(transition, 0.5s);
}
CSS
.round-corner {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
.transition {
-webkit-transition: 0.5s;
-moz-transition: 0.5s;
-ms-transition: 0.5s;
-o-transition: 0.5s;
transition: 0.5s;
}
Sass
$base-margin: 3em;
@function mg-half() {
@return $base-margin / 2;
}
@function mg-thrid() {
@return $base-margin / 3;
}
@function mg-quater() {
@return $base-margin / 4;
}
section {
margin-bottom: $base-margin;
h1 {
margin-bottom: mg-thrid();
}
p {
margin-bottom: mg-half();
}
dl {
margin: 0 mg-thrid() mg-half();
dt {
margin-bottom: mg-quater();
}
dd {
margin-bottom: mg-thrid();
}
dd + dd {
margin-bottom: mg-quater();
}
}
}
CSS
section {
margin-bottom: 3em;
}
section h1 {
margin-bottom: 1em;
}
section p {
margin-bottom: 1.5em;
}
section dl {
margin: 0 1em 1.5em;
}
section dl dt {
margin-bottom: 0.75em;
}
section dl dd {
margin-bottom: 1em;
}
section dl dd + dd {
margin-bottom: 0.75em;
}
@functionは独自のファンクション(関数)を作る事ができます。@function内で実行された内容を@returnで返します。
サンプルコードではベースとなるmarginに対して2分の1、3分の1、4分の1の独自ファンクションを作り、それぞれのセレクタ内で呼び出してます。
@functionは@mixinほど使用頻度は少ないと思われますが、あれやりたい...なんて思った時に@functionでできる場合もあるので頭の片隅に入れておくと良いと思います。
この記事で使うイベントやメソッドなど
.scrollTop();
.css('prop', 'value');
$(window).scroll(function() { Do Something });
ヘッダーとフッターがあり、メインのコンテンツとサイドバーがある簡単な2カラムレイアウトで考えます。(都合上サイドバーは.side-barの中に追従するコンテンツを入れるといった入れ子のマークアップをします。)
このレイアウトで追従して欲しいサイドバーの追従範囲はコンテンツの高さです。スクロールしてヘッダーが見えなくなった場所でサイドバーをページ上部に固定します。追従を解除する場所はフッターがサイドバーの最下部に到達した場所です。
まずは各要素の高さをそれぞれ変数に入れましょう。追従する範囲となるサイドバーの高さをコンテンツの高さと揃えます。合わせて追従を解除する場所(ヘッダーの高さとコンテンツの高さを足した値から追従するサイドバーの高さを引いた値)も変数に入れます。
jQuery Code
$(function() {
//各要素の高さ
var headerHeight = $('.page-header').height();
var contentsHeight = $('.page-body').height();
var fixedSideBarHeight = $('#fixed-side-bar').height();
//サイドバーの高さをコンテンツの高さと揃える
$('.side-bar').css('height', contentsHeight);
//追従を解除する場所
var scrollStopPos = headerHeight+contentsHeight-fixedSideBarHeight;
});
スクロールイベントが始まると、どれだけスクロールしたかを監視します。どれだけスクロールしたかのスクロール量はjQueryのメソッドである.scrollTop()
で求めることができます。
追従を開始する場所と解除する場所に来たらそれぞれjQueryでCSSのプロパティを変更します。
jQuery Code
$(function() {
//各要素の高さ
var headerHeight = $('.page-header').height();
var contentsHeight = $('.page-body').height();
var fixedSideBarHeight = $('#fixed-side-bar').height();
//サイドバーの高さをコンテンツの高さと揃える
$('.side-bar').css('height', contentsHeight);
//追従を解除する場所
var scrollStopPos = headerHeight+contentsHeight-fixedSideBarHeight;
//イベント開始
$(window).scroll(function() {
//スクロール量
var scrollVal = $(window).scrollTop();
});
});
ここからはif〜else if〜else文で条件を指定していきます。
if 追従区間 { 追従 } else if 追従解除位置 { 追従解除 } else { 通常 } と言う条件になります。
追従区間はスクロール量 > ヘッダーの高さ かつ 追従解除する場所 > スクロール量になります。
この条件になったら.css()
でposition: fixed; top: 0;
にします。
追従解除位置はスクロール量 > 追従解除する場所になります。
この条件になったらposition: absolute; bottom: 0
にします。
通常(追従範囲外)の場合はposition: static;
とします。
jQuery Code
$(function() {
//各要素の高さ
var headerHeight = $('.page-header').height();
var contentsHeight = $('.page-body').height();
var fixedSideBarHeight = $('#fixed-side-bar').height();
//サイドバーの高さをコンテンツの高さと揃える
$('.side-bar').css('height', contentsHeight);
//追従を解除する場所
var scrollStopPos = headerHeight+contentsHeight-fixedSideBarHeight;
//イベント開始
$(window).scroll(function() {
//スクロール量
var scrollVal = $(window).scrollTop();
//追従区間
if(headerHeight < scrollVal && scrollStopPos > scrollVal) {
$('#fixed-side-bar').css({
'position': 'fixed',
'top': '0'
});
//追従解除
} else if(scrollStopPos < scrollVal) {
$('#fixed-side-bar').css({
'position': 'absolute',
'top': '',
'bottom': '0'
});
//デフォルト
} else {
$('#fixed-side-bar').css('position', 'static');
}
});
});
]]>
そんな中、ライターの和田静香さんがツイッターで呼びかけたのが選挙ステッカーでした。アメリカじゃ、ビヨンセやケイティ・ペリーも選挙に行ったら「VOTED!」とステッカーを貼ってるよ!とツイートすると、様々なクリエーターが参加しだしました。
なんと吉田戦車さんまで参加してびっくり!
そんな訳で僕も少しでも投票率があがるようにと選挙ステッカーを作ってみました。もちろん犬ですが、今回はノリゾー犬を使わずに新たにパグのイラストを書き下ろしました。
何パターンか作ったのですが、やはりiPhoneなどのスマフォが貼りやすいかな?と思い、5cm×5cm(吹き出し入りは5cm×7cm)で青バージョンと黄バージョンの2色展開で作りました。
よろしければiPhoneに貼ってみてください。
WindowsならXAMPP、MacならMAMPをダウンロードする。Macでも好みによってはXAMPPを利用するのももちろん有り。
http://hoge.localhost/でアクセス出来るようにVertual Hostの設定とhostsへの追記をする。
XAMPPはhttpd-vhosts.confを編集。場所はC:\xampp\apache\conf\extra
MAMPはhttpd.confを編集。場所はMAMP/conf/apache
hostsにドメイン名を記述。WindowsはC:\WINDOWS\system32\drivers\etcにあり、Macは/private/etc/にある。
設定の方法は過去記事参照MAMPでVirtualHostを設定する
Windowsは標準でRubyが入っていないのでRubyInstallerからダウンロードしてきてインストール。コマンドたたいてインストールの確認をする。
ruby -v
コマンドラインよりインストール。
gem update --system gem install compass
プロキシ越しの場合
gem install compass -r -p http://proxy.hoge.jp:ポート番号
インストールの確認
compass -v
該当ディレクトリにconfig.rbの名前でファイルを作成し、下記を記述。
http_path = "/" css_dir = "shared/css" sass_dir = "shared/sass" images_dir = "/" javascripts_dir = "shared/js" output_style = (environment == :production) ? :compressed : :expanded line_comments = (environment == :production) ? :false : :true
CSSやSASSのパスなどは環境によって変更
sassファイルの変更を監視するバッチファイルを作成。
開発環境用はexpanded形式、本番環境用はcompact形式でコンパイルする。
拡張子はWindows用は.batでMac用は.command
本番.bat
compass watch -e production
開発.bat
compass watch
本番.command
#!/bin/bash htdocs=$(dirname $0) cd $htdocs compass watch -e production
開発.command
#!/bin/bash htdocs=$(dirname $0) cd $htdocs compass watch
以上でとりあえずWordpressやMovable TypeをローカルにインストールしてSassを使って制作する環境が整う。
]]>変わる事の無かった犬のシルエットを今になって「もっとちゃんとした犬のイラストに変更したい」と思い、何パターンも書いて気に入ったイラストをメインイメージにチェンジしました。
ブログも同一デザインに!と思ってはいてもなかなか時間がとれず、アバターを変更してから結構日数が経ってしまいましたが、ようやっとリデザイン出来ました。
今回はシルエットでなく、イラストをきっちり書いたのでやはりRetna Displayでもきれいに見えて欲しい!なのでSVGを利用しました。
アイコン関連は今までPhotoshopで書いてたのですが、Font Awesomeのアイコンフォントを使わせてもらいました。タイトルフォントはCodeを使わせてもらいました。
今まではデザインするにあたって、Photoshopで簡単なカンプを作ってたのですが、今回は作らずにブラウザでデザインする手法で作っていきました。スマフォ画面をメインに、PC用にCSSを書き加えていくと言った手法をとりました。
書きたいと思っていた記事もたくさんあるのですが、こちらもなかなか書けず...
リニューアルを期にまたちょいちょいと記事を書いて行こうと思いますので宜しくお願いいたします。
環境
OS 10.7.5 / MAMP 1.9.1 / VMWare Fusion4.1.3 / Windows XP
バーチャルホストの設定に関しては以前MAMPでVirtualHostを設定すると言う記事を書きましたので必要があればこちらを参照してみて下さい。
]]> まずはMAMPのhttpd.confにポートを追加します。通常はListen 80かListen 8888になっていると思いますが、もう一つポートを追加してあげます。僕の場合は8000と言うポートを追加しました。Listen 80 # 8000ポートを新規追加 Listen 8000
次にバーチャルホストの設定。80ポートはMacから、8000ポートはVMWare Fusion上からアクセスするために追加します。
DocumentRootは僕の場合はホームの直下にhtdocsを置いているのでこのような設定にしています。
<VirtualHost *:80> DocumentRoot "/Users/MyName/htdocs/hoge" ServerName hoge.localhost </VirtualHost> <VirtualHost *:8000> DocumentRoot "/Users/MyName/htdocs/hoge" ServerName hoge.localhost </VirtualHost>
/private/etc/hostsにも忘れずに書き加えます。(privateフォルダは不可視フォルダなのでShift+Command+Gキーで移動します。)
127.0.0.1 hoge.localhost
MacのIPアドレスを調べます。ユーティリティ/システム情報.appを起動させてネットワークのIPv4アドレスを調べてメモっておきます。
MAMPを再起動させてMac側の設定は終わりです。
VMWare FusionのWindows側に移ります。
C:\WINDOWS\system32\drivers\etcとたどり、hostsファイルをメモ帳などで開きます。(hostsファイルは念のためにバックアップを取っておきます。)
先ほどメモったIPアドレス+半角スペース+Macで設定したバーチャルホストのServerNameを記述します。
XXX.XXX.X.X hoge.localhost
VMWare Fusionのネットワーク設定をブリッジ(自動検出)にします。
これでhttp://hoge.localhostへとアクセス出来るようになります。
ああ...大変だった...
]]>4回に渡ってタブプラグインを改修していきましたが、今回はURLにパラメータを付けて特定のタブが開いた状態へリンクを貼れるように改修いたしました。(正確には書いてもらった...)
詳しい解説は今回は省きますが、内容はURLに付いたパラメータを解析するメソッドを用意し、パラメータに応じて開くタブを制御しています。タブ数は4つまで対応するようになっています。
]]> 使い方オプションで用意しているプロパティは以下の通り
初期値のままで使う場合はリンク元のhref属性にhoge.html?tab=tab02と指定した場合、2番目のタブが開いた状態、hoge.html?tab=tab03と指定した場合、3番目のタブが開いた状態で表示されます。
ソースコードはGithubに置いてあります。
]]>前回はjQuery Cookie プラグインを使ってタブの表示状態を保持するように改修しました。
今回は最初に表示されるタブを選択出来るように改修します。
jQuery Code
(function($) {
$.fn.tabs = function(options) {
var o = $.extend({
targetID: '#tab',
tabElement: '.tab-list li',
boxElement: '.tab-box',
defaultOpenTab: 0
}, options);
$(o.tabElement, o.targetID).each(function() {
var selectedTab = $.cookie(o.targetID + 'selectedTab');
if (selectedTab) {
$(o.boxElement, o.targetID).not(':eq(' +selectedTab+')').hide();
$(o.tabElement, o.targetID).eq(selectedTab).addClass('selected');
} else {
$(o.boxElement, o.targetID).hide().eq(o.defaultOpenTab).show();
$(o.tabElement, o.targetID).eq(o.defaultOpenTab).addClass('selected');
}
$(this).click(function(){
var tabIndex = $(o.tabElement, o.targetID).index(this);
$.cookie(o.targetID + 'selectedTab', tabIndex);
$(o.tabElement, o.targetID).removeClass('selected');
$(this).addClass('selected');
$(o.boxElement, o.targetID).hide().eq(tabIndex).addClass('selected').fadeIn();
});
});
return this;
};
})(jQuery);
前回と違うのは7行目と17、18行目だけです。
何をやっているかと言うと7行目に最初に選択されているタブをオプションとして設定します。0が1番目、1が2番目になります。(初期値は0とします)
17行目は以前のコードでは『1番目の内容以外を非表示』としていたのを『n番目の内容以外を表示』に変更します。
まずは全ての内容を.hide()で非表示にして、.eq(n番目)を.show()で表示します。
18行目は.eq(n番目)のタブ(liタグ)に.addClass()します。
これでn番目のタブが選択された状態を初期値として設定出来るようになります。
GithubデビューしたのでGithubにコードを置いておきました。宜しければご自由にお使いください。
]]>※基本bodyに指定するフォント関連でのみ使用し、他の場所では極力ハックは使わないようにしています。決してハックを推奨する記事ではありません。
]]> CSS Codebody {
font-family: Verdana, Arial, Hiragino Kaku Gothic Pro, "ヒラギノ角ゴ W3", Osaka, "MS Pゴシック", sans-serif;
font-size: 13px;
font-family: Verdana, Arial, "メイリオ", Meiryo, "MS Pゴシック", sans-serif\9;
font-size: 82%\9;
_font-family: Verdana, Arial, "MS Pゴシック", sans-serif;
_vertical-align: baseline;
color: #333;
}
body:not(:target) {
font-family: Verdana, Arial, "メイリオ", Meiryo, "MS Pゴシック", sans-serif\9;
font-size: 82%\9;
}
\9ハックはIE8以下のブラウザにスタイルを適用するハックです。IE9はこのハックは適用されませんので:not(:target) { color: #333\9; }
と記述する事によりIE9に適用されます。
_ハックはIE6のみに適用されるハックです。
セレクタハックを使うより記述がシンプルだと思います。ちなみに僕はSassを使っているので、こんな形で記述しています。
@mixin font-main {
font: {
family: Verdana, Arial, Hiragino Kaku Gothic Pro, "ヒラギノ角ゴ W3", Osaka, "MS Pゴシック", sans-serif;
size: 13px;
}
}
@mixin font-ie {
font: {
family: Verdana, Arial, "メイリオ", Meiryo, "MS Pゴシック", sans-serif\9;
size: 82%\9;
}
}
@mixin font-lte-ie6 {
_font-family: Verdana, Arial, "MS Pゴシック", sans-serif;
_vertical-align: baseline;
}
body {
@include font-main;
@include font-ie;
@include font-lte-ie6;
color: #333;
&:not(:target) {
@include font-ie;
}
}
これがコンパイルされると先述したCSSコードになります。
]]>1回目は指定した秒数ごとに画像がスライドする無限ループのカルーセルを作ります。2回目は無限ループに加え、ボタンを画像分用意し、クリックするとボタンに対応した画像が表示されると言ったものに改造して行きます。(余裕があれば3回の記事にし、プラグイン化しようと思います。)
プログラムの流れは下記のような流れに従って作ります。
それではコードを解説して行きます。
HTMLは下記のようなソースコードになります。
HTML Code
<div id="carousel">
<div class="window">
<div class="images">
<ul>
<li><img src="img/img_c-photo01.jpg" width="360" height="270" alt="" />/li>
<li><img src="img/img_c-photo02.jpg" width="360" height="270" alt="" /></li>
<li><img src="img/img_c-photo03.jpg" width="360" height="270" alt="" /></li>
<li><img src="img/img_c-photo04.jpg" width="360" height="270" alt="" /></li>
<li><img src="img/img_c-photo05.jpg" width="360" height="270" alt="" /></li>
<li><img src="img/img_c-photo06.jpg" width="360" height="270" alt="" /></li>
</ul>
</div>
</div>
</div>
図にするとこんな感じです。div#carouselの中にdiv.windowがあります。div.windowの役目は画像を表示する領域の指定です。画像(img要素)はul liでマークアップし、div.imagesで包みます。このdiv.imagesを一定時間ごとに左へスライドさせます。
まずは初期設定です。ここでは使い回しそうな値を変数に入れておきます。
jQuery Code
$(function() {
var carousel = $('div.images');
var carouselUl = carousel.children();
var carouselLi = carouselUl.find('li');
var imageWidth = carouselLi.find('img').width();
});
初期設定ではそれぞれの値を変数に入れておきます。
今回作るカルーセルは画像を無限にスライドさせます。無限ループをすると言う事は、最後の画像が表示されたら画像リストを元の位置(座標0,0)に戻す必要があります。
この際に画像リストが1組しかないと、最後の画像が左にスライドする事無く元の位置に戻るため、きれいなアニメーションになりません。
この状態を回避するにはもう1組の画像リストを用意し、2組目の画像リストが表示された時にdiv.images(var carousel)を元の位置に戻してあげればいいわけです。
要素を複製するには.clone()メソッドを利用します。そして複製した要素をdiv.imagesに追加します。要素を追加するには.appendTo()を利用します。
これでdiv.imagesには2つのul要素を内包しました。このdiv.imagesには幅をセットします。幅を指定するには.css('property', 'value')を利用します。
幅の値は(画像の幅 × 画像の数) × 2で求めらるので次のようなコードになります。
jQuery Code
carouselUl.clone().appendTo(carousel); //カルーセルする画像リストを複製して要素に追加
carousel.css('width', carouselLi.length * imageWidth * 2); //幅を設定
いよいよアニメーションの部分に入ります。画像の幅分左にスライドするアニメーションを作ります。アニメーションは下図のようにdiv.images(carousel)を指定した秒ごとにimgの幅分(imageWidth)スライドすると言うものです。
表示領域のdiv.windowにはCSSでposition: relative;を記述してます。この左端を起点にdiv.imagesをposition: absolute;で絶対配置し、jQueryのanimateメソッドでleftプロパティを操作します。
animateメソッドは.animate(params, [duration], [easing], [callback])のような書式になります。paramsにはcssのプロパティを、durationにはアニメーションの動作時間をミリ秒で、または'slow'や'normal'、'fast'などのキーワードで、easingにはイージングを指定します(easingプラグインを入れてない場合は'liner'か'swing'のみ)。callbackにはアニメーションが終わった後に実行するメソッドを指定します(コールバック関数と言います)
まずは左に画像の幅分スライドするアニメーションを記述します。
jQuery Code
carousel.animate({'left' : '-=' +(imageWidth)}, 'slow'});
これだけでは1回しかアニメーションは実行されません。常にアニメーションをさせるにはsetInterval()を利用します。
setIntervalを利用すると指定した秒数ごとに実行するメソッドを呼び出す事が出来ます。setIntervalは次のような書式になります。
jQuery Code
setInterval(function() {
Do something
},ミリ秒);
先ほど記述したアニメーションをメソッド化してDo somethingの所で指定した秒数ごとに呼び出すようにしましょう。
jQuery Code
function carouselAnimate() {
carousel.animate({'left' : '-=' +(imageWidth)}, 'slow'});
}
setInterval(function() {
carouselAnimate();
},2000);
これで2000ミリ秒毎にcarouselAnimate()が呼び出されるので、2000ミリ秒毎にdiv.images(carousel)がimageWidth分左にスライドして行きます。
さて、ここまでのコードを1度まとめて見てみましょう。
jQuery Code
$(function() {
//初期設定
var carousel = $('#images');
var carouselUl = carousel.children();
var carouselLi = carouselUl.find('li');
var imageWidth = carouselLi.find('img').width();
carouselUl.clone().appendTo(carousel); //カルーセルする画像リストを複製して要素に追加
carousel.css('width', carouselLi.length * imageWidth * 2); //幅を設定
//スライドアニメーション
function carouselAnimate() {
carousel.animate({'left' : '-=' +(imageWidth)}, 'slow'});
}
//指定した秒数ごとの処理
setInterval(function() {
carouselAnimate();
},2000);
});
さて、このままではdiv.imagesは永遠に左にスライドし続けてしまいます。さきほどちょっと触れた無限ループの動作を作って行きます。
スライドアニメーションを無限ループにするためには複製した2組目の画像リストの1番目の画像が表示された後直後に、div.images(carousel)を元の位置(座標0,0)に戻してあげます。
そのためには複製された2組目の画像の1枚目を特定する必要があります。そのためにはカウントアップする変数を用意して、表示領域に表示されている画像が何枚目かを特定します。仕組みは下記のようになります。
この動作を繰り返せば無限ループが実現出来ます。
現在まで出来たコードに変数countを追加し、3の条件を判定するメソッドを追加します。そしてアニメーションメソッドのcarouselAnimate()の中で呼び出される.animate()のコールバック関数で条件判定のメソッドを実行します。
jQuery Code
$(function() {
var count = 0; //カウンター
===== 中略 =====
function carouselAnimate() {
count ++; //アニメーションする度にカウンター変数を1ずつ加算して行く
carousel.animate({'left' : '-=' +(imageWidth)}, 'slow',
//コールバック関数で条件メソッドを呼び出す
function(){
positionInit();
});
}
//現在の表示されている画像を判別するメソッド
function positionInit() {
if(!(count % imageLength)) { //カウンターの数を画像の数で割った余りがゼロなら
carousel.css({'left': 0}); //div#imagesを左端に戻す
count = 0; //カウンターを初期化
}
}
});
これで無限ループするカルーセルが出来上がりました。長くなりましたが完成したコードは下記のようになります。
jQuery Code
$(function() {
//初期設定
var count = 0; //カウンター
var carousel = $('#images'); //カルーセルする画像が梱包されているdiv
var carouselUl = carousel.children();
var carouselLi = carouselUl.find('li'); //カルーセルする画像リスト
var imageWidth = carouselLi.find('img').width(); //画像の幅
var imageLength = carouselLi.length; //画像の数
carouselUl.clone().appendTo(carousel); //カルーセルする画像リストを複製して要素に追加
carousel.css('width', carouselLi.length * imageWidth * 2); //カルーセルする画像リストの横幅を設定
//アニメーション
function carouselAnimate() {
count ++; //アニメーションする度にカウンター変数を1ずつ加算して行く
carousel.animate({
'left' : '-=' +(imageWidth)
}, 'slow',
function(){
positionInit()
}
);
}
//現在の表示されている画像を判別するメソッド
function positionInit() {
if(!(count % imageLength)) { //カウンターの数を画像の数で割った余りがゼロなら
carousel.css({'left': 0});
count = 0;
}
}
setInterval(function() {
carouselAnimate();
},2000);
});
説明も長く、難しかったかもしれませんが、仕組みを知ると色々と応用が効いてくると思います。デモをダウンロード出来るようにしておきますので是非試して見てください。
]]>