Hatena::Groupsubtech

ういはるかぜの化学

Saturday, May 19, 2012

[][]HTML+JavaScriptでのMetro style appにおける制限 16:18 HTML+JavaScriptでのMetro style appにおける制限 - ういはるかぜの化学 を含むブックマーク はてなブックマーク - HTML+JavaScriptでのMetro style appにおける制限 - ういはるかぜの化学

去年の9月ごろに書いていたのだけど、ほかに書くことを書いて順を追って公開しようと思っていたら寝かせすぎた…。msWWAがMSAppにかわってたりしたのでその辺を修正して公開。

Metro style appの実装形態としてHTML+JavaScript+CSSを選択することができ、Internet Explorer 10が持つ機能ローカルアプリケーションを実装できます

ローカルアプリケーションとして動くということで通常のブラウザ機能だけでなくネイティブ機能を利用できるようになっていますしかしながらそれと同時に仕様セキュリティ上の理由で一部の機能に制限がもうけられています

ウィンドウ操作

Metro style appでは新規ウィンドウ作成ウィンドウ位置変更など各種ウィンドウ操作は行えません。ウィンドウ操作にはダイアログも含まれます。具体的には以下のメソッドが影響を受けます

  • alert
  • prompt
  • open
  • moveby
  • moveto
  • resizeby
  • resizeto

だだし例外的にアプリケーションからはwindow.closeは実行できます。window.closeはアプリケーションの終了と同じですが基本的には使うべきではないとされています。利用すべき場面は復帰できないエラーが発生した場合に強制終了するといった使い方です。

javascriptスキーム

a要素のjavascriptスキームは動作しないようになっています。これはあまり困りませんね。

解決策

DOMclickイベントや直接書きたい場合にはonclick属性を利用するように書き換えます

innerHTML/outerHTML/insertAdjacentHTML/document.write に渡すことできるHTMLの制限

通常innerHTMLやdocument.write にはHTMLを渡して出力したり要素を生成したりできます

ところがMetro style appの場合にはinnerHTMLなどに渡すことのできるHTMLに制限がかかります。たとえば以下のようなコードを実行しようとします。

<script>
    window.addEventListener('DOMContentLoaded', function () {
        var divE = document.createElement('div');
        divE.innerHTML = "<a onclick='console.log(1)' href='#'>Link</a>";
        document.body.appendChild(divE);
    }, false);
</script>

すると実行時に以下の例外エラーが発生します。

0x800c001c - JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property or the document.write method to add a script element will generate this exception. If the content is safe and from a trusted source, use a method to explicitly manipulate elements and attributes, such as createElement, or use

これはinnerHTMLなどのプロパティメソッドに渡すことのできるHTMLセキュリティ上静的なもの(安全もの)となっていることが求められているためです。静的でないHTMLというのはscript要素やonなんとか属性、form要素などのスクリプト等の動的な要素をふくむもののことです。

許可される要素や属性IE8以降で実装されている window.toStaticHTML というscript要素をはじめとして動的・未知の要素・属性サニタイズをするメソッドを通るものです。Making HTML safer: details for toStaticHTML (HTML) - Windows app developmentにそのリストがありますsvg要素なども通らないので注意が必要です。

この制限は外部からデータを読み込んでそのままアプリケーションに流し込んだ際、悪意あるスクリプトを実行してしまうのを防ぐためにあるものと思われます

Metro style appはローカルアプリケーションなのでコンピュータへのアクセスが行えるようになっていて、たとえばファイル操作するようなスクリプトを含んだHTMLをinnerHTMLで差し込んでしまうとそのローカルアプリケーションの一部として実行されて困ったことが起こる、といった感じですね。

innerHTML以外にも以下のメソッドプロパティにこの制限のかかっています

  • innerHTML
  • outerHTML
  • insertAdjacentHTML
  • pasteHTML
  • document.write / document.writeln
  • DOMParser.pasteFromString
解決策: document.createElementを利用する

innerHTMLなどを使わずcreateElementで要素を作ってごく普通に内容をセットしていく方法です。この場合自前でHTMLパースしない限りは悪意あるスクリプトを取り込んでしまうことはなくなります

逆に自前でHTMLパースしてしまうと潜在的に危険ものも組み立ててしまう可能性があるので注意が必要です。

