アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

SVGを画像化する

はじめに

昨今のクライアントサイドでは、動的な画像のレンダリング、アニメーション、拡張・縮小を求められることが多々あります。そのような際にSVGは利用しやすい形式です。一方で、画像として内容を保存したくなることもあります。そのような場合に使える、SVG画像をPNG画像に変換する方法を簡単に述べます。

SVGとは

SVGファイル(スケーラブル・ベクター・グラフィックス、Scalable Vector Graphics)は画像形式の1つです。XMLをベースにした二次元ベクターデータで画像を描きます。ベクターデータとは「画像を、点の座標とそれを結ぶ線(ベクター、ベクトル)などの数値データをもとにして演算によって再現する方式」です。その大きな特徴は「拡大・縮小しても画質が損なわれない」ことです。

Illastratorなどでも作れますが、JavaScriptで簡単に作れます。実際にSVGを業務などでがっつりと利用するのであれば、d3jsがお勧めです。かなり扱いやすくできています。

実際の変換処理

やり方は非常に簡単で、以下の3ステップで可能です。

  1. SVG画像を作成する
  2. XMLSerializerを使ってSVG画像のデータを取り出す
  3. Canvasを使ってPNG形式に変換する

XMLSerializerは最新のブラウザであればほぼ使用可能です(詳細はこちら)。

コード

実際のコードは次のようになります。svg2jpeg関数にSVG要素(DOM)を渡すことで、PNG画像に変換します。変換処理では、SVG要素と同じサイズのCanvasを使い、Imageオブジェクトを利用してSVGデータをCanvasに貼り付けます。その後、CanvasのtoDataURL()メソッドを使用してPNG画像データを取り出します。

function svg2jpeg(svgElement, sucessCallback, errorCallback) {
  var canvas = document.createElement('canvas');
  canvas.width = svgElement.width.baseVal.value;
  canvas.height = svgElement.height.baseVal.value;
  var ctx = canvas.getContext('2d');
  var image = new Image;
  
  image.onload = () => {
    // SVGデータをPNG形式に変換する
    ctx.drawImage(image, 0, 0, image.width, image.height);
    sucessCallback(canvas.toDataURL());
  };

  image.onerror = (e) => {
    errorCallback(e);
  };

  // SVGデータを取り出す
  var svgData = new XMLSerializer().serializeToString(this.damageMap.nativeElement);
  image.src = 'data:image/svg+xml;charset=utf-8;base64,' + btoa(svgData);
}

// 使い方
svg2jpeg(document.getElmentById('SVG要素のID'), function(data) {
    // data: JPEGのbase64形式データ(文字列)
}, function(error) {
    // error: 何らかのエラーオブジェクト  
})

HTMLサンプル

実際に試すには、以下のコードをHTMLファイルに保存してブラウザで開いて見てください。「変換する」ボタンを押すことで、SVGPNG画像に変換し、表示します。ChromeFirefoxSafariでは動作確認済みです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Sample</title>
  <style>
    .image {
      margin: 0 auto;
      display: flex;
      align-items: center;
      width: 900px;
    }
    .image__svg {
      width: 400px;
    }
    .image__sep {
      flex-grow: 1;
      text-align: center;
    }
    .image__converted {
      width: 400px;
      height: 400px;
      border: 1px solid rgba(0, 0, 0, 0.5);
    }
  </style>
</head>
<body>
<div class="image">
  <div class="image__svg">
    <svg
        id="svg"
        xmlns="http://www.w3.org/2000/svg"
        width="400"
        height="400"
        viewBox="0 0 400 400"
        preserveAspectRatio="xMidYMid meet"
        style="background-color: #eee;">
      <circle cx="50" cy="50" r="50" fill="rgba(255,0,0,0.5)" />
      <circle cx="200" cy="200" r="50" fill="rgba(0,255,0,0.5)" />
      <circle cx="350" cy="350" r="50" fill="rgba(0,0,255,0.5)" />
      <circle cx="350" cy="50" r="50" fill="rgba(255,255,0,0.5)" />
      <circle cx="50" cy="350" r="50" fill="rgba(0,255,255,0.5)" />
    </svg>
  </div>
  <div class="image__sep">
    <div>==&gt;&gt;</div>
    <div><button id="convert-button">変換する</button></div>
  </div>
  <div class="image__converted">
    <img src="" id="converted-image">
  </div>
</div>
<script>
  (function() {
    document.addEventListener('DOMContentLoaded', function() {
      document.getElementById('convert-button').addEventListener('click', function() {
        svg2imageData(document.getElementById('svg'), function(data) {
          console.log(data);
          document.getElementById('converted-image').src = data;
        }, function(error) {
          console.log(error);
          alert('failed to convert');
        });
      });
    });

    function svg2imageData(svgElement, successCallback, errorCallback) {
      var canvas = document.createElement('canvas');
      canvas.width = svgElement.width.baseVal.value;
      canvas.height = svgElement.height.baseVal.value;
      var ctx = canvas.getContext('2d');
      var image = new Image();

      image.onload = () => {
        ctx.drawImage(image, 0, 0, image.width, image.height);
        successCallback(canvas.toDataURL());
      };

      image.onerror = (e) => {
        errorCallback(e);
      };

      var svgData = new XMLSerializer().serializeToString(svgElement);
      image.src = 'data:image/svg+xml;charset=utf-8;base64,' + btoa(svgData);
    }
  }());
