Y

ChromeApps外部リソース(画像)取得用のAngularJS Directive

はじめに

はじめて作ったChromeAppで外部から取得した画像が表示されない問題がありましたが、なんとか解決したのでメモします。

画像が表示されていなかった

スクリーンショット 2015-12-27 22.40.35.png

コンソールに表示されているエラーは以下です。

Refused to load the image 'https://api.indiesquare.me/wallet/get_asset_image?asset=ZONO' because it violates the following Content Security Policy directive: "img-src 'self' blob: filesystem: data: chrome-extension-resource:".

解決策1 XMLHttpRequestを使ってresponseTypeにblobを設定する

External Content

公式サイトに解決策がいくつか書いてあります。1つ目はXMLHttpRequestを利用してresponseTypeをblobにする方法です。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.is-dev1.agileworks.jp/v2/token/image?name=ZONO', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  var img = document.createElement('img');
  img.setAttribute('width', '100px');
  img.setAttribute('height', '100px');
  img.src = window.URL.createObjectURL(this.response);
  document.body.appendChild(img);
};

xhr.send();

スクリーンショット 2015-12-29 23.15.07.png

無事画像が表示されています。でもちょっとコード量が多い気がします。

解決策2 webviewを使う

<webview src="https://api.is-dev1.agileworks.jp/v2/token/image?name=ZONO" width="100" height="100"></webview>
"permissions": ["webview"],

スクリーンショット 2015-12-29 23.28.09.png

画像は出ていますが画像サイズの調整ができてないようです。

解決策3

webviewの方が実装は簡単ですが、解決策1のXMLHttpRequestが正しい解決方法な気がします。解決策1はコード量が多いのでAngularJSのDirectiveを作りました。

coin.directive('blobimg', function() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      name: '@',
      css: '@'
    },
    template: '<span></span>',
    link: function($scope, iElement) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', 'https://api.is-dev1.agileworks.jp/v2/token/image?name=' + $scope.name, true);
      xhr.responseType = 'blob';
      xhr.onload = function(e) {
        var img = document.createElement('img');
        img.classList.add($scope.css);
        img.src = window.URL.createObjectURL(this.response);
        iElement[0].appendChild(img);
      };
      xhr.send();
    }
  };
});
<blobimg name={{b.asset}} css="token-image-small"></blobimg>{{b.asset}}

結果

スクリーンショット 2016-01-03 15.14.26.png

まとめ

画像が正しく表示されています。directiveを使うことでアプリ内で共通して利用できそうです。ソースはgithubに置いています。

参考

External Content

ChromeAppsでの外部リソースの扱い方

XMLHttpRequest2 に関する新しいヒント

yoyaのメモ

Laravelで画像処理(アップロード/リサイズ/サムネイル)を行なう方法

ng-mtg#6 AngularJS ディレクティブ・パターン

TipMe

TipMe with IndieSquare