var divE = document.createElement('div');
var aE = document.createElement('a');
aE.href = "#";
aE.textContent = "Link";
divE.appendChild(aE);
document.body.appendChild(divE);
解決策: window.toStaticHTMLを利用してサニタイズする

innerHTMLなどが受け取って安全とされるものはwindow.toStaticHTMLを通ることを許可されている要素や属性、ということなのでtoStaticHTMLメソッドを利用してサニタイズしてしまます

var divE = document.createElement('div');
// <a onclick="console.log(1)" href="#">Link</a> -> <a href="#">Link</a>
divE.innerHTML = window.toStaticHTML('<a onclick="console.log(1)" href="#">Link</a>');
document.body.appendChild(divE);

toStaticHTMLで静的となったHTMLであればinnerHTMLにセットしてもエラーとならなくなります

解決策: 安全ではない操作として実行する

安全ではない操作を実行する」方法も用意されています。これはinnerHTMLなどに安全ではないHTMLをセットしても動く、普通IEと同様の挙動を実現する方法です。まあ、同様の挙動といっても「安全ではない操作単位での実行となるのでコードを若干修正する必要があります

安全ではない操作の実行にはwindow.MSAppに存在するexecUnsafeLocalFunctionメソッドを利用します。

execUnsafeLocalFunctionメソッド引数関数をとり、その関数を実行している間は各種のチェックが無効となります。たとえば以下のようなコードで動くようになります

<script>
    window.addEventListener('DOMContentLoaded', function () {
        var divE = document.createElement('div');
        MSApp.execUnsafeLocalFunction(function () {
            divE.innerHTML = "<a onclick='console.log(1)' href='#'>Link</a>";
        });
        document.body.appendChild(divE);
    }, false);
</script>

この方法は信頼されている、たとえばアプリケーションローカルリソースを読み込んでのようなデータ差し込む場合にのみ利用すべきです。

またこのinnerHTMLをセットする操作比較的行われる操作のため、Visual Studioなどテンプレートからアプリケーションを作った場合についてくるWinJSライブラリに以下のヘルパーメソッドとして用意されています

<script>
    window.addEventListener('DOMContentLoaded', function () {
        var divE = document.createElement('div');
        WinJS.Utilities.setInnerHTMLUnsafe(divE, "<a onclick='console.log(1)' href='#'>Link</a>");
        document.body.appendChild(divE);
    }, false);
</script>
注意

追記: 以下の点はRelease Previewで変更されて即座にエラーとなるようになりました。

この制限のわかりにくいポイントの一つとして、要素がドキュメントに追加された際にエラーが発生するというところがあります

以下のコードで実際エラーが発生するのはdocument.body.appendChildのタイミングとなります

<script>
    window.addEventListener('DOMContentLoaded', function () {
        var divE = document.createElement('div');
        divE.innerHTML = "<a onclick='console.log(1)' href='#'>Link</a>";
        document.body.appendChild(divE);
    }, false);
</script>

innerHTMLをセットした瞬間ではないのでjQueryを使っている場合などjQueryの内部で突然エラーが発生して悩むことになることがあります

サンプルコード

<!DOCTYPE html>
<meta charset="utf-8">
<title>Unsafe operations</title>
<link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet">
<script src="//Microsoft.WinJS.0.6/js/base.js"></script>
<script src="//Microsoft.WinJS.0.6/js/ui.js"></script>
<script>
    window.addEventListener('DOMContentLoaded', function () {
        var divE = document.createElement('div');

        // エラー
        //divE.innerHTML = "<a onclick='console.log(1)' href='#'>Link</a>";
        //document.body.appendChild(divE);

        // エラー
        //divE.outerHTML = "<a onclick='console.log(1)' href='#'>Link</a>";
        //document.body.appendChild(divE);

        // エラー
        //document.write("<script>alert(1);<"+ "/script>");

        // OK
        //divE.innerHTML = window.toStaticHTML("<a onclick='console.log(1)' href='#'>Link</a>");
        //document.body.appendChild(divE);

        // OK
        //WinJS.Utilities.setInnerHTMLUnsafe(divE, "<a onclick='console.log(1)' href='#'>Link</a>");
        //document.body.appendChild(divE);

        // OK
        window.MSApp.execUnsafeLocalFunction(function () { divE.innerHTML = "<a onclick='console.log(1)' href='#'>Link</a>"; });
        document.body.appendChild(divE);
    }, false);
