CSSのanimationやtransitionの終了をJavascriptで検知する

簡単なサンプルを作成。
まずはHTML。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>TEST</title>
<link rel="stylesheet" href="style.css" type="text/css" media="screen" charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js" charset="utf-8"></script>
<script src="zoom.js" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">btn</button><br>
<div class="container">
	<div class="box">
		<div class="inner"></div>
	</div>
</div>
</body>
</html>

つづいてCSS。ボックスが中心に表示されるように設定。

button {
	font-size: 16px;
}

.container {
	position: relative;
	vertical-align: top;
	position: relative;
	width: 480px;
	height: 480px;
	border: 1px solid #ddd;
}

.box {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 200px;
	height: 200px;
	background: #99b1ee;
	-webkit-transform: translate(-50%, -50%);
	-moz-transform   : translate(-50%, -50%);
	-ms-transform    : translate(-50%, -50%);
	transform        : translate(-50%, -50%);
	-webkit-transition: all 1s ease 0s;
	transition        : all 1s ease 0s;
}

.box.active {
	width: 300px;
	height: 300px;
}

最後にJS。

$(function() {
	var transitionEndEvents = [
		'webkitTransitionEnd',
		'mozTransitionEnd',
		'oTransitionEnd',
		'transitionend'
	];
	var animEnd = transitionEndEvents.join(' ')

	$('.box').on(animEnd, function() {
		alert('done!');
	});
	
	$('#btn').on('click', function() {
		var $el = $('.box');
		if ($el.hasClass('active')) {
			$el.removeClass('active');
			return false;
		}
		$el.addClass('active');
	});
});

CSSの.activeで、widthとheightを変更しているので、完了後のアラートは2回表示さる。

月の情報を便利に使う

Javascriptで指定月の情報を取得して、それを毎度毎度、組み立てていくのが手間なので、オブジェクトっぽく引き出せるようにJSファイルを作りました。

MonthObj.js

/**
 * MonthObj.js
 * Month Object
**/

