AngularJS TIPS
画像を動的に生成するには?(ng-src/ng-srcset)
<img>タグのng-src属性に指定する画像リソースのURLをAngularJSのスコープオブジェクト経由で完成させることで、動的に画像を表示する方法を説明する。
以下のコードは、画像(<img>
要素のsrc
属性)をスコープオブジェクト経由で動的に生成する例です。ここでは、スコープオブジェクトのisbn
プロパティにリテラルを設定しているだけですが、一般的には外部サービスから取得した情報を基に、画像パスを生成するような状況はよくあることです。
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8" />
<title>AngularJS TIPS</title>
</head>
<body ng-controller="MyController">
<div>
<img src="http://www.wings.msn.to/books/{{isbn}}/{{isbn}}.jpg" />
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script>
angular.module('myApp', [])
.controller('MyController', ['$scope', function($scope) {
$scope.isbn = '978-4-7741-7568-3';
}]);
</script>
</body>
</html>
|
このコードを実行し、ブラウザーの開発者ツールから通信状況を確認してみましょう(図1)。Chromeであれば[Network]タブから確認できます。
すると、最初にAngularJSによって処理される前の「http://www.wings.msn.to/books/{{isbn}}/{{isbn}}.jpg」をリクエストし、その後、あらためて本来の画像「http://www.wings.msn.to/books/978-4-7741-7568-3/978-4-7741-7568-3.jpg」をリクエストしていることが分かります。
これは無駄なリクエストという意味で望ましい状況ではありませんし、そもそも壊れた画像、もしくは意図しない画像が(一瞬かもしれませんが)表示されるのは、ユーザーに対して誤解を招く原因にもなります。
そこでAngularJSで画像パスを動的に作成する場合には、src
属性ではなく、ng-src
属性を利用するようにしてください(リスト2)。ng-src
属性を利用することで、AngularJSが本来のsrc
属性を生成するまでは、画像はリクエストされません。よって、余計なリクエストが発生したり、意図しない画像が表示されたりしてしまうような不具合も改善できます。
<img ng-src="http://www.wings.msn.to/books/{{isbn}}/{{isbn}}.jpg" />
|
[Note]ng-srcset属性
ng-src
属性とよく似た属性として、ng-srcset
属性もあります。ng-srcset
属性は、srcset
属性のAngularJS版です。
srcset
属性はHTML5で追加された属性で、以下のように画像パスを「パス 条件」のカンマ区切りで表します。
<img src="images/sample.png"
srcset="images/sample.png 1x,
images/sample_high.png 2x" />
|
これによって通常のデバイス(PCのディスプレイなど)ではsample.pngを、高解像度のデバイス(iPhoneのRetinaディスプレイなど)ではsample_high.pngを、それぞれ読み込むようになります(x
はデバイスピクセル比を表し、例えば上記の2x
は「2倍」のデバイスピクセル比を持つデバイスという条件を意味します*1)。つまり、srcset
属性を利用することで、解像度に応じて画像を切り替える(=レスポンシブ対応する)ような用途で、特別なコードを記述する必要がなくなるわけです。
- *1 コード例では
src
属性も記載されていますが、これは下位互換性のための指定です。srcset
属性を利用できないブラウザーでは、src
属性が優先して読み込まれます。
補足:ng-src属性ではJavaScript疑似プロトコルは使わない
AngularJSアプリでは、ng-src
/src
属性でJavaScript疑似プロトコル(href="javascript:~"
)は利用できませんので、注意してください。利用した場合にもエラーにはなりませんが、以下のように自動的にサニタイズされてしまいます。
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8" />
<title>AngularJS TIPS</title>
</head>
<body ng-controller="MyController">
<div>
<img ng-src="{{memo}}" />
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script>
angular.module('myApp', [])
.controller('MyController', ['$scope', function($scope) {
$scope.memo = 'JavaScript:alert("注意!")';
}]);
</script>
</body>
</html>
|
ng-src
属性でJavaScript疑似プロトコルを利用したコード(src_js.html)
<img ... src='unsafe:javascript:alert("注意!")'>
|
処理対象:画像 カテゴリ:基本
API:ngSrcset(ng-srcset)|ngSrc(ng-src) カテゴリ:ng(コアモジュール) > directive(ディレクティブ)
※以下では、本稿の前後を合わせて5回分(第57回~第61回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
57. $injectorサービスでサービスの取得/存在確認を行うには?($injector)
AngularJSの管理外でサービスを手動でインスタンス化して利用できる$injectorサービスの応用的な活用方法として、has/get/instantiateメソッドを解説する。
58. モデルをバインドするテンプレートを指定するには?(ng-bind-template)
AngularJSのディレクティブであるng-bind-template属性を使って、{{...}}エクスプレッションを含むテンプレートをビューにバインドする方法を説明する。
59. 【現在、表示中】≫ 画像を動的に生成するには?(ng-src/ng-srcset)
<img>タグのng-src属性に指定する画像リソースのURLをAngularJSのスコープオブジェクト経由で完成させることで、動的に画像を表示する方法を説明する。
60. 不正な入力値もモデルに反映させるには?(ng-model-options)
入力フォームに検証機能を付けた場合、デフォルトでは不正値はモデルに反映されない。この制限を回避して反映させる方法を説明する。
61. 日付/時刻値を入力する際にタイムゾーンを加味するには?(ng-model-options)
ng-model-optionsディレクティブにtimezoneパラメーターを指定することで、タイムゾーンによる時差を加味した日時を<input>要素から取得する方法を説明する。