</script>
<body>
</body>

Friday, February 03, 2012

[]Metro style appsはHTMLで書けるの?という話。 14:46 Metro style appsはHTMLで書けるの?という話。 - ういはるかぜの化学 を含むブックマーク はてなブックマーク - Metro style appsはHTMLで書けるの?という話。 - ういはるかぜの化学

Windows 8Metro style appsがHTMLJavaScript「で」書けるようになるということについて、先日Twitterでも少し誤解されていたのでちょっとまとめ直してみます

実際書けるの?

ざっくり整理するとこうなります

ちなみにここにはパッケージングが必要だとかそういう話は含めていません。

というわけで関連する技術適当に図にしたのがこれです。

f:id:mayuki:20120203143644p:image:w640

これはごく一般的なMetro style appsの形です。真ん中にInternet Explorerエンジンを置いて、上が普通のWebで使うことのできる技術、下がWindowsネイティブ技術です。

というわけですこし分解して見てみます

0. Web

Metro style appsの前にブラウザで見る普通のWebページの場合を。多分こんな感じ。ネイティブ機能は全くありません。

f:id:mayuki:20120203143645p:image:w640

1. 最小の構成

まず最初Metro style appsに必要最低限な構成です。この場合最低HTMLが1ファイルあれば出来上がりです(ほかにも必要であればCSSとかJSとかとか)。この時利用する技術普通のWebと同じレベル、いわゆるWeb標準としてあるものだけです。

f:id:mayuki:20120203143646p:image:w640

これでもとりあえず見た目がMetro styleかどうかはともかくMetro style appsです。

2. 先行実装、ベンダー拡張

はいちょっと機能にしたい、表現力を上げたいなどという時にはブラウザに先行実装されていたり、ベンダーが独自に拡張したCSSAPIを利用します。-ms-*プロパティとかですね。まあこれも最近Web世界では-webkit-*とかよく使われているのでそれですね。

f:id:mayuki:20120203143647p:image:w640

というわけでその辺りを盛り込んだものでもMetro style appsです。この時点ではやっぱりまだ普通のWebとあまり変わりません。

3. Windows Library for JavaScript

しかしそろそろちゃんとMetro styleにしたくなります。色合いやコントロールなどです。

そういったMetro styleらしいアプリケーションを構築するためにWindows Library for JavaScript、WinJSとよばれるライブラリ提供されていますライブラリと言いながらスタイルシートも含まれています

で、WinJSを使うようになるとこんな感じです。WinJSは色々な機能があり、必要なものだけを選択して(要するに.jsファイルの参照)使えるので取り敢えず見た目やベースライブラリだけを使う前提です。

f:id:mayuki:20120203143648p:image:w640

図をみるとわかりますがまだこの時点では拡張されたものも含めてWeb寄りの技術で構成されています

HTML版のMetro style appsではUIコントロールにWinJS.UIというものを使いますが、その記述も実態もHTML5と(拡張された)CSSJavaScriptで構成されています

書き方次第ではまだWeb共存できる可能性があります。が、WinJS.UIが他のベンダープレフィックスなどを考慮してくれることはないのでこの辺りから普通のブラウザと同じかどうかはだいぶ怪しくなります(IEでは動いてしまうけれどIEしか動かない)。

これはもちろんMetro style appsです。

4. Windowsネイティブ

そして最後Web標準になりそうもWebから扱えそうにもならないような機能(ブラウザに持つ必要のないもの)はWindowsネイティブ機能Windows Runtime(WinRT)に頼ることになります

たとえばコンテキストメニュー、ページナビゲーション、アプリケーションサスペンド、ソケット通信、ファイル操作といったローカルと密接なものたちなどです。またWinJSも一部WinRTを知っているので、協調して動いたりラッパーになっていたりするものがあります

f:id:mayuki:20120203143644p:image:w640

ここまで来て最初の図になります。そしてネイティブ機能を使うことになるのでもはやWeb技術だけではなくなります

そしてこの形がMetro style appsとしては一般的な構成になるとおもわれますVisual Studioテンプレートはこの形で吐き出します。

まとめ

というわけでHTMLで書けるかという話ですが最初のほうに書きましたが、大抵はWindows 8依存したHTMLで書くことになるけれどブラウザと同じ形にしようと思えばできる、です。

