jQueryの使い方を簡単に説明してみるなど
私が出入りしている某社のWebをメンテナンスしている部署の方々から「こういうのやりたいんだけど、出来る?」とコンテンツの開閉を見せられたりやら、「jQueryの本だけは買ってみたんだけど...」的な話をチラホラ聞かされたりなど、この手の事に興味を持ってもらえそうな感じだったので、5分程度でさらっとなぞれる解説を書いてみてました。 まあ僕も人に偉そうに言えるほど詳しい訳じゃないんですが...
ちなみにターゲットとしているのは、CSSすら若干怪しく、JavaScriptはDocument.writeでコンテンツを差し込む為のものだと半ば本気で思っている人たちです。そういう人向けに書いてます。
本当はもうちょっと社内の実例を出しながら書いてあったので流石にマズいので適当に変えて晒してみたいと思います。
続きを読むCSSなblendingを試してみる等
こないだ見つけてこれは素晴らしいと一人大盛り上がりしていたCSS3のblend-modeについて。 このところnode-webkitでいろいろ映像絡みのオモチャを作っているので、主にその辺を前提にこいつを触ってみました。
なんなんそれ
どんなもんなのかはこちらのサイトさんで割とわかりやすく解説されてます。
動作環境
別にWebkit限定でないみたいですが、とりあえずChromiumではデフォルトで動作。GoogleChromeは現在のDevChannelでもFlagsで有効化が必要です。
触ってみた感じ
Photoshop野郎としては提案者のAdobeが仕様として合成の計算式出してる事もありPhotoshopのレイヤーモードの感覚で使えるのがなにより好印象です。(乗算・スクリーン以外は割とグラフィックソフト間で結果が異なったりするもんで)
動かしてみた。
Chromeの上でいくつかテストしてみました。 上の動画はそのときのテストの要素をキャプチャしたもんです。
img要素にただanimationを乗せた状態
単なる重ね合わせなので、透過もなにもないです。レンダリングもちゃんと補完がかかります。まあこの地点では特に今回のblendingはまったく関係ありません。mix-blend-mode: screen; を有効にする。
それぞれのリングが重なり合い、3つとも重なったところが白になっています。レイヤーモードが正しくスクリーンとして扱われている証拠です。しかしながら、transformによる変形の補間がかからなくなりました。さらに親要素にfilter:blur(6px)を与える
親要素にfilter:blurを掛けてもちゃんとブラーがかかります。何故親要素に掛けたのかというと...実はimgそのものにデバッガーからフィルタを掛けるとおもっくそ崩壊したからです。(ちなみにあらかじめCSSで与えてるとちゃんと出るにはでますが、animateを与えると壊れます)ちなみにこんな具合に壊れます。
一旦blurを抜き、下にvideoタグを引く
ではvideoタグの上ではどうか?問題なかったです。この地点までは。 ただ、この状態、レイヤーの合成モードが伝搬せず、この画像を囲ってる親要素で止まってるんですわ。 この辺の挙動はまだよく分からない。この要素にblendオプションを掛ければ望み通りなんですが...さらに親要素にmix-blend-mode: screen; を掛ける
はい、豪快に壊れましたね。animateに引っ張られていく感じです。 ただ動かさない限りは問題無く動きそうな感じではありますな。
まあ軽く触っただけなのでまだなんも言えませんが、現状の実装でもそれなりに面白い使い方はできそうです。
俺はclickイベントを書くように、tapイベントを書きたいんだ。
きっとこの少年だって、きっとパズドラとかで画面タップしまくってるハズ。 いや、あれどういうゲームかしらんのですけどね。そしてこれは単にGettyImages使ってみたかっただけですね、はい。
というわけで、タイトルのアレを書いてみました。
参考にさせて頂いたのはこちら。 http://pro-tyablog.blogspot.jp/2013/09/javascript.html
やってることはまんまですね。
(function($){
$.fn.tap=function(callback){
return this.each(function() {
$(this).on('touchstart touchmove touchend click', function(event){
//タッチ開始の場合、要素のdata-isTouchフラグをtrueに
if ('touchstart' == event.type){
$(this).data('isTouch', true);
};
//touchmoveを拾った場合、要素のdata-isTouchフラグをfalseに
if ('touchmove' == event.type){
$(this).data('isTouch',false);
};
//isTouchフラグがあった場合、callbackを呼ぶ。
if ($(this).data('isTouch')){
//preventDefaultでclickの発生を抑止
event.preventDefault();
// フラグをfalseに
$(this).data('isTouch',false);
return callback.call(this)
};
if ('click' == event.type){
//clickの場合は普通にそのまま返す。
return callback.call(this)
};
})
});
};
})(jQuery);
- ontouchstartでフラグ付けて、
- ontouchmoveでフラグをキャンセル、
- ontouchendでフラグが存在したらイベントを発生させる、
という感じです。ただシンプルに書けるようにしたかったので、jQueryプラグイン化して、tap(fn)で書けるようにしました。 クリックイベントでも発生するので、タッチデバイス向けに高速なタップがなされがちな箇所はこれに置き換えるだけでサクっと 出来る筈。
jQueryのanimateをキーフレーム打ちできるようにしてみるなど
jQueryのanimateを大量に書き連ねなくちゃいけないときが、あるんです。男には。 で、その上それがcallback地獄になってて、コードのど真ん中に美しいピラミッドが出来上がってたりするんです。 まあ、イケてないよね、正直。キーフレーム打てたらそれでそもそも解決じゃん?みたいな。
というわけで書いてみた。
使い方
プラグイン本体はこいつ
(function($){
$.fn.keyframeAnimate = function(keyframes,interval,easing,callback){
var keyframe = []
var lastframe = 0;
//各プロパティをばらすと共に、各プロパティの指定フレーム数をチェック。
for(key in keyframes){
if(lastframe <= keyframes[key].length){
lastframe = keyframes[key].length
}
keyframe.push({property:key,frames:keyframes[key]})
}
//最長フレーム数に合わせて、最終フレームのコピーで埋める
for(i=0,il=keyframe.length;i<il;i++){
var currentLength = keyframe[i].frames.length;
if(currentLength < lastframe){
var lastValue = keyframe[i].frames[currentLength-1];
var fillcount = lastframe - currentLength;
for(j=0;j<fillcount;j++){
keyframe[i].frames.push(lastValue)
}
}
}
return this.each(function() {
var $el = $(this);
var scope = this;
var i = 0;
function doAnimate(i){
var frame = {};
for(j=0,jl=keyframe.length;j<jl;j++){
frame[""+keyframe[j].property] = keyframe[j].frames[i]
}
$el.animate(frame,interval,easing,function(){
i++
if(i<lastframe){
doAnimate(i)
}else if(i == lastframe){
return callback.call(this)
}
})
}
doAnimate(i);
});
};
})(jQuery);
書き方汚いのは毎度の事だ気にするな。 使い方はだいたいjQuery.animate()と同じだけど、プロパティの値の指定を配列で渡す事と、durationではなくフレームの間隔の指定になるという点のみが違う。またキーフレームは一番指定数の多いところが優先されて、例えば全長6フレーム指定なのに、一部プロパティが4フレームまでの指定、になると5,6は4の値を継続して指定される。
$("#test").keyframeAnimate({
top:[50,-40,30,-20,10,0],
opacity:[0.3,0.6,1]
},100,"swing",function(){
//callback処理
});
こんな具合。かなりスッキリ出来ると思うの。jsdo.itで晒しているのは、エロい人が直してくれると信じているからなので、だれかもっとスマートに書き直してください。以上!おやすみ!
CSSアニメーションのコールバックを簡単に済ませる方法を考える
CSSアニメーションはJavaScriptでのアニメーションと違いハードウェアの恩恵を受けれるので非常に負荷も軽くかつなめらかに動かせるという利点はあるものの、こいつはこいつでJavaScriptとの連携を取るに当たっては少々面倒な手段を取らざるを得ない事が度々御座います。
そんなわけで書いてみたのがこれ。深夜の3分間クッキングにふさわしい、たった11行の、まるで卵かけご飯を料理と言い張るようなシロモノです。
なんの事ありません。たったこれだけの事です。
(function($){
$.fn.animateCallback = function(callback){
var alias = "animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd"
return this.each(function() {
$(this).bind(alias, function(){
$(this).unbind(alias);
return callback.call(this)
});
});
};
})(jQuery);
引数はcallbackのみです。シンプルです。要素のイベントハンドラ、animationEndにさくっとcallbackとその実行の直前にイベントハンドラの中身を空にするようにしているだけです。
なんか書きがちな処理なんですが、毎度毎度こんなの書いてるのも面倒なので。これどっかに置いておけば、アニメーション終了後にアニメーションさせるclassを消すって処理はこんな感じにできます。
$("#button").bind("click",function(){
$("#testTarget").animateCallback(function(){
$("#testTarget").removeClass("doAnimate")
}).addClass("doAnimate")
});
以上、深夜の3分間クッキングですた。
追記 : callbackにthisを用いてないのは、スコープがその上のclickイベント基準になってるからな訳ですが、この辺りbind同様にthisをそのオブジェクト基準にさせんのってどうしたら良いんでしょ。私はゆるふわガーリーなのでよく知りません。解決 : @tektoh氏が ”return callback.call(this); でどうでしょう” と答えをするっと出してくれマスタ。なるほど、こうやればいいのか。無知は晒しとくもんだね!助かりマスタ。