CSS Filtersで写真加工するWebApp - CSS PhotoEditor


iOS6も発表されて、あとはNew iPhoneのリリースが待たれる季節ですね。私は3Gの発売時に買い替えて、2年後iPhone4にし、また2年が経とうとしているので今年は新しいのに買い換えようという気持ちです。
世間ではAppleのマップでいろいろと騒いでいたりしますが、OSがアップデートされるたびに私がチェックすることといえばブラウザの仕様や機能の変更です。
去年はWebAppやスマホサイトを作るには嬉しい変更がありました。position:fixedやiframeの慣性スクロール、他にもSVGや縦書き、明朝フォントのサポートもありました。
その辺りはiOS5のMobile Safariから使えるようになったHTML5・CSSを試してみました【前編】【後編】というエントリーでまとめて書いています。このときもデモ用にフルスクリーンで使えるWebAppを作成しました。

今回はCSS Filtersの可能性を試すためにデモを作ってみました。

CSS PhotoEditorについて

まずは見てください! …と言いたいところですが、重要なinput type="file"やCSS FiltersはiOS5では動きません。PCブラウザでも現在(2012/07/26)時点でCSS Filtersが動作するのは最新のChromeと本日公開されたSafari6です。なので今はChromeか最新のSafariで見ていただくのが良いかと思います。

DEMO:CSS PhotoEditor
(Supported : Chrome20, Safari6)

CSS PhotoEditorとは言っているものの、結構なJSを書いてます。なのでCSS PhotoEditorのCSSっていうのはほとんどCSS Filtersの部分のことのみを言っていますね。Slider UIを使うにあたってどうしてもJSでValueを取ってこないとどうにもならないので、じゃあもうCSSにこだわらないでJSをばりばり書こうとなったのです。そのおかげでかなりリッチな仕様に仕上がりました。

Ajax file upload

CSS PhotoEditorではAJAXでアップロードしてそのまま編集できるようにしています。ただDEMO用のWebAppなのであまり期待しないでください。バックエンドはPHPで書いていますが、なんちゃってコードなのであまり変な画像とか上げようとしないでくださいね。AjaxアップロードにはjQuery.uploadを使わせていただきました。

Slider UI


Slider UIはinput type="range"を使いました。今までだとSlider UIはインタフェースもすべてJSで書く必要があったのですが、input type="range"を使えばvalueを取ってくるだけですむので非常に便利ですね。input type="range"にはname/value属性の他に、入力できる最大・最小値を設定するmax/min属性や入力ステップ値を設定できるstep属性などが設定できます。
StyleはCSSで変更することができます。スライダーの軸となる部分のグラフィックinput[type='range']で、ハンドルの部分のグラフィックは::-webkit-slider-thumbをつけたセレクタで変更することができます。具体的にはこんな感じです。

input[type='range'] {
  width:270px;
  height:52px;
  margin:0;
  -webkit-appearance: none !important;
  background:url(images/slider-line.png) no-repeat 10px 20px;
  -webkit-background-size:250px 11px;
}
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none !important;
  background:url(images/slider-handle.png) no-repeat 0 7px;
  width:41px;
  height:52px;
  border:0;
  -webkit-background-size:410px 40px;
  cursor:-webkit-grab;
}

今回は使っていませんがborder-imageを使えばリキッドに対応したスライダーUIが作れそうな気がしますね。

Flip transition

右上のインフォメーションボタンを押した時のクルッというトランジションは、いつものCSS Transitionを使用しています。iOS5のMobile Safariから使えるようになったHTML5・CSSを試してみました【後編】CSS3によるTransition Effects 30でも紹介しました。よかったら参考にしてみてください。

Media queries & Landscape mode

実を言うと当初はiPhoneで見るためのデモサイトを作るだけの予定でした。Chromeで確認しながら作って、ある程度できた段階でiPhoneで確認する感じで作っていました。ほとんど出来上がってからChromeで見ている画面が寂しくなって、じゃあPC用の画面も作ろうとなってそこでMedia queriesでやることにしました。
なのでChromeで見ている画面はOverviewページのようでありながら、Windowを縮めていくとフルスクリーンWebAppになるというおもしろい感じになりました。one sourceなのでデバックもやりやすくてよかったです。

iPhoneをLandscape Viewで使っている人をあまり見かけないので手を抜きがちになりやすいですが、今回はPCでも見れるようにという事でLandscape Modeもがっつり対応しました。
Chromeで見ている場合はWindowサイズを縮めてWebAppモードにしつつ、横長の画面にするとLandscape Modeで見ることができます。縦が短くなるのでメニューの位置を横に移して写真領域を大きく見れるレイアウトにしています。

CSS Filtersについて

CSS FiltersはW3CのFilter Effects 1.0を元に実装されているようです。7. Filter Functionsに使用できるエフェクトの詳細について書かれています。opacityやdrop-shadowなんかも含まれていますが、これらとCSSのプロパティのopacityなどとはどう違いがあるんでしょうかね。描画方法に差があったりするのだろうか。