大抵のアプリケーション最後パターンになると思いますが、重要なのは1や2のパターンもアリだと言うことです。これはMetro styleを必要としないアプリケーション、例えば全て独自のUIをもつゲームなどを作る場合には有利になるのではないかと思います

ちなみに

Web標準的なもので書こうと思えば書けるといってはみたものの、一部操作に制限があったりするのでWebコードをそのまま持っていくと何らかの書き換えが必要になる場合がまれにあります。そんな時はMetro style appsに依存して回避する書き方か制限を回避する推奨される別な手段での書き方に修正が必要です。

トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20120203

Sunday, January 22, 2012

[]Metro style appsと解像度画面サイズと画面解像度 19:00 Metro style appsと解像度と画面サイズと画面解像度 - ういはるかぜの化学 を含むブックマーク はてなブックマーク - Metro style appsと解像度と画面サイズと画面解像度 - ういはるかぜの化学

このエントリの内容はWindows Developer Previewの仕様を元にしています。今後Betaリリース時には変更される可能性があることに注意してください。

Metro style appsの解像度に合わせたスケーリング - ういはるかぜの化学 - subtech でスケーリングについて書きましたが、その拡大率が決定される条件がちょっと謎な感じに見えます。たとえば同じ画面解像度1920x1080でも10.6インチ23インチとで拡大率が違うわけです。

しかVAIO Z(13インチ, 1920x1080)にWindows Developer Previewをインストールするとなぜかシステム解像度(以前からあるあのDPI設定)がデフォルトで120dpiになっています。その割にはMetro style appsはスケーリングしません。どうも画面サイズ(物理的な画面サイズ)をWindows側で把握してコントロールしているような感じです。

画面サイズの取得なんてとれるのかなと思って調べてみるとGetDeviceCaps 関数というWin32 APIにVERTSIZE,HORZSIZEを渡すと取れそうなのですがいろいろなところでまともな値は返さない(物理サイズの参考にはならない)という声も見かけます

まあそうはいっても他に見当たらないのでコードを書いてとりあえず試してみました。

https://gist.github.com/1656292

書いたコードVAIO L (24インチ, 1920x1080)で実行したところ530x300mmという値が返ってきました。24インチ16:9で53.13cm x 29.89cmぐらいらしいのでだいたいあってそうです。ならばとVAIO Z (13インチ, 1920x1080)で試してみると今度は290x160mmという値が返ってきました。やっぱりちゃんと動いているっぽいです。

Windows 7で動かすと677x381mmという明らかに変な値が出てくることからWindows 8からまともに機能するようになったようです。

というわけでこれをシミュレータで動かしたりして、さらにそのサイズからDPIを求めたりしてまとめたのが以下の表です。

環境 画面サイズ(インチ) Windowsが把握している画面サイズ 画面解像度 画面サイズと画面解像度で求めたDPI 拡大率
VAIO L 24 530x300mm 1920x1080 約92dpi x 91dpi 100%
VAIO Z 13 290x160mm 1920x1080 約168dpi x 171dpi 100%
シミュレーター 10.6 132x235mm 1366x768 約148dpi 100%
1920x1080 約207dpi 140%
2560x1440 約276dpi 180%
12 1280x800 162x258mm 約126dpi 100%
23 286x509mm 1920x1080 約96dpi 100%
27 336x598mm 2560x1440 約109dpi 100%

これでどういう意味があるかと言うと、どうもWindows 810.6インチ(1366x768)をスタンダード スレートと定義しているらしく(ガイドラインの一番上の図がそんな感じ)そこを基準にいろいろ決まっているようです。

たとえば10.6インチの1920x1080では140%に拡大されるのに13インチで1920x1080のVAIO Zでは何も起こらないのは、

  • 10.6インチの1920x1080は約207dpiで140%の拡大率
  • 拡大率140%は約207dpiが基準になり、それを超えると適用される
  • VAIO Zでは約170dpi前後ぐらいしかないので100%の域になる

となっていると推測できます画面サイズで決定されるので拡大率にシステムDPI設定は考慮されないことになります

これで画面解像度だけで拡大率が決まるわけではない理由がなんとなくわかりました。

CSSメディアクエリーで使われていた謎のdpi

MSDNガイドラインでは以下のようなメディアクエリーの例が書かれていました(微妙に間違ってるので直してますけど…)。