/* MonthObjクラス
================================================== */
function MonthObj(dateObj) {
	var y = dateObj.getFullYear();
	var m = dateObj.getMonth();

	// Paramater
	this.monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	this.classes = {
		month: ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
		week: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
	}

	// Today Info
	this.today = new Date();
	this.todaysYear = this.today.getFullYear();
	this.todaysMonth = this.today.getMonth();
	this.todaysDate = this.today.getDate();
	this.isTodayThisMonth = (this.todaysYear == y && this.todaysMonth == m) ? true : false;

	// 指定月 Info
	this.Year = y;
	this.Month = m;
	if ( ((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0 ) this.monthDays[1] = 29;
	this.days = this.getObjArray()

	this.firstday = this.getFirstDay();
	this.lastday = this.getLastDay();

	return this;
}


/* 日の情報を月単位オブジェクトで返す
================================================== */
MonthObj.prototype.getObjArray = function() {
	var arr = [];

	for (var i = 1, len = this.monthDays[this.Month]; i <= len; i++) {
		var o = {
			year		: this.Year,
			month		: this.Month,
			date		: i,
			day			: new Date(this.Year, this.Month, i).getDay(),
			css_month	: this.classes.month[this.Month],
			css_week	: null,
			past_weeks_m: this.getWeeksOfMonth(i),
			past_weeks_y: this.getWeeksOfYear(i),
			today		: false
		};

		o.css_week = this.classes.week[o.day];

		if (this.isTodayThisMonth && this.todaysDate == i) o.today = true;

		arr[i - 1] = o;
	}

	return arr;
}


/* 最初の曜日
================================================== */
MonthObj.prototype.getFirstDay = function() {
	return new Date(this.Year, this.Month, 1).getDay();
}


/* 最後の曜日
================================================== */
MonthObj.prototype.getLastDay = function() {
	return new Date(this.Year, this.Month, this.monthDays[this.Month]).getDay();
}


/* 始めの空白数
================================================== */
MonthObj.prototype.getCountBeforeDays = function() {
	return this.getFirstDay();
}


/* 最後の空白数
================================================== */
MonthObj.prototype.getCountAfterDays = function() {
	return (6 - this.getLastDay());
}


/* 月で何週目か
================================================== */
MonthObj.prototype.getWeeksOfMonth = function(d) {
	var t = new Date(this.Year, this.Month, d);
	var pastWeeks = Math.floor((t.getDate() - t.getDay() + 12) / 7);
	//console.log('-----');
	//console.log(m + ' 月\t第 ' + pastWeeks + ' 週目');
	return pastWeeks;
}


/* 1年で何週目か
================================================== */
MonthObj.prototype.getWeeksOfYear = function(d) {
	var t = new Date(this.Year, this.Month, d);
	var firstday = new Date(this.Year, 0, 1);// その年の1月1日
	var pastDays = Math.floor((t.getTime() - firstday.getTime()) / (1000 * 60 * 60 * 24));
	var pastWeeks = Math.floor((pastDays - t.getDay() + 12) / 7);
	//console.log(pastDays + ' 日目\t第 ' + pastWeeks + ' 週目');
	return pastWeeks;
}

使用例
MonthObj.html

<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>MonthObj Sample</title>
<style type="text/css" media="screen">
*,
*:after,
*:before {
	margin: 0;
	padding: 0;
	border: 0;
	-webkit-box-sizing: border-box;
	-moz-box-sizing   : border-box;
	box-sizing        : border-box;
}

html,
body {}

html {
	font-family: sans-serif;
	font-size: 62.5%;
	line-height: 1.5em;
}

body {
	font-size: 16px;
	font-size: 1.6rem;
}

.container {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 480px;
	padding: 30px;
	transform: translate(-50%, -50%);
	background: #f0f0f0;
}

.container h3 {
	text-align: center;
	margin: 0 auto 1em;
}

.monthContainer {}

.monthMain {
	display: table;
	border-collapse: collapse;
	border-spacing: 0;
	table-layout: fixed;
	width: 100%;
	background: #fff;
	font-family: monospace;
	text-align: center;
}

.monthMain > ul {
	display: table-row;
	list-style: none;
}

.monthMain > ul.monthHeader {
	font-weight: bold;
	background: #999;
	color: #fff;
}

.monthMain > ul > li {
	display: table-cell;
	vertical-align: middle;
	border: 1px solid #ccc;
}

.monthMain > ul > li > span,
.monthMain > ul > li > a {
	display: block;
	padding: 1em 0.25em;
}

.monthMain .today {
	background: #f7fdb0;
}

</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js" charset="utf-8"></script>
<script src="MonthObj.js" charset="utf-8"></script>
<script>
$(function() {
	
	_langs = {
		en: {
			month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
			month_s: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
			week:  ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
			week_s: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
		},
		ja: {
			month: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
			month_s: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
			week:  ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
			week_s: ['日', '月', '火', '水', '木', '金', '土']
		}
	};
	
	var t = new Date('2015-11-01');//Dateを生成
	
	var mm = new MonthObj(t);//オブジェクトを作成
	
	$('.monthTitle').html((t.getMonth() + 1) + '月');//月を表示
	
	createMonthView();//カレンダーを作成
	
	function createMonthView() {
		var tags = '';
		tags += '<div class="monthMain">';
		
		// ヘッダー(曜日)
		tags += '<ul class="monthHeader">';
		for (var i = 0; i < 7; i++) {
			tags += '<li><span>' + _langs.ja.week_s[i] + '</span></li>';
		}
		tags += '</ul>';
		tags += '<ul class="monthRow">';

		// 始めの空白表示 getCountBeforeDays()でいくつか空白かを取得できる
		for (var i = 0, len = mm.getCountBeforeDays(); i < len; i++) {
			tags += '<li class="empty"><span>empty</span></li>';
		}
		
		// 日数ループ days配列から情報を引き出す
		for (var i = 0, len = mm.days.length; i < len; i++) {
			var D = mm.days[i];

			console.log('==================================================');
			console.log(D);
			for (key in D) {
				console.log(key+':\t',D[key]);
			}
			
			if (D.day == 0) tags += '</ul><ul class="monthRow">';//週の終わりと初め
			
			tags += '<li class="';
			tags +=  D.css_month;
			tags +=  ' ';
			tags +=  D.css_week;
			if (D.today) {
				tags +=  ' today';
			}
			tags +=  '" data-year="' + D.year;
			tags +=  '" data-month="' + D.month;
			tags +=  '" data-date="' + D.date;
			tags += '"><span>'+ D.date +'</span></li>';
		}
		
		// 最後の空白表示 getCountAfterDaysでいくつか空白かを取得できる
		for (var i = 0, len = mm.getCountAfterDays(); i < len; i++) {
			tags += '<li class="empty"><span>empty</span></li>';
		}
		
		tags += '</ul></div>';
		
		$('.monthContainer').html(tags);
	}
});
</script>
</head>
<body>
	<div class="container">
		<h3 class="monthTitle"></h3>
		<div class="monthContainer"></div>
	</div>
</body>
</html>

以上です。