最近、CSSアニメーションの終了をJSに伝える手法をもろもろ試し、これからは transitionend をつかおうと心に決めたのですが、これまでは transitionend のことを信頼してなかったので下記のような方法を考案し、つかってました。
- アニメーションさせる要素は .data-sec という子要素を持つ
- SCSSをつかい、.data-sec の zoom には transition-duration と同じ値を入れる
- アニメーションさせる要素に .anim というクラスが振られた際にアニメーションがスタートする
- JS側は .data-sec の zoom を取得し transition-duration の値を知る
JavaScript
(function(win, doc, ns) { "use strict"; function Sprite(id) { var that = this; _init(); function _init() { that.duration = 0; that.$elm = $("#" + id); that.$sec = $("<div>"); that.$sec.addClass("data-sec").css({ display: "none", width: 0, height: 0 }); that.$elm.append(that.$sec); } } Sprite.CONST = { START_KLASS : "anim" }; Sprite.EVENT = { ANIM_END : "animend" }; Sprite.prototype.start = function() { var that = this, dfd = new ns.Util.Deferred(), zoom; that.$elm.addClass(Sprite.CONST.START_KLASS); if (!that.duration) { zoom = that.$sec.css("zoom"); if (/\%/.test(zoom)) { that.duration = parseFloat(that.$sec.css("zoom"), 10) * 10; } else { that.duration = parseFloat(that.$sec.css("zoom"), 10) * 1000; } } setTimeout(function() { var param = { duration : that.duration }; dfd.resolve(param); }, that.duration); return dfd; }; Sprite.prototype.reset = function() { var that = this; that.$elm.removeClass(Sprite.CONST.START_KLASS); }; ns.Sprite = Sprite; })(this, document, App);
SCSS
@mixin sprite($duration) { transition-duration: #{$duration}s; .data-sec { zoom: $duration; } } .sprite { $duration: .5; @include sprite($duration); } body { background: #e3e3e3; } .box { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; border-radius: 20px; width: 120px; height: 120px; background: #3e3e3e; box-shadow: 0 0 2px rgba(0, 0, 0, .2); transition-property: all; transition-timing-function: ease-in-out; &.anim { width: 200px; height: 200px; } }