/* CSS - 拡大率に応じてリモートの画像を読み込む */
@media all and (max-resolution: 134dpi){
    /* 100%の拡大率のとき100%用の画像 */
    .imageBackground {
        background-image: url('http://www.fabrikam.com/foo.png?s=100');
    }
}
@media all and (min-resolution: 135dpi) {
    /* 140%の拡大率のとき140%用の画像 */
    .imageBackground {
        background-image: url('http://www.fabrikam.com/foo.png?s=140');
    }
}
@media all and (min-resolution: 173dpi) {
    /* 180%の拡大率のとき180%用の画像 */
      /* MSDNのサンプルでは174dpiになっているが173dpiでないと動かない */
    .imageBackground {
        background-image: url('http://www.fabrikam.com/foo.png?s=180');
    }
}

134dpi、135dpi、173dpiとありますがこれは100%を96dpiとしたときの値です。つまり

  • 96dpi * 100% = 96dpi
  • 96dpi * 140% = 134.40dpi (135dpi)
  • 96dpi * 180% = 172.8dpi (173dpi)

となりますWindowsは96dpiが標準解像度となっているのでそれが基準になっているのですね。

CSS定義例で言うと

  • 一つ目はmax-resolution:134dpiなので134dpiまでなので135dpi(140%)にならない範囲ぎりぎり→100%
  • 二つ目min-resolution:135dpiなので140%の時の135dpi以上
  • 三つ目はmin-resolution:173dpiなので180%の時の173dpi以上

適用されることになるわけです。

ちなみにこのDPI値はHTML+JavaScriptなMetro style appsではwindow.screen.deviceXDPIとして取得できます。WinRTを経由してもWindows.Graphics.Display.DisplayProperties.LogicalDpiプロパティを使うことで取得できます

が、なぜか180%の時の値が違います。deviceXDPIは173を返しますがLogicalDpiは174を返します。MSDNメディアクエリーの例に174dpiと書いてあったのはWinRTの値が元なのではないかと思います。実際ダウンロードできるサンプルコードの方では173dpiになっています。まあ計算しても違うわけですしWinRTのバグのような気がします。

f:id:mayuki:20120122185111p:image

というわけでスケーリング周りを調べたらなかなかややこしかったですという話でした。

[]Metro style appsの解像度に合わせたスケーリング 17:29 Metro style appsの解像度に合わせたスケーリング - ういはるかぜの化学 を含むブックマーク はてなブックマーク - Metro style appsの解像度に合わせたスケーリング - ういはるかぜの化学

このエントリの内容はWindows Developer Previewの仕様を元にしています。今後Betaリリース時には変更される可能性があることに注意してください。

昨今のスマートフォンタブレットは画面が高精細化してきつつあり、アプリケーション解像度に応じた対応を迫られ、iPhone 4以降ではRetina Display対応といった風にアプリケーション対応しているのを見かけるようになりました。

Windows 8(コードネーム)はこれからリリースされるOSですのでそのあたりも考慮されています。そこでMetro style appsにおいてはアプリケーションはどのようにして対応するのかガイドライン(Content Moved (Windows))があるのでちょっと解説してみます

スケーリングのされ方

Metro style appsでは解像度と画面の物理サイズによって100%,140%,180%と3段階の拡大率を持ち自動的に適用されます。拡大というのはブラウザの拡大みたいなものです。

たとえば10.6インチの1366x768では拡大なしですが、同じ物理画面サイズで1920x1080の場合には140%に拡大されるといった感じです。また、同じ1920x1080でも10.6インチ(スレートサイズ)と23インチ(デスクトップ)では解像度(DPI)が違うので拡大率も違ったりします。この辺は別に書きます(→Metro style appsと解像度と画面サイズと画面解像度 - ういはるかぜの化学 - subtech)

拡大率 画面サイズ
100% 10.6インチ/1366x768, 23インチ/1920x1080
140% 10.6インチ/1920x1080
180% 10.6インチ/2560x1440

アプリケーションですべきこと

自動的に拡大されると書きましたが、ただ拡大するだけではキレイになるとは限らないのでアプリケーション側での対応も必要となりますガイドライン(Content Moved (Windows))によれば以下のことをするようにと書かれています

スケーラブルなベクターグラフィックスを使う

解像度依存ベクター画像を使いましょうという話です。ベクター画像であれば伸び縮みさせてもジャギジャギしたりもやもやしたりしません(Windowsがうまくレンダリングします)。