</script>
</body>
</html>

実際にブラウザで表示すると次のように表示されます。

f:id:asialkazushi:20180914141741p:plain
初期画面

変換ボタンをクリックすると、右側の領域にPNG画像が表示されます。開発ツールなどで確認してください。

f:id:asialkazushi:20180914141746p:plain
変換後

おわりに

画像や何らかのグラフ表示などの課題に直面した際には、SVGCanvasを使えればほぼ解決可能です。画像化の方法を組み合わせることで、サーバへ保存できるようにもなり、なお便利になります。

Monacaアプリの広告SDKを入れてみよう(AdMob編)

アプリから収益をあげる手段として広告は今なお有力な選択肢です。しかし昨今のAppleによるリジェクト騒動があったりと、広告SDKを巡る動きはとても早く、追従していくのが大変ではないかと思います。



そこで公式なサポートは難しいのですが、執筆時点での情報としてMonacaアプリへの広告SDKの組み込みについて紹介したいと思います。まずは最も有名と思われる広告プラットフォーム、AdMobの使い方です。



利用はプラグイン利用



AdMobはAdMob Plugin Proというサードパーティープラグインを使うのが良いようです。そのためMonacaではゴールドプラン以上の利用が必須になります。



設定メニューからCordovaプラグインの管理を選択して、cordova-admob-proをインストールします。





AdMobでAd unit IDを取得



Google AdMobへ行き、iOS/AndroidそれぞれAd unit IDを取得します。載せ方はBanner、Interstitialが選択できます。Interstitialのがよりリッチで高額とのことですが、あまり多用するとアプリ利用者に嫌われる傾向があります。そのためアプリの画面切り替え、読み込み時の画面などで使われます。





JavaScriptコードの修正



使い方は次のようになります。各プラットフォームごとにAd unit IDを切り替えて設定する必要があります。






var onDeviceReady = function() {
    // select the right Ad Id according to platform
    var admobid = {};
    if( /(android)/i.test(navigator.userAgent) ) { // for android  & amazon-fireos
        admobid = {
            banner: 'ca-app-pub-xxxxxxxxxxxx/yyyyyyyyy', // or DFP format "/6253334/dfp_example_ad"
            interstitial: 'ca-app-pub-xxx/yyy'
        };
    } else if(/(ipod|iphone|ipad)/i.test(navigator.userAgent)) { // for ios
        admobid = {
            banner: 'ca-app-pub-xxxxxxxxxxxx/yyyyyyyyy', // or DFP format "/6253334/dfp_example_ad"
            interstitial: 'ca-app-pub-xxx/kkk'
        };
    } else { // for windows phone
        admobid = {
            banner: 'ca-app-pub-xxx/zzz', // or DFP format "/6253334/dfp_example_ad"
            interstitial: 'ca-app-pub-xxx/kkk'
        };
    }
    if(AdMob) AdMob.createBanner( {
        adId: admobid.banner, 
        position: AdMob.AD_POSITION.TOP_CENTER, 
        autoShow: true } );
};
document.addEventListener("deviceready", onDeviceReady, false);


後はバナーであれば AdMob.createBanner を実行します。interstitialの場合は次のようになります。





if(AdMob) AdMob.prepareInterstitial( {adId:admobid.interstitial, autoShow:false} );


アプリをビルドする





独自のプラグインを使っていますので、アプリストア配布のMonacaデバッガーではデバッグできません。デバッグビルドなど、ビルドした上でアプリを実機にインストールして確認してください。






プラグインサードパーティー製という点が若干不安の残る点ではありますが、開発は活発に行われているようなので今後のバージョンアップにも追従してくれると思われます。



また、AdMobはGoogleが運営しているとあって規約上の問題になるようなことはしないと思われますので、他のプラットフォームに比べると安心して利用できるのではないでしょうか。

企業向けアプリ開発に最適なチャートライブラリWijmoを試す

ハイブリッドアプリは幅広く使われていますが、特に需要が高いのが企業向けアプリです。マルチプラットフォームでの動作やWeb技術を使った素早い開発スタイルが好まれています。



そんな業務システムを作る上で欠かせないのがグラフやチャートではないでしょうか。膨大なデータも可視化することでトレンドを見いだしたり、経営判断をする上で大事な指標になることでしょう。



ということで今回は有償のチャート、UIライブラリであるWijmoをMonacaアプリ上で試したいと思います。



グラフの種類



