タグ別アーカイブ: HTML5 API

WebAudio.tokyo #4

2017 年 3 月 28 日 (火) に WebAudio.tokyo #4 に参加してきました.

私は, 5 分の LT 枠で, 自作の Web Audio API ライブラリの概要を話してきました.

発表では, Chrome の Web MIDI API の実装をされた @toyoshim さんから, レコーディング機能の実装について質問されたり, 発表後には, Web Music Hackathonのボスである @g200kg さんとお話をできたりと非常に楽しい勉強会でした.

また, 自分が制作した 「Web Audio API の解説サイトを参考にさせてもらってます」
という方もいらっしゃってとてもうれしかったです.

Google の @agektmr さんに, X Sound をツイートしてもらえたのも感激でした.

最後に, 関連リンクを紹介しておきます.

XSound.js 1.13.0 リリース

XSound.js 1.13.0 をリリースしました.
今回のリリースで, Microsoft Edge にもおおよその機能は対応しました.

といっても, 大した対応はしていません.

Edge の ScriptProcessorNode のバグに対応しただけです.

ScriptProcessorNode インスタンスを生成するには, AudioContext インスタンスの createScriptProcessor を利用します. 例えば, 以下のような感じ

const context = new AudioContext();
const processor = context.createScriptProcessor(2048, 2, 2);

第1引数は, 必須で onaudioprocess イベントのバッファサイズを指定します.
第2引数, 第3引数はオプションで, それぞれ, 入力チャンネル数 / 出力チャンネル数を指定します.
省略した場合は, どちらもデフォルト値 2 が適用されると仕様では定義されています.

実は, Edge はこの仕様に反していて, 明示的に入力チャンネル数 / 出力チャンネル数を指定しないとダメなのです.

ここを省略していたので, 1.13.0 より前のバージョンにおいて Edge でエラーが出ていました.

これを, PR 送って修正したいのですが, Edge の Web Audio API のソースが公開されていないようなのです…
(誰かご存知でしたら教えていただけると助かります〜)

ちなみに, WebKit と Gecko の Web Audio API のソースは公開されているのですが…

Microsoft Edge でも X Sound を楽しんでください~

iframeを編集可能な領域にする

HTML

<iframe width="640" height="480"></iframe>

srcは指定する必要ありません. widthとheightを適当に指定しておきます.

JavaScript

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

iframe.contentDocument.body.contentEditable = true;
iframe.contentDocument.designMode              = 'on';

以上で, iframe上のHTMLが編集可能になります.

あとは,

iframe.contentDocument.execCommand

を利用して, 文字を装飾したり, リンクを挿入したりしてください

JavaScript Fullscreen API

特定の要素をフルスクリーンにする場合

if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
    element.msRequestFullscreen();  // IE 11 (IE 11未満は未対応)
} else if (element.requestFullscreen) {
    element.requestFullscreen();
} else {
    throw new Error('Cannot change to full screen.');
}

フルスクリーンを解除する場合

if (document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen();
} else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
    document.msExitFullscreen();
} else if (document.cancelFullScreen) {
    document.cancelFullScreen();
} else if (document.exitFullscreen) {
    document.exitFullscreen();
} else {
    throw new Error('Cannot exit from full screen.');
}

フルスクーン状態の要素の取得

var fullscreenElement = null;

if (document.webkitFullscreenElement) {
    fullscreenElement = document.webkitFullscreenElement;
} else if (document.mozFullScreenElement) {
    fullscreenElement = document.mozFullScreenElement;
} else if (document.msFullscreenElement) {
    fullscreenElement = document.msFullscreenElement;
} else if (document.fullscreenElement) {
    fullscreenElement = document.fullscreenElement;
}

フルスクリーンイベントの検知

document.addEventListener('webkitfullscreenchange', function(event) {}, false);
document.addEventListener('mozfullscreenchange', function(event) {}, false);
document.addEventListener('MSFullscreenChange', function(event) {}, false);
document.addEventListener('fullscreenchange', function(event) {}, false);

また, フルスクリーン状態におけるスタイルを設定することも可能です.

#element:-webkit-full-screen {
    /* ... */
}

#element:-moz-full-screen {
    /* ... */
}

#element:-ms-fullscreen {
    /* ... */
}