HTMLアプリケーションを作る場合にはSVGを、C#などで作る場合にはXAMLを使うことで実現します。

アプリケーションパッケージからビットマップ画像を読み込む

ビットマップ画像(JPEG,PNGなど)に特定のルールに従って名前をつけておくと自動的に拡大率の状態に応じて読み込むファイルを変える機能があります

この機能によって拡大率の違いによってサイズの違う画像を読み込むことができます

たとえばHTMLでは以下のようにimg要素でファイル /img/Image.png を参照します。

<img src="/img/Image.png" alt="Image" />

この時、実際に読み込まれるファイルは /img/Image.png だけでなく以下の拡大率によってバリエーションも参照されます

この例のようにファイル名に .scale-{100,140,180} を含めるか、フォルダとして scale-{100,140,180} として分けるか好きな置き方を選ぶことができます。これはHTMLからの参照だけでなくCSSからの参照(たとえばbackground-imageプロパティ)も対象となります

外部の画像を参照する場合メディアクエリーを使う

外部つまりリモートにある画像を参照する場合には拡大率によって自動バリエーション検索する機能は動作しません。

そこでHTML ベースMetro style appsでCSSから参照する場合にはメディアクエリーで解像度に応じて読み込む画像を切り替えます

たとえばMSDNにある例だと以下のようなCSSになっています

/* CSS - 拡大率に応じてリモートの画像を読み込む */
@media all and (max-resolution: 134dpi){
    /* 100%の拡大率のとき100%用の画像 */
    .imageBackground {
        background-image: url('http://www.fabrikam.com/foo.png?s=100');
    }
}
@media all and (min-resolution: 135dpi) {
    /* 140%の拡大率のとき140%用の画像 */
    .imageBackground {
        background-image: url('http://www.fabrikam.com/foo.png?s=140');
    }
}
@media all and (min-resolution: 173dpi) {
    /* 180%の拡大率のとき180%用の画像 */
    /* MSDNのサンプルでは174dpiになっているが173dpiでないと動かない */
    .imageBackground {
        background-image: url('http://www.fabrikam.com/foo.png?s=180');
    }
}

min-resolution/max-resolutionの値が謎のdpiになっている理由は別に書くことにしますが、メディアクエリーのパターンとしては謎のdpiの指定も含めてこのようになります

ユーザー画像ファイルシステムから取り出すときにはサムネイルAPIを使う

ユーザーが持っている画像を動的に読み出して使う場合にはWinRTにあるサムネイルAPIを使いますサムネイルAPIWindows現在の拡大率に最適な画像を返します。

サムネイルAPIというのはWindows.Storage名前空間にあるStorageFileクラスが持つ、GetThumbnailAsyncメソッドのことです。StorageFileクラスフォルダなどから参照したときにとれるものです(よくあるFileクラス的なもの)。

参照:StorageFile class - UWP app developer | Microsoft Docs

画像を実行時に読み込む場合には拡大率をみて読み込む

JavaScriptなどから動的に画像を読み込む場合にはコード現在の拡大率によって画像の参照をコントロールする必要があります

現在の拡大率はWindows.Graphics.Display.DisplayPropertiesクラスResolutionScaleプロパティを参照することで得ることができます

switch (Windows.Graphics.Display.DisplayProperties.resolutionScale) {
    case Windows.Graphics.Display.ResolutionScale.scale100Percent:
        console.log('100%'); break;
    case Windows.Graphics.Display.ResolutionScale.scale140Percent:
        console.log('140%'); break;
    case Windows.Graphics.Display.ResolutionScale.scale180Percent:
        console.log('180%'); break;
}
画像には幅と高さを指定する

拡大率で読み込む画像が変わったりした場合レイアウトが崩れるのを防ぐため、画像には幅と高さを指定するようにします。

グリッドをつかう

要するにメジャーグリッドを20px、マイナーグリッドを5pxずつとして画面を設計することで拡大した場合にも中途半端な値(たとえば23px*1.4倍=32.2pxに対して25px*1.4倍=35px)にならずピクセル丸めとズレのようなものが発生しなくなってきれいです。

アプリケーションでしてはいけないこと

スケーリング考慮する上で逆に避けるべきこともガイドラインには書かれています

小さい画像を拡大時に使うこと