まずは基本となる棒グラフです。グラフはSVGで描かれているので描画が高速です。





タップイベントによるドリルダウンに対応しており、インタラクティブなグラフが描けます。さらに描画はレスポンシブで縦向き、横向き両方に対応しています。





グラフをリアルタイムに切り替えることもできます。例えば円グラフに切り替えた場合。





複数の項目を並べることもできます。





別なグラフと組み合わせる表示もサポートしています。





グラフはSVGで表示されていますのでスタイルシートを使ってスタイルの変更ができます。





リアルタイムにデータを追加していくグラフも利用できます。





実際にデータが追加されている時にはこのように表示されます(画像をクリックすると再生されます)。監視系やストリーム系データを扱うときに重宝しそうです。





それ以外にも曲線グラフや、





エリアグラフもあります。





タブレットサイズにも対応



レスポンシブに対応しているということもあり、タブレットでの横型サイズでも問題ありません。SVGなのでサイズが大きくなってもグラフはぼやけることなく綺麗です。むしろ細部まで確認したい時にはタブレットサイズのが良さそうです。





曲線のエリアグラフも綺麗です。





プロットだけの描画。





このように2カラムとしてグラフとその説明を表示するのもタブレット向きです。





軸のラベルやヘッダー、フッターなどのラベルを変更するのも簡単です。





タップした時にイベントを実行できます。








多機能な分、読み込むファイルも多くなりますのでMonaca IDEでアップロードするよりもLocalKitで実行した方が良いかと思います。Wijmo自体はグラフだけでなく、UIライブラリも含んでいるのでExcelのような表計算表示であったり、日付時刻や色選択など多彩な入力コンポーネントが用意されています。Webブラウザで見られるデモが用意されていますので気になる方はチェックしてみてください。



WijmoとMonacaアプリの相性は良いように感じます。業務アプリで求められる機能が数多く提供されていますのでぜひ試してみてください。



HTML5/AngularJS/TypeScript対応JavaScriptライブラリ - Wijmo [ ウィジモ ] | グレープシティ株式会社

MonacaのCordova 5対応に関する注意点

MonacaがCordova 5.2に対応いたします!
Cordova 5.2を利用することで、下記のような多くのメリットを提供いたします。

より安定してよりセキュア、より多くの人々にアプリを届けることができる、最新のCordovaバージョンが使えるようになります。
プラグインの導入及びバージョンの選択が、開発している皆さま自身で選択できるようになります。また、プラグインの選択によって最新のCrosswalkをご利用いただけるようになります。既存のプロジェクトの変換方法や影響のある変更点などについてまとめておりますので、ご確認頂きますようお願いいたします。

プロジェクトのアップデート方法



既存プロジェクトをCordova 5.2にアップデートするには、Cordovaプラグインの管理画面より「5.2.0」を選択してください。



Cordova 5.2への対応方針



  • ・今後、新しく作成されるプロジェクトはCordova 5.2となります。
  • ・既存のプロジェクトについては、手動でCordova 5.2にアップデートしてください。その際に、自動的にバックアップが作成されます。
  • ・Cordova 5.2のプロジェクトをダウングレードすることはできません。


なお、Cordova 5に対応したデバッガーはバージョン5.0となります。デバッガーが搭載するCordovaバージョンとプロジェクトのバージョンが異なる場合、正しくアプリケーションが動作しない可能性があります。既存のプロジェクトをデバッグする場合はカスタムデバッガーをご利用ください。

新しく追加されるCordovaプラグイン



下記の2つのプラグインが、Monacaコアプラグインとして追加されます。

  • ・Whitelistプラグイン: アプリケーションのセキュリティ設定を拡張します。このプラグインを取り除くことはできません。Androidプラットフォームに適用されます。
  • ・Crosswalkプラグイン: AndroidでCrosswalkエンジンを使用するために使用します。


その他のCordovaプラグインの変更点





Androidプラットフォームの変更点



  • ・Cordova 5アプリのデバッグでは、Monacaデバッガーのバージョン5.0を使用してください。
  • Android版のMonacaデバッガーと、ハイパフォーマンス版(Crosswalk)Monacaデバッガーが統合されます。そのため、Crosswalkを使用したアプリについても、通常のMonacaデバッガーをご利用ください。プロジェクト設定により、デバッガーは自動的にWebViewを切り替えます。
  • ・Crosswalkのバージョンが13.42.319.11から14.43.343.25に更新されます。プラグイン設定でCrosswalkのバージョンを個別に指定することもできます(上位プランが必要です)。
  • ・Cordova 5アプリはAndroid 4.0以降をサポートします。
  • ・Cordova Androidプラットフォームが3.6.3から4.1.1にアップデートされ、APIレベルは22となります。
  • ・config.xmlのAppBackgroundColor設定は廃止されます。
  • ・デバッガーで外部アクセスURLの制限は行われません。