#element:fullscreen {
    /* ... */
}

SVGElementにclass属性を設定する

HTMLElementにclass属性を設定するときは, classNameプロパティやclassListプロパティにアクセスして設定します.

var div = document.createElement('div');
div.className = 'section-lv1';
div.classList.toggle('active');

SVGElement(やそれを継承したSVGの要素)に対して, その方法で設定しようとしても設定されません. では, どうすればいいかと言うと, setAttributeメソッドを利用します (逆に, HTMLElementでclass属性をsetAttributeメソッドで設定するのはタブーです).

var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('class', 'rect');

SVGで画像を動的に描画する

SVGで画像を動的に描画するには,

  • innerHTMLを利用する
  • createElementNS + appendChildを利用する

以上の2つの方法があります.

innerHTMLを利用する場合は, 特に解説は必要ないかと思いますので, createElementNS + appendChildを利用する方法を解説します.

var image = document.createElementNS('http://www.w3.org/2000/svg', 'image');

image.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'sample.png');

image.setAttributeNS(null, 'x',  x);
image.setAttributeNS(null, 'y',  y);
image.setAttributeNS(null, 'width',  64);  
image.setAttributeNS(null, 'height', 64);

document.querySelector('svg').appendChild(element);

ポイントは属性が名前空間付き属性であるということです. したがって, setAttributeではなく, setAttributeNSを利用する必要があります.

SVG 動的に要素を追加する

SVGにJavaScriptで動的に要素を追加する場合, HTMLElementのように, document.createElementメソッドで要素を作成し, DOMツリーに追加する方法ではうまくいきません

var text = document.createElement('text');

text.setAttribute('x', 10);
text.setAttribute('y', 10);
text.textContent = 'sample';

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

svg.appendChild(text);

この問題は, 要素を作成するときに名前空間を指定できるdocument.createElementNSメソッドを利用することで解決できます.

var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');

text.setAttribute('x', 10);
text.setAttribute('y', 10);
text.textContent = 'sample';

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

svg.appendChild(text);

第1引数にSVGの名前空間を指定し, 第2引数にSVGのタグ名を指定するだけです.

参考 : document.createElementNS

ArtCanvas.js 2.0 のリリース

描画に必要な機能の実装がおおよそ完了したので, これをバージョン 2.0としてリリースします.

  • レイヤー
  • ペン, 図形, テキストの描画
  • Undo / Redo / レイヤーのクリア
  • カラー
  • ライン (線幅, ラインキャップ, ラインジョイン)
  • 変形
  • エキスポート

少々挙動がおかしい機能もありますが, 以上のような機能が実装されています (バグは今後のバージョンアップで修正していきます).

Geolocation API

Geolocation APIの使い方を備忘録的に…

if (navigator.geolocation) {
    /**
      * getCurrentPositionの第1引数
      * @param {Geoposition} position
      */
    var successCallback =function(position){
         console.log(position.coords.latitude);          // 緯度
         console.log(position.coords.longitude);         // 経度
         console.log(position.coords.altitude);          // 高度
         console.log(position.coords.accuracy);          // 緯度・経度の精度
         console.log(position.coords.altitudeAccuracy);  // 高度の精度
         console.log(position.coords.heading);           // 方角 (0 ~ 360)
         console.log(position.coords.speed);             // 速度
    };

    /**
      * getCurrentPositionの第2引数 (省略可能)
      * @param {PositionError} code
      */
    var errorCallback = function(error) {
         switch (error.code) {
              case 0 :
                   console.error('原因不明のエラー');
                   break;
              case 1 :
                   console.error('ユーザーが位置情報の使用を許可しなかった');
                   break;
              case 2 :
                   console.error('電波状況が悪いなどの理由で, 現在位置を取得できなかった');
                   break;
              case 3 :
                   console.error('タイムアウト');
                   break;
              default :
                   break;
         }
    };

    // getCurrentPositionの第3引数 (省略可能)
    var options = {
        enableHighAccuracy : true,  // より精度の高い情報を取得するかどうか
        timeout : 10000,            // タイムアウト値 (ミリ秒)
        maximumAge : 60000          //  キャッシュ期間 (ミリ秒)
    };

    navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options);
} else {
    // Geolocation APIが利用できない場合
}