シンプルなデモページを作ったので御覧ください。クリックでフィルターがトグルします。
CSS Filters Demo's capture
CSS Filters Demo

以下にそれぞれ簡単な説明も書いてみます。

grayscale( | )

グレースケールは単純に彩度を落とすだけのフィルターですね。0〜100%の値で指定でき、0%がdefaultで100%で完全なグレースケールになります。

.grayscale {
  filter: grayscale(50%);
  -webkit-filter: grayscale(50%);
}
sepia( | )

セピアもグレースケールと同じ感じの値の設定・default値です。100%で完全なセピアカラーになります。

.sepia {
  filter: sepia(80%);
  -webkit-filter: sepia(80%);
}
saturate( | )

saturateは彩度を変更できるフィルターで、0%以上の値を設定できます。default値は100%で、0%でモノクロになります。彩度を高くしたい場合は100%以上の値を設定します。

.saturate {
  filter: saturate(240%);
  -webkit-filter: saturate(240%);
}
hue-rotate()

hue-rotateは色相を変更できます。値は-90degや45degのように角度で指定します。default値は0degです。

.hue-rotate {
  filter: hue-rotate(120deg);
  -webkit-filter: hue-rotate(120deg);
}
invert( | )

invertは色の反転フィルターです。100%で完全に反転して、default値は0%です。

.invert {
  filter: invert(80%);
  -webkit-filter: invert(80%);
}
opacity( | )

透過フィルターです。0%で完全に透明になり、default値は100%です。

.opacity {
  filter: opacity(50%);
  -webkit-filter: opacity(50%);
}
brightness( | )

brightnessは明度を変更するフィルターです。-100%〜100%の値で指定でき、0%がdefaultで100%で真っ白になります。-100%にすると真っ黒になります。

.brightness {
  filter: brightness(30%);
  -webkit-filter: brightness(30%);
}
contrast( | )

コントラストはsaturateと同じ感じの値の設定・default値です。コントラストを高くしたい場合は100%以上の値を設定します。

.contrast {
  filter: contrast(120%);
  -webkit-filter: contrast(120%);
}
blur()

blurはぼかしフィルターです。ぼかす範囲をpxなどで指定します。defaultは0です。

.blur {
  filter: blur(10px);
  -webkit-filter: blur(10px);
}
drop-shadow()

ドロップシャドウはCSSプロパティのbox-shadowと同じです。値の指定方法も同じです。

.drop-shadow {
  filter: drop-shadow(8px 8px 10px rgba(0,0,0,0.5));
  -webkit-filter: drop-shadow(8px 8px 10px rgba(0,0,0,0.5));
}


個人的にはcustom functionを試してみたかったのですが、まだ実装されていないようです。custom filterにはProgrammable shaderをフィルターとして使用することができます。vertex-shaderという複雑なtransformをすることができる値やfragment-shaderというピクセルにエフェクトをかける値を設定したりします。WebGLやOpenGLの表現をCSSで利用できるので、やろうと思えばよりダイナミックなグラフィック表現ができます。説明だけだとわからないと思います。以下のサイトでデモを紹介しています。


Introducing CSS shaders: Cinematic effects for the web

おまけ

週末2日間でひと通り作ったのですが、やっているうちにどんどんリッチになっていきました。他にも実は搭載されている機能を紹介しようと思います。

WebApp Mode

これはデモ動画でも紹介されているし、当たり前といえば当たり前ですね。ホーム画面に登録してNative Appぽく起動することもできます。

Capture Mode

ある程度つくった段階で友人などに見せていたのですが「保存はできないの?」といった意見もありました。「いやいやデモだし」と濁していたのですが、せめてスクリーンキャプチャで撮ってもらえるようにしてみたらという意見をいただいて作りました。写真をダブルタップすることでツールバーなどが消えて、写真が良い感じにフルスクリーンになります。ホーム画面から起動するWebAppではStatus Barが消せないのがもどかしいです。

Force WebApp Mode

Overviewモードで見ているときに強制的にWebAppモードに切り替えるスイッチです。Overviewモードでインフォメーションボタンを押して表示される「WebApp Mode by Force」という項目でオンにすることができます。Window幅を縮めているときは表示されません。

Filter Param List

これは本当におまけな機能で、Overviewモードで見ているときだけの機能です。Overviewモードで表示しているときに、白いiPhoneのホームボタンを押すと設定されているフィルターの値のリストが表示されます。

まとめ

iOS6ではファイルアップロードに対応するというAppleの発表でSNSなどのWebAppも写真投稿などに対応していることだと思います。環境が限られているとはいえ、CSS Filtersも使いようによれば効果的な表現ができるように思います。
NativeAppのほうが使いやすいに決まっているし、WebAppはそんなに重要じゃないと思うかもしれませんが、スマートフォンからWebを見る機会は案外多いです。TwitterやFacebookなどで流れてきたURLをひらくときは、アプリ内とはいえWebViewで見ているのですから。当たり前ですが、WebからもNativeAppと変わらない体験を提供することは欠かせないことだと考えます。

追記

一部NDAに触れる可能性のある部分がありましたので編集しました。