また、Whitelistプラグインが有効になった関係で、アプリにて「Content-Security-Policyのmetaタグが無い」旨のエラーが出力される場合があります。 この場合、以下のmetaタグを記述することでエラーを抑制できます。



<meta http-equiv="Content-Security-Policy" content="default-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">


iOSプラットフォームの変更点



  • ・Cordova iOSプラットフォームが3.7.0から3.9.1にアップデートされます。
  • ・Cordova 5アプリはiOS 8.0以降をサポートします。
  • Xcodeバージョンが6.2から6.4にアップデートされます。


WebViewの変更と、Crosswalkバージョンの指定方法



Cordova 5.2より、CrosswalkはCordovaプラグインの一つとして提供されるため、Crosswalkを用いたWebViewの組み込み方法が変更となります。下記の通り、Cordovaプラグインの管理画面より、プロジェクトへの追加をお願いいたします。

1. Crosswalkエンジンをプロジェクトに追加します。



2. 「Crosswalk WebView Engine」の設定を開きます。



3. プラグインとCrosswalkのバージョンを選択できます。



ただし、プラグインバージョンとCrosswalkバージョンの組み合わせによってはビルドに失敗したり、動作が不安定になる可能性があります。また、バージョン指定機能は有料ユーザー限定の機能となりますのでご了承ください。

お問い合わせはこちら



本件についてのお問い合わせにつきましては、こちらのフォームよりお願いいたします。みなさまの開発のお役立てできることを期待しています。

横浜商科大学でMonacaアプリの制作発表会が行われました

こんにちは、生形です。

先日、横浜商科大学Monacaアプリの制作発表会が開催され、私も見学をさせてもらってきました。
横浜商科大学では、商学部の経営情報特論Bという授業の中で、Monacaを使ったアプリ制作演習を実施しています。
この授業では一からアプリの企画をして実際に形にするところまでを目標としているそうです。
夏休み中の二週間の短期集中講義で、最初の一週間で企画・コンセプト設計・ペルソナ分析などを行い、
次の一週間でアプリ開発技術(HTML・CSSJavaScript)を一通り学習するスケジュールです。
二週目のHTML・CSSJavaScriptの授業は私が出張講師としてお伺いしました。
それ以降は、各チームごとに自主的にアプリの制作を進めてもらいました。
商学部なので学生の皆さんは当然プログラミングの教育を受けたこともなく、
すべて初めての経験だったようですが、3か月かけてモックアップまで完成させることができました。

以下は発表会の様子です。













このように、最近は情報系以外の学校でもアプリの企画や研究のためにMonacaを採用して頂くケースが増えています。
制作したアプリを手軽にスマホ上で動作させることができるので、
学生のアイデアをアウトプットするためのツールとして適しているとの評価を頂いているようです。

授業の成果を何らかの形で表したいと考えている教育関係者の方にはMonacaをおすすめします!
ご興味のある方は、以下の連絡先までお気軽にお問い合わせください。

Monacaアカデミックお問い合わせ先
Monacaアカデミック紹介ページ
メール:info@asial.co.jp

日本電子専門学校作品発表会でMonacaアプリの制作発表が行われました

こんにちは、生形です。

先週の10月2日(金)にアップルストア銀座3Fシアターにて、
日本電子専門学校Webデザイン科の学生の皆さんが制作した作品の発表会「AppleStore College Night」が開催されました。
日本電子専門学校では、授業の中に新しい技術を積極的に取り入れていらっしゃっていて、
その一環としてMonacaによるHTML5モバイルアプリ開発も実施されたということで、発表会にお邪魔してきました。
どの作品も完成度が高く、またプレゼンテーションも素晴らしいものでした。
非常に面白い作品がたくさんあり全部紹介したいところですが、今日はMonacaを使った3作品を抜粋して紹介いたします。

「StarBooks」




はてなブックマークやPocketなどの複数のブックマークサービスをまとめるアプリです。
MonacaCSSフレームワークMaterializeを使用して制作されています。
記事を一元管理する機能のほか、記事に手書きメモを書き込むことができたりと、とても多機能なアプリでした。
UIにはマテリアルデザインが適用され、トレンドを押さえていながらもオーソドックスで使い勝手が良さそうな印象を受けました。


「大正あやかし事変」




大正×妖怪×恋愛がテーマのリズムPRGゲームです。
Monacaとenchant.jsを使用して制作されています。
リズムに合わせてタップすると敵にダメージを与えることができ、敵を倒すとストーリーが進行していきます。
スマホゲームユーザーはシンプルな操作感を好むという分析のもと、
シンプルでかつ軽快にプレイできるゲーム設計となっていて、とても面白そうでした。


「CLAM! ~CLASS ALBAM~」




小学校の生徒と先生の交流を促す学級日誌アプリです。
登録した日誌データはニフティクラウドmobile backendに保管されます。
カメラを起動して写真を登録する機能があり、生徒の成長を記録するアルバムとしての役割も果たすのだそうです。
このアプリはユースケース設計がしっかりとしていたので、具体的な利用シーンが目に浮かびました。
学校へのタブレット端末の導入が進んでいることも後押しして、すぐにでも教育現場で採用できそうだと感じました。



