HTML5 Canvas ライブラリ (ArtCanvas.js 2.0) のプロトタイプを公開しました

HTML5 CanvasのライブラリであるArtCanvas.js…

これは, 初めて作成したライブラリだったこともあり, 今のレベルから見ると完成度がよろしくなく, いつかきちんと根本的に設計からリファクタリングしようと思っていて…放置状態でした.

しかし, Issueを投稿してくださった方がいて, リファクタリングにとりかかるモチベーションが湧いてきました.

そのプロトタイプデモを公開しました. また, 今回のバージョンからプログラムの設計も, APIの部分も根本から変更しているので,(というよりは, 新規に作成したようなもの), 今後は2.x系としてリリースしていく予定です (もっとも, ソースコードにコメントをきちんと記述して, APIのREADMEを作成を早急にすべきですが…).

バージョン2.xからの大きなロジック・機能の変更は以下の2点に集約されます.

  1. パスの定義を保存するスタック配列をもつことで, 変形しても画質が劣化しないようにする. さらに, パスを描画後のスタイル変更も可能にする
  2. Photoshopのようなレイヤー機能をもつ

ただし, これによってちょっと実装が難しくなったものもあります. 操作履歴の戻る / 進む, いわゆる Undo / Redoですね.

今のところは, History APIを駆使すれば実装できるかな…なんて考えています.

HTMLSelectElementのselectedIndexプロパティ

今日はなぜか使う機会が多かったので…

JavaScriptからセレクトメニューを扱うときはほとんどは選択されている<option>のvalue属性の値を取得することです.

以下のように, <select>タグの要素ノード (HTMLSelectElement) を取得してそのvalueプロパティにアクセスするだけです.

var selectedValue = document.querySelector('select').vallue;

しかしながら,たまに選択されている項目のインデックスやそのテキスト内容を取得したいこともあります. そんなときに便利なのが, selectedIndexです. 以下のような感じのコードです.

var select = document.querySelector('select');

//選択されている項目のインデックスを取得
var selectedIndex = select.selectedIndex;

//選択されている項目のテキストを取得
var selectedText = select.options[selectedIndex].text;

Photoshop スマートオブジェクトの使いどころ

久々にPhotoshopのこと.

Photoshopにはスマートオブジェクトという機能があってこれがなかなか便利なのです. 使いどころとしては,

  1. 同じデザインのイラストが多い
  2. 写真を変形する
  3. フィルタ (スマートフィルター)
  4. Illustratorのデータを読み込み

1. 同じデザインのイラストが多い

この場合は, 作成したボタンなどをスマートオブジェクトに変換して,  レイヤーを複製することで, 例えばデザインの変更があっても,1つを修正すれば, スマートオブジェクトで複製したレイヤーのものがすべて変更される. これが何気に最もうれしい.

Photoshop スマートオブジェクト
Photoshop スマートオブジェクト

2. 写真を変形する  3. フィルタ (スマートフィルター)

写真はラスタデータなので, そのまま変形 (拡大・縮小や回転) を繰り返すと, 画質がどんどん劣化していく. 同じように, フィルターも何度もフィルタをかけ直したりしていると画質が劣化していく. スマートオブジェクトに変換しておくことによってこの心配がいらなくなる.

Photoshop スマートオブジェクト (スマートフィルタ)
Photoshop スマートオブジェクト (スマートフィルタ)

また, スマートフィルター (スマートオブジェクトにしてフィルターをする) にしておけば, フィルターをレイヤースタイルのように操作することが可能になるので, フィルターの調整はもちろん, フィルタの表示 / 非表示の切り替えが可能になります.

Photoshop スマートフィルタ 操作
Photoshop スマートフィルタ 操作

4. Illustratorのデータを読み込み

「スマートオブジェクトとして開く」で変形やフィルターを繰り返し適用しても画質が劣化しません.

Photoshop スマートオブジェクトとして開く
Photoshop スマートオブジェクトとして開く

ちなみに, スマートオブジェクトを適用せずに変形やフィルター処理をすると元に戻せなくなる処理を破壊編集と呼ぶそうです.

スマートオブジェクトを適用すれば, 元の状態に戻すことが可能になります (非破壊編集).

PHP シェルコマンド実行系関数

PHPでシェルコマンドを実行する関数をまとめてみました.

Function Description
shell_exec, 実行演算子 (`…` バッククォートでコマンドを囲んで実行する) 実行されたコマンドからの出力を返す. 出力がなかった場合やエラーの場合はNULLを返す.
exec コマンド結果の最後の行を返す. ただし, 第2引数に配列を指定することで出力の各行を取得することが可能. 第3引数を指定している場合, シェルの終了ステータス (int) が渡される.
system コマンド出力の最後の行を返す. 第2引数を指定している場合, シェルの終了ステータス (int) が渡される.
passthru 全てのデータをコマンドから直接返す. 出力がバイナリデータの場合に利用する. 第2引数を指定している場合, シェルの終了ステータス (int) が渡される.
popen 指定したコマンドのフォークによってできたプロセスへのパイプをオープンする.
proc_open コマンドを実行して入出力用にファイルポインタを開く.

 