小さい画像というか100%用の標準的なサイズだけしか用意されていない場合、高解像度環境でスケーリングが必要な場合自動的に拡大されてぼやけた見た目になることになります。ということで画像は各拡大率にあわせたものを用意しておきましょう。

iPhoneで言うとRetina非対応アプリiPhone 4で実行したようなことになるのでという話です。

大きい画像を小さくして使うこと

小さい画像を高解像度で使うのと逆に、高解像度用の画像を低い拡大率で使うと縮小するとジャギジャギしてしまうので避けましょう。たとえば180%のパターンだけ用意してそれを140%と100%でも使い回す、といったことです。

ただし例外的に写真画像は縮小しても見た目上問題ないのであればよいでしょう。

5pxの倍数以外でサイズを指定すること

上にも書きましたが5pxの倍数以外でサイズを指定すると拡大したときにズレが生じてしまますので避けましょう。

スケーリングの状態を試す

スケーリングの仕組みが用意されていてもどうやってテストすれば?となるわけですが、シミュレータには解像度画面サイズを想定した設定が用意されていてこれでテストすることができます

f:id:mayuki:20120122171004p:image

どうぞご利用ください。

参考までに設定時の状態を以下にまとめておきます

拡大率 設定
100% 10.6インチ/1366x768, 12インチ/1280x800, 23インチ/1920x1080, 27インチ/2560x1440
140% 10.6インチ/1920x1080
180% 10.6インチ/2560x1440

トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20120122

Sunday, October 02, 2011

[]Metro style appのために拡張されているCSS(ズーム編) 16:09 Metro style appのために拡張されているCSS(ズーム編) - ういはるかぜの化学 を含むブックマーク はてなブックマーク - Metro style appのために拡張されているCSS(ズーム編) - ういはるかぜの化学

今度はズーム系で拡張されているプロパティについてですいまいちズーム周りはまだ挙動が怪しかったり、まともに動かなかったりしますが一応。

そしてまたタッチ前提のものなのでいくつか動画をつけておきます

実際に試したサンプルもおいておきますhttp://mayuki.github.com/Sample/Metro/Html/Zoom.html

あ、あと、例によってWindows Developer Previewという名の通りベータでもないので今後変更される可能性は大きくあるのはご注意ください。

-ms-content-zooming

そのスクロール可能な要素でズームを許可するかどうかのプロパティです。meta要素で指定するviewportのuser-scalable=noと同じような効力がありますが、CSSプロパティなのでbody要素以外にも適用できるのがちょっと違います

要素に対する指定はデフォルトでnone(ズーム非許可)ですが、body要素のみズームが許可されています。これをnoneにすることでページのズームを抑止できます

none
ズームを許可しません
zoom
ズームを許可しま

-ms-content-zoom-boundary

拡大率の最小値、最大値を指定するプロパティです。-ms-content-zoom-boundary-min/-ms-content-boundary-maxの短縮です。値は拡大率なのでパーセント(%)をとります。

-ms-content-zoom-chaining

ズームが境界(つまり拡大率の最大・最小)に達したとき、親要素に処理が続くかどうかを指定するプロパティです。-ms-scroll-chainingのズームです

none
境界に達していてもはねるエフェクトがみえるだけで親要素に続きません
chained
境界に達して、さらに拡大縮小を行うと一番近い親の要素がズームしま

-ms-content-zoom-snap-type

ズームしたとき拡大率がスナップするかどうかを指定するプロパティですスナップする値は-ms-content-zoom-snap-pointsプロパティで指定できます

これらのプロパティを指定すると拡大率の刻みを指定できると思うのですがうまく動いていないのでよくわかりません。

none
スナップの指定は利用しません
mandatory
強制的に一番近いスナップポイントに合わせます
proximity
ズームした後とても近いスナップポイントがあればそこに合わせます

-ms-content-zoom-snap-points

ズームの拡大率のスナップする値を指定するプロパティです。今のところ動かし方が間違っているのか変な動きになってしまます

snapInterval(start<length>, step<length>)
パーセントで刻みを指定しま
snapList(list<lengths>)
パーセントスナップ位置を指定しま

-ms-content-zoom-snap

-ms-zoom-animation

拡大率が変わるときアニメーションをするかどうかを指定します。今のところ指定しても特に何か変わって見えません。