現在、Monacaを取り入れた授業を実施して頂ける教育機関様を募集しております。
Monaca副読本のサンプルも提供しておりますので、ご興味のある教職員の方はお気軽にお問い合わせください。


Monacaアカデミックお問い合わせ先
Monacaアカデミック紹介ページ
メール:info@asial.co.jp

Monacaを学校の授業で活用!プログラミング教育事例セミナーアフターレポート

アシアルの岡本です。

9月13日(日)に『HTML5×Monacaプログラミング教育事例セミナー
というイベントを『HTML5プロフェッショナル認定資格』を運営する『LPI-Japan』様と共同で開催致しました。

休日の開催にもかかわらず50名近くの方にお越しいただきました。
ご登壇頂いた先生方とお越しいただいた皆様に、この場を借りてお礼申し上げます。
また、来られなかった方々のために当日の様子と資料をご紹介いたします。

当校におけるHTML5プロフェッショナル認定試験認定者(卒業生・在校生)の 就職状況・採用について


東京電子専門学校 榎本 博文 氏

榎本先生からは、資格対策コースの学校内での実施に関するお話をいただきました。

HTML5の資格は難易度が高いため、継続的な学習を促すために様々な工夫をされたそうです。
自宅でも学習を行うよう授業では毎回小テストを行ったり、採点を学生同士で実施させることで他者に教える機会を用意したそうです。



ビジネス系大学の学生がMonacaを使ってスマホアプリ制作プロジェクトをやりきった


横浜商科大学 遠山 緑生 氏


遠山先生からは、嘉悦大学のゼミと横浜商科大学でのMonacaの活用に関するお話をいただきました。

遠山先生は2013年からMonaca嘉悦大学の経営経済学部のゼミで使い始めたそうです。
それ以前はテキストエディタでWebアプリを開発する課題を出されていたのですが、スマホで動くようにさせるまでにかなりの困難があったそうです。

Monacaを採用することでこれまで実機で動くアプリを作れるチームが全体の5割以下だったものが
9割に改善し、また、ストアへの出展までたどり着けるグループも現れたとのことです。

また2015年は横浜商科大学の「経営情報特論 B」でもMonacaを活用した講義を展開しており、
こちらは9月26日を発表日としてグループごとにアプリの制作を進めているとのことです。

遠山先生の講義はアプリの企画から入るのが特徴で、これは商学部ならではのアプローチだと感じました。



プログラマ指向学生向けのアプリ作成演習について


東京工科大学 藤澤 公也氏


藤澤先生からは、Monacaを使った授業の進め方やチーム作りの方法に加え、発表の流れや機器の活用方法までお話しいただきました。


藤澤先生も2013年から学校の必修科目でMonacaを活用されていて、週1回2コマ(90分x2)を15週、実施されているそうです。授業の最後の方では発表もあるそうですが、二段構えになっていて予選を通過したチームだけが最終発表に臨める仕組みを採用しているとのことです。



HTML5プロフェッショナル認定試験セミナー




アシアルの生形からはHTML5認定試験の範囲や難易度、学習方法などをお話しさせて頂きました。



Monacaワークショップ




私、岡本の方からはMonacaの使い方をワークショップ形式でお伝えいたしました。また、Monacaを採用されている他の学校の先生の声も一部紹介させて頂きました。



参加者特典!


今回のセミナーにご参加いただいた皆様にはアンケートと引き換えに、学校の授業で使えるMonaca副読本の試作品を提供させて頂きました。



こちらの品は開発中のものですが、ご興味のある方には教職員限定で進呈いたしますので、ご一報ください。

Monacaアカデミック問い合わせ先



アシアルの岡本までお気軽にご相談ください。
Monacaアカデミック紹介ページ
メール:info@asial.co.jp
お電話: 03-5875-6862



当日のスケジュールは次のような流れでした


13:00~13:30 開場
13:30~13:50 ごあいさつ:LPI-Japan 成井 弦
13:50~14:10 Monacaのご紹介:アシアル 岡本 雄樹
14:10~14:40 事例:東京電子専門学校 榎本 博文 氏
          「当校におけるHTML5プロフェッショナル認定試験認定者
          (卒業生・在校生)の 就職状況・採用について」
14:40~14:50 休憩
14:50~15:20 事例:横浜商科大学 遠山 緑生 氏
          「ビジネス系大学の学生がMonacaを使って
           スマホアプリ制作プロジェクトをやりきった」
15:20~15:50 事例:東京工科大学 藤澤 公也氏
          「非プログラマ指向学生向けのアプリ作成演習について」
15:50~16:00 休憩・移動
16:00~17:00 選択A:HTML5プロフェッショナル認定試験セミナー
16:00~17:00 選択B:Monaca入門ワークショップ