ちなみに, いずれの関数も第1引数は実行するシェルコマンドの文字列です.

SplFileObjectとLimitIterator

PHPでログファイルなど巨大なファイルサイズを読み込む場合, file関数やfile_get_contentsなどでぜんぶ読み込んでしまうと, memory_limitにひっかかってエラーが発生してしまうことがあります.

解決策としては, ファイルの必要な部分だけ読み込むことで, そのためには, fopen / fgets or fread / fclose などC言語由来の低レイヤーなAPIを使うというのが1つの方法ですが,  高レイヤーなAPIを利用して解決することもできます.

それが, SplFileObjectクラスとLimitIteratorクラスを利用する方法です. 使い方はこんな感じです

<?php

    $splFileObject = new SplFileObject('ファイルのパス');

    //どっから読み込むか
    $offset = 1000;   //1000行目から

    //どれだけ読み込むか
    $count = 1000;  //1000行分

    $contents = [];

    //1000行目から1999行目まで読み込む
    foreach (new LimitIterator($splFileObject, $offset, $count) as $content) {
        //指定した範囲だけ行ごとに配列の要素として格納する
        //行番号がわかるように$offsetから格納
        $contents[$offset++] = $content;
    }

    var_dump($contents);

ちなみに, 指定した行数を読み込む前に, ファイルの終端に達してもエラーは発生しないので安心してください.

ApplicationCache API

HTML5 ApplicationCache APIを利用する場合の典型的なコード例

* ApplicationCacheを利用するためにはマニフェストファイルや.htaccessの設定なども必要です. この記事ではApplicationCache API, つまり, JavaScriptのコード部分のみを紹介しています.

document.addEventListener('DOMContentLoaded', function() {
    if (window.applicationCache) {
         //ApplicationCache APIが実装されていれば,
         //ページ読み込み時にキャッシュマニフェストを確認する処理が自動で実行される

         //キャッシュのダウンロードが完了して, 再度updateメソッドの呼び出しが可能になるタイミングで発生するイベント.
         //また, このイベント発生以降にswapCacheメソッドを呼び出すことで, 最新のキャッシュに更新することが可能となる.
         applicationCache.onupdateready = function() {
              //UPDATEREADY (4) -> 最新のキャッシュファイルを利用する準備が完了
             console.log(applicationCache.status === applicationCache.UPDATEREADY); // -> trueのはず

             //バックグラウンドでキャッシュを最新のものに更新
             applicationCache.swapCache();

             if (window.confirm('確認メッセージ')) {
                 //更新されたキャッシュの内容を反映するためにリロード
                 location.reload(false); //キャッシュを利用してリロード
             }
         };
     }
}

また, あまりないかもしれませんが, ページ読み込み時以外でもキャッシュマニフェストの確認処理を実行したい場合は, updateメソッドを明示的に呼び出す必要があります.

//1時間ごとにキャッシュマニフェストの確認処理を実行
window.setInterval(function() {
    if (window.applicationCache) {
        applicationCache.update();
    }
}, (60 * 60 * 1000));

Googleカスタム検索のフォームをデザインする

Googleのカスタム検索を利用する場合, 一般的には指定された<script>タグと<gcse:search>タグを記述する.

<script>
 (function() {
 var cx = '検索エンジン ID ';
 var gcse = document.createElement('script');
 gcse.type = 'text/javascript';
 gcse.async = true;
 gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
 '//www.google.com/cse/cse.js?cx=' + cx;
 var s = document.getElementsByTagName('script')[0];
 s.parentNode.insertBefore(gcse, s);
 })();
</script>
<gcse:search></gcse:search>

これで, 検索機能はもちろんUI・デザインもそれなりのものなので, 特にカスタマイズしないという場合はこれでOKです.

しかしながら, デザインを大きく変更したい場合, この方法だとJavaScriptによってたくさんのタグやid / class属性が付加されるのでCSSで制御しづらい…

その場合には, こちらのページにあるHTMLフォームを利用します.

<form id="cse-search-box" action="http://google.com/cse">
  <input type="hidden" name="cx" value="YOUR SEARCH ENGINE ID goes here" />
  <input type="hidden" name="ie" value="UTF-8" />
  <input type="text" name="q" size="31" />
  <input type="submit" name="sa" value="Search" />
</form>
<img src="http://www.google.com/cse/images/google_custom_search_smwide.gif">

“YOUR SEARCH ENGINE ID goes here” の値には, 検索エンジン IDを入力します.

注意点としては, Googleのロゴ画像は必ず表示する必要があるので,

<img src="http://www.google.com/cse/images/google_custom_search_smwide.gif">

は必ず必要です. もしくは, <img>タグの代わりに, <script>タグで読み込んでもOKです.

<script type="text/javascript" src="//www.google.com/cse/brand?form=cse-search-box&lang=en"></script>

<script>タグを利用して画像を読み込んだ場合, 検索キーワードを入力するテキストボックスのプレースホルダーとして利用できます.