none
ズームアニメーションしません
default
Windowsがもつデフォルトズームアニメーションを発生させます

msContentZoomFactor プロパティ(JavaScript)

現在の拡大率を取得できるプロパティです。値は0.0から1.0(等倍)、2.0(2倍)のようになります

var factor = document.querySelector('#box').msContentZoomFactor;
トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20111002

Thursday, September 29, 2011

[][]HTML+CSS+JavaScriptで動くMetro style appsの話(実行環境周り) HTML+CSS+JavaScriptで動くMetro style appsの話(実行環境周り) - ういはるかぜの化学 を含むブックマーク はてなブックマーク - HTML+CSS+JavaScriptで動くMetro style appsの話(実行環境周り) - ういはるかぜの化学

Windows 8ではHTML+JavaScriptでネイティブ機能を使ったアプリケーションを開発できるようになるわけですが、どんな仕組みになっているのか調べたので簡単に書いてみようと思います。はじめはWinRTとは…WinMDが云々…といった感じで細かく書こうかと思ったのですがややこしいので(まとめてると調べるのが終わらない)おおざっぱに、です

あ、当たり前ですWindows Developer Previewという名の通り今後変更される可能性は多いにあるのでそこはご理解とご協力とお察しください。

Metro style apps

HTML+JavaScriptで作ることのできるアプリケーションMetro style appという新しいMetro UI対応したアプリケーションのみで、従来型のデスクトップアプリケーションを作ることはできません。

ちなみに従来型のデスクトップアプリケーションDesktop appsと呼ばれ、Metro style appのことはまれにImmersiveアプリケーションと呼ばれたりします。"Immersive"は「没入型の」ということですね。Building Windows 8ブログにしばしば出てきますし、API名前などは大体MetroではなくImmersiveと書かれています

そんなMetro style appはHTML+JavaScriptであろうと、C++であろうと、C#であろうと…WinRTと呼ばれるWindowsの新しいAPIセットの上で動きます。というよりMetro style appはWinRTの上以外では動きませんし、逆にWin32 APIも(一部を除いて)利用できません。

実行環境

さて、HTML+JavaScriptでもMetro style appを作れるということですがどんな形で動くのかというとこんな感じになっています

f:id:mayuki:20110929030756p:image:w640

HTML+JavaScriptでアプリケーションが作れて動く、といったところでいきなりWindowsが直接解釈できる実行形式になるわけではありません。

WWAHost.exeというWindowsの実行アプリケーションがあり、その中にInternet ExplorerTrident(レンダリングエンジン)とChakra(JavaScriptエンジン)が組み込まれています。そしてWWAHost.exeHTML+CSS+JavaScriptを読み込んでレンダリングエンジンJavaScriptエンジンを使ってアプリケーションとして動かすという形になっています

mshta.exeとかちょっと懐かしいですね(ほろり。

WWAHost.exeはただInternet Explorerエンジンを組み込むだけでなく、JavaScriptエンジン協調してWinRTのクラスライブラリJavaScript側へ公開してくれます。その結果JavaScriptからWinRTつまりWindowsネイティブ機能などを扱うことができるようになっているという感じです

たとえばwindowオブジェクト(グローバル)にWindowsなどが生えていて、Windows.Storage.KnownFolders.picturesLibrary.createFileAsync(...)といった感じで呼び出すことができるようになっています

アプリケーションの構成的はだいぶおおざっぱですがこんな感じですね。これに加えて周辺技術にWinRTをはじめとしてパッケージングのAppXやWinJSなどがあるのですがまあそれはまた後で書くかもしれません。

WinRTってなに

今までのWindowsではアプリケーションを作るためのAPIとしてWin32 APIというもの提供されていましたが、Metro style appのために新たにWindows Runtime(WinRT)というAPIというかライブラリ提供されています

WinRTはファイルデバイスネットワークなどへのアクセスといった様々なOSネイティブ機能オブジェクト指向的に整理して構築し直したものです。さらにネイティブライブラリでありメタデータを持つ規約のようなものでもあるので、C++C#JavaScriptなどさまざまな言語に公開できるようになっているのが特徴です

Windows Runtimeという名前です.NETCLR(Common Language Runtime)のような仮想マシン実行環境を持っていません。その意味では実装形態は問わずさまざまな言語から使うことを考慮した点など従来のCOMにだいぶ近いものといえそうです

トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20110929