ご要望にお応えして次回も開催します!



日程は未定ですが、アンケートでは大変な反響を頂いたため改めてMonacaを活用したプログラミング教育の事例セミナーを開催したいと考えております。ご興味のある方や、登壇でご協力いただける方はアシアルの岡本までご連絡いただければ幸いです。

Monacaアカデミック問い合わせ先



Monacaアカデミック紹介ページ
メール:info@asial.co.jp
お電話: 03-5875-6862

Monacaアプリでコピー&ペーストを実装するならクリップボードプラグイン!

こんにちは、渡辺です。

今回は、「VersoSolutions/CordovaClipboard」プラグインの使い方を紹介します。
このプラグインを利用することでアプリ内でのテキストコピー&ペーストができます。

■利用するプラグイン


VersoSolutions/CordovaClipboard
( https://github.com/VersoSolutions/CordovaClipboard )


■サンプルプロジェクトについて



・サンプルプロジェクトの動作確認環境


iPhone6 (iOS 8.1.2)
・GALAXY Note 2 SC-02E (Android4.3 )
デバッグビルドしたアプリで確認済
(注意:ストア版デバッガーでは、今回利用するプラグインが組み込めれていないため、動作しませんので注意してください。)


プラグインのインストール


こちらの過去記事に記述したましたので、参照ください。

■コピーする


まず「deviceready」イベント後に、テキストをコピーする処理を実行します。




var text = "Clipboard Plugin";
document.addEventListener('deviceready', function()
{
    cordova.plugins.clipboard.copy(text);
});



■貼り付ける


上で行ったコピー処理の対象を、貼り付けます。コールバックの引数に
コピーされたテキストが入っています。




cordova.plugins.clipboard.paste(function(text)
{
    alert(text);
});
    


■サンプルプロジェクトのコード


index.html




<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
        var text = "Clipboard Plugin";
        document.addEventListener('deviceready', function()
        {
            cordova.plugins.clipboard.copy(text);
            cordova.plugins.clipboard.paste(function(text)
            {
                alert(text);
            });
        });
    </script>
</head>

<body>
    This is a template for Monaca app.</body>

</html>



■参考情報


・VersoSolutions/CordovaClipboard
https://github.com/VersoSolutions/CordovaClipboard


■お知らせ


Monacaチームでは現在、新規開発メンバーを大募集中です。詳しくはこちらを参照ください!
https://ja.monaca.io/careers.html

Monacaアプリでフラッシュライトを利用する方法

こんにちは、渡辺です。

今回は、「EddyVerbruggen/Flashlight-PhoneGap-Plugin」プラグインを利用して
フラッシュライトを操作するサンプルプロジェクトを作ります。

■利用するプラグイン


EddyVerbruggen/Flashlight-PhoneGap-Plugin
( https://github.com/EddyVerbruggen/Flashlight-PhoneGap-Plugin )


■サンプルプロジェクトについて


サンプルプロジェクトでは、フラッシュライトを1秒間隔で点滅させるアプリを作成します。

・サンプルプロジェクトの動作確認環境


iPhone6 (iOS 8.1.2)
・GALAXY Note 2 SC-02E (Android4.3 )
デバッグビルドしたアプリで確認済
(注意:ストア版デバッガーでは、今回利用するプラグインが組み込めれていないため、動作しませんので注意してください。)

プラグインのインストール


こちらの過去記事に記述したましたので、参照ください。

■フラッシュライトが利用できるか確認する


まず「deviceready」イベントが発生したあとに、フラッシュライトが利用できるか確認します。
変数isAvailableで判定しています。



window.plugins.flashlight.available(function(isAvailable) {
  if (isAvailable) {
  
    /**
     * フラッシュライトが利用できる場合の処理を記述 
     */

  } else {
    alert("Flashlight not available on this device");
  }
});



■フラッシュライトのOn / Off


フラッシュライトをOn/Offする方法です。
下の方法以外にも「window.plugins.flashlight.toggle()」を利用すれば、
現状OnのときはフラッシュライトをOffに、Offの状態のときは、Onに切り替えることができます。



    // switch on
    window.plugins.flashlight.switchOn(); 

    // switch off
      window.plugins.flashlight.switchOff();


■フラッシュライトを点滅させる


setInterval()を利用して、フラッシュライトを点滅させる方法です。
点滅させる間隔は、ここでは1秒としていますが、任意に調整してください。



    interval = setInterval(function () {
        window.plugins.flashlight.toggle();
      }, 1000);


■フラッシュライトを終了させる(Android)


Androidの場合は、アプリ終了時にフラッシュライトを適切に終了させる必要があります。
終了を行わないと、アプリがバックグラウンドに入っても、フラッシュライトが光り続けてしまします。ここでは、バックグラウンドに入る際の処理と、「戻る」ボタンの挙動を上書きするようにしています。




    document.addEventListener("backbutton", function () {
      // pass exitApp as callbacks to the switchOff method
      window.plugins.flashlight.switchOff(exitApp, exitApp);
    }, false);

    document.addEventListener("pause", function () {
       window.plugins.flashlight.switchOff(exitApp, exitApp);
    }, false);

    function exitApp() {
            clearInterval(interval);
            navigator.app.exitApp();
          }



■サンプルプロジェクトのコード


index.html




<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
        document.addEventListener('deviceready', function () {
          var interval = null;
          window.plugins.flashlight.available(function (isAvailable) {
            if (isAvailable) {
              interval = setInterval(function () {
                window.plugins.flashlight.toggle();
              }, 1000);
            } else {
              alert("Flashlight not available on this device");
            }
          });
        
          document.addEventListener("backbutton", function () {
            window.plugins.flashlight.switchOff(exitApp, exitApp);
          }, false);
        
          document.addEventListener("pause", function () {
            window.plugins.flashlight.switchOff(exitApp, exitApp);
         }, false);

          function exitApp() {
            clearInterval(interval);
            navigator.app.exitApp();
          }
        });
    </script>
</head>

<body>
    This is a template for Monaca app.
</body>

</html>




■参考情報


・EddyVerbruggen/Flashlight-PhoneGap-Plugin
https://github.com/EddyVerbruggen/Flashlight-PhoneGap-Plugin


■お知らせ


Monacaチームでは現在、新規開発メンバーを大募集中です。詳しくはこちらを参照ください!
https://ja.monaca.io/careers.html

NVD3を使って、AngularJSで作ったハイブリッドアプリのグラフを統合しよう

ハイブリッドアプリにグラフを表示する方法はいくつもあります。ハイブリッドアプリは基本的にHTML,Javascript,CSSで動くウェブアプリケーションなので、JavaScriptのグラフライブラリならなんでも使うことができますし、バックエンドでグラフを作成して静止画として表示することもできます。

この記事では、D3というデータビジュアリゼーションライブラリに基づき、再利用することのできるNVD3に注目します。それでは、このNVD3がJavaScriptのみでどうやってグラフを作成し、AngularJSのディレクティブにどのようにしてラッピングされているのかを見>ていきましょう。

また、人気のJavaScriptライブラリは他には以下のようなものあります。


  • D3.js - D3はData-Driven Documentsの意味です。SVGを用いた、大変強力なデータビジュアリゼーションライブラリです。低級ライブラリなので簡単なグラフを作成するのにも大変複雑な作業を要しますが、完成したものは驚くべき出来栄えとなります。

  • Chart.js - D3.jsよりも簡単に使えますが、それでもまだかなりカスタマイズ性が高いものです。SVGではなくcanvasを用いており、そのため古いブラウザやウェブビューをサポートする必要がある際には非常に良い選択肢と言えるでしょう。

  • n3-charts - AngularJSとD3.jsの上位に作られており、このライブラリを使えばAngularJSでグラフを表示することはとても簡単になります。



私たちは近頃、OnsenUIではグラフ作成ライブラリをサポートすべきか、もしそうならどのライブラリを選ぶべきかということを議論してきました。そこで、簡単さとD3.jsの強力なデータ可視化が組み合わさったNVD3が候補の一つに挙がりました。またこの記事で紹介するように、NVD3はAngularJSアプリケーションに簡単に組み込むことができます。

NVD3の長所


  • レスポンシブ - NVD3を使って作られたグラフは、スクリーンのサイズ・向きごとにそれぞれに適した形で描画されます。

  • ダイナミック - データに変更があったときには簡単にグラフをリフレッシュできます。



下のイメージは、NVD3とOnsenUIを用いて作った、世界各国の人口を表示する簡単なアプリです。



人口データはWorld Population APIから取得しています。

NVD3でグラフを作成する



まず初めにHTMLファイルを新規作成し、以下のリソースをロードします。


  • d3.js

  • nv.d3.js

  • nv.d3.css



これらは全てCDNで利用可能なので、以下のようにすることができます



<html>
  <head>
    <title>My chart</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.css">
    <script src="chart.js"></script>
  </head>
  <body>
    <!-- D3 will use this "svg" tag to render the chart! -->
    <svg></svg>
  </body>
</html>


それでは最初のグラフを作成して、スクリーンに描画してみましょう。chart.jsと名前を付けたファイルを作成し、以下のコードを追加してみましょう。



var data = []; // We'll leave this empty for now.

nv.addGraph(function() {
  // Creates a new Line chart.
  var chart = nv.models.lineChart()
    .showLegend(false)
    .showYAxis(true)
    .showXAxis(true);

  // Tells NVD3 to display values with two decimal places.
  chart.xAxis
    .axisLabel('x')
    .tickFormat(d3.format('.2f'));

  chart.yAxis
    .axisLabel('y')
    .tickFormat(d3.format('.2f'));

  // Select the "svg" tag and render the chart.
  d3.select('svg')
    .datum(data)
    .call(chart);

  // This will render the chart every time the
  // window is resized, so it will always fit the
  // screen.
  nv.utils.windowResize(function() {
    chart.update()
  });

  return chart;
});


ブラウザでこのコードを実行してみると、まだデータを追加していないので"No data Available"と表示されると思います。データは以下のようなフォーマットで定義されます。



var data = [{
  key: 'Label',
  values: [{x: 0, y: 0}, {x: 1, y: 1}, ...]
}];


簡単なデータを作成し、グラフに渡してみましょう。



var data = []

// Generate y = ln(x) for x = [0..e].
for (var i = 1; i <= Math.E; i += 0.01) {
  data.push({x: i, y: Math.log(i)});
}


保存して再読み込みすると、ブラウザはこのようなグラフを表示するはずです。

See the Pen JdeOLd by Andreas Argelius (@argelius) on CodePen.




NVD3グラフをAngularJSのディレクティブでラッピングする



AngularJSの強みはデータバインディングです。AngularJSのディレクティブを作成し、そこでchartのデータをHTMLの属性にバインドしてみましょう。この章では<line-chart>コンポーネントを作成します。このコンポーネントは以下のようにして使用できます。



<line-chart data="data" height="200px" width="120px"></line-chart>


ユーザーがデータを変更できるように、<input>タグも追加します。最終的にはこのようになるはずです。



<div ng-app="app" ng-controller="MyController as main">
  <line-chart height="250px" data="main.data"></line-chart>

  <h3>Change the values: </h3>

  <p ng-repeat="datum in main.data[0].values">
    <input type="number" ng-model="datum.y">
  </p>
</div>


とても短いコードですが、これで全て完了です!アプリを読み込んで、data配列をダミーデータで初期化しましょう。



angular.module('app', [])
  .controller('MyController', ['$scope', function($scope) {
    this.data = [{
      key: 'Data',
      values: [{
        x: 0,
        y: 0
      }, {
        x: 1,
        y: 1
      }, {
        x: 2,
        y: 4
      }, {
        x: 3,
        y: 9
      }, {
        x: 4,
        y: 16
      }, {
        x: 5,
        y: 25
      }]
    }];
  }]);


ここではまだディレクティブのコードを書いていないので、input要素だけが動いています。ディレクティブを作成するのは真正直な作業なので以前書いたJavaScriptのみのコードから拝借します。ここで、2つのサービス(d3とnv)を使いました。これは、それぞれのオブジェクトを返すだけのもの
です。



angular.module('app')
  .directive('lineChart', ['d3', 'nv', function(d3, nv) {
    return {
      restrict: 'E',
      scope: {
        // Bind the data to the directive scope.
        data: '=',
        // Allow the user to change the dimensions of the chart.
        height: '@',
        width: '@'
      },
      // The svg element is needed by D3.
      template: '<svg ng-attr-height="{{ height }}" ng-attr-width="{{ width }}"></svg>',
      link: function(scope, element) {
        var svg = element.find('svg'),
          chart;

        // This function is called when the data is changed.
        var update = function() {
          d3.select(svg[0])
            .datum(scope.data)
            .call(chart);
        };

        // Render the chart every time the data changes.
        // The data is serialized in order to easily check for changes.
        scope.$watch(function() { return angular.toJson(scope.data); }, function() {
          // The chart may not have been initialized at this point so we need
          // to account for that.
          if (chart) {
            update();
          }
        });

        // The chart can not be rendered at once, since the chart
        // creation is asynchronous.
        scope.$on('chartinit', update);

        nv.addGraph(function() {
          // This code is the same as the example before.
          chart = nv.models.lineChart()
            .showLegend(false)
            .showYAxis(true)
            .showXAxis(true);

          chart.xAxis
            .axisLabel('x')
            .tickFormat(d3.format('.2f'));

          chart.yAxis
            .axisLabel('y')
            .tickFormat(d3.format('.2f'));

          nv.utils.windowResize(function() {
            chart.update()
          });

          // Emit an event so we can know that the
          // chart has been initialized.
          scope.$emit('chartinit');

          return chart;
        });
      }
    }
  }]);


$watchコールバック関数ではupdate()関数を呼び出す前にグラフが初期化されていることをチェックしています。nv.addGraph()関数は非同期的に実行されるので、コールバック関数はグラフが生成される前に発火する可能性があります。その際は以下のエラーが返却されます。



TypeError: Cannot read property 'apply' of undefined


下のグラフを使って遊んでみましょう。データバインディングのおかげで、データに変更があるたびにグラフは再び描画されます。

See the Pen NVD3 Line Chart Sample by Andreas Argelius (@argelius) on CodePen.




これに似たディレクティブがこの記事の冒頭の例でも使われています。コードは私のGitHubページにあります。

まとめ


この記事について何か質問があれば、下でコメントしてください。どんなフィードバッ>クでも歓迎します!