カスタム要素の使用 - Web API

カスタム要素の使用
=========

ウェブコンポーネント標準の主な特徴の 1 つは、 HTML ページに機能をカプセル化するカスタム要素を作成できることで、カスタムページの機能を提供する要素の長いネストしたバッチを作成する必要がありません。この記事では、カスタム要素 API の使い方を紹介します。

高水準のビュー
-------

ウェブ文書上でカスタム要素を制御するのは `CustomElementRegistry` オブジェクトです。このオブジェクトで、ページへカスタム要素を登録したり、どのようなカスタム要素が登録されているのかを返したりすることができます。

ページにカスタム要素を登録するには、 `CustomElementRegistry.define()` メソッドを使います。引数に次のものを取ります。

* 要素に与える名前を表す文字列。カスタム要素の名前は、ダッシュが使われている名前 (kebab-case) である必要があります。単一の単語にすることはできません。
* 要素の振る舞いを定義したクラスのオブジェクト。
* 省略可 `extends` プロパティを含むオプションオブジェクトです。このプロパティは、もしあれば、要素が継承する組み込み要素を指定します（カスタマイズされた組み込み要素にのみ関係します）。

カスタム要素には 2 つの種類があります。

* **自律カスタム要素** (Autonomous custom element) はスタンドアロンです。標準の HTML 要素を継承しません。 HTML 要素としてページ内で記述して使います。例えば、`<popup-info>` あるいは `document.createElement("popup-info")` などです。
* **カスタマイズされた組み込み要素** (Customized built-in element) は、基礎となる HTML 要素を継承します。これらを作成するには、どの要素を拡張するかを指定する必要があり（上記の例で示した通り）、基本要素を記述し、カスタム要素の名前を `is` 属性（またはプロパティ）で指定することで使用します。例えば、 `<p is="word-count">` や `document.createElement("p", { is: "word-count" })` のようにします。

例えば、**カスタマイズされた組み込み要素**である word-count 要素を定義するには次のようにします。

```js
customElements.define("word-count", WordCount, { extends: "p" });
```

 この要素は `word-count` と呼ばれ、クラスオブジェクトは `WordCount` であり、 `<p>` 要素を拡張したものになります。これは拡張された要素内で `is` 属性を設定することでのみ構築することができます。例えば、 `<p is="word-count">` または
 `document.createElement("p", { is: "word-count" })` のようにします。

カスタム要素のクラスのオブジェクトは `class` 構文で実装します。例えば、 `WordCount` は次のように構成します。

```js
class WordCount extends HTMLParagraphElement {
  constructor() {
    // コンストラクターでは常に super を最初に呼び出してください
    super();

    // ここに要素の機能を記述します
  }
}
```

**メモ:** JavaScript のソース全体があります。

これはごく簡単な例ですが、ここでできることはもっとあります。クラスの中でライフサイクルコールバックを定義することにより、要素のライフサイクルの特定の時点で実行することができます。例えば、 `connectedCallback` は文書に接続された要素にカスタム要素が追加されるたびに実行されます。一方 `attributeChangedCallback` はカスタム要素に属性が追加、削除、変更される時に実行されます。

これらについては、下記のライフサイクルコールバックの使用の節で詳しく学ぶことができます。

簡単な例での作業
--------

ここで、もう少し簡単な例で、カスタム要素の作成方法をより詳しく説明しましょう。

### 自律カスタム要素

自律カスタム要素の例を見てみましょう。`<popup-info-box>` (ライブ例も参照) です。これは画像とテキストを受け取り、ページにアイコンを埋め込みます。アイコンにフォーカスすると、テキストをポップアップ情報ボックスに表示し、さらにコンテキスト内の情報を提供します。

最初に汎用的な `HTMLElement` クラスを継承して `PopupInfo` というクラスを定義する JavaScript ファイルです。

```js
class PopupInfo extends HTMLElement {
  constructor() {
    // コンストラクターでは常に super を最初に呼び出してください
    super();

    // ここに要素の機能を記述します
  }
}
```

前述のコードスニペットはクラスのコンストラクター (`constructor()`) の定義を含んでいます。ここでは常に `super()` を最初に呼び出し、正しいプロトタイプチェーンが確立されるようにします。

コンストラクターの内部では、その要素のインスタンスが生成されたときに持つすべての機能を定義します。この場合、カスタム要素にシャドウルートを添付し、いくつかの DOM 操作を使用して要素の内部シャドウ DOM 構造を作成します。それをシャドウルートに添付します。そして最後に、いくつかの CSS をシャドウルートに添付してスタイル付けを行います。

```js
// シャドウルートを生成
this.attachShadow({ mode: "open" }); // 'this.shadowRoot' を設定して返す

//（内部の）span 要素を生成
const wrapper = document.createElement("span");
wrapper.setAttribute("class", "wrapper");
const icon = wrapper.appendChild(document.createElement("span"));
icon.setAttribute("class", "icon");
icon.setAttribute("tabindex", 0);
// アイコンを、定義された属性または既定のアイコンから挿入
const img = icon.appendChild(document.createElement("img"));
img.src = this.hasAttribute("img")
  ? this.getAttribute("img")
  : "img/default.png";
// 画像を追加する際には、常に説明文を含めるようする
img.alt = this.hasAttribute("alt") ? this.getAttribute("alt") : "";

const info = wrapper.appendChild(document.createElement("span"));
info.setAttribute("class", "info");
// 属性の中身を取得し、 info の span の中に入れる
info.textContent = this.getAttribute("data-text");

// CSS を作成しシャドウ DOM に割り当てる
const style = document.createElement("style");
style.textContent = `.wrapper {
 /\* 簡略化のために CSS は省略 \*/
}`;

// 生成された要素をシャドウ DOM に添付する
this.shadowRoot.append(style, wrapper);
```

最後に、カスタム要素を `CustomElementRegistry` に登録します。前述の `define()` を使用して、引数で要素名とその機能を定義するクラス名を指定します。

```js
customElements.define("popup-info", PopupInfo);
```

これによって要素がページで使えるようになりました。 HTML 内で下記のように使用することができます。

```html
<popup-info
 img="img/alt.png"
 data-text="Your card validation code (CVC)
 is an extra security feature — it is the last 3 or 4 numbers on the
 back of your card."></popup-info>
```

**メモ:** こちらで完全な JavaScript ソース を見ることができます。

### 内部スタイルと外部スタイル

上記の例では `<style>` 要素を用いてシャドウ DOM にスタイルを適用しましたが、代わりに完全に `<link>` 要素から外部スタイルシートを参照することが可能です。

例えば、 popup-info-box-external-stylesheet のコードを少し見てみましょう（ソースコードはこちら）。

```js
// 外部スタイルシートをシャドウ DOM に適用
const linkElem = document.createElement("link");
linkElem.setAttribute("rel", "stylesheet");
linkElem.setAttribute("href", "style.css");

// 生成された要素をシャドウ DOM に添付
shadow.appendChild(linkElem);
```

なお、 `<link>` 要素はシャドウルートの描画をブロックしないので、スタイルシートのロード中にスタイル付けされていないコンテンツ (FOUC) が一瞬表示されるかもしれないことに注意してください。

最近のブラウザーの多くは、共通のノードからクローンされた、あるいは同一のテキストを持つ `<style>` タグに対して、単一のバッキングスタイルシートを共有できるようにする最適化を実装しています。この最適化によって、外部スタイルでも内部スタイルでも性能は同程度になるはずです。

### カスタマイズされた組み込み要素

ここで、もう 1 つの組み込み要素の例を見てみましょう。 expanding-list です。（ライブでも確認してください） これにより番号なしリストが展開・収納するメニューになります。

まず始めに、これまでと同様の方法でクラス要素を定義します。

```js
class ExpandingList extends HTMLUListElement {
  constructor() {
    // コンストラクターでは常に super を最初に呼び出してください
    super();

    // ここに要素の機能を記述します
  }
}
```

ここでは要素の詳細な機能については説明しませんが、ソースコードからどのように動作するのか確認することができます。これまでと唯一違う点は、 `HTMLUListElement` インターフェースを継承しており、 `HTMLElement` ではないことです。そのため、独立した要素ではなく、 `<ul>` 要素の特徴を備えた上に、定義した機能を持ちます。これこそが、自律カスタム要素ではなくカスタマイズされた組み込み要素である理由です。

次に、以前と同様に `define()` を用いて要素を登録しますが、今回はこのカスタム要素がどの要素から継承したのかという情報をオプションとして渡しています。

```js
customElements.define("expanding-list", ExpandingList, { extends: "ul" });
```

ウェブ文書内で組み込み要素を使用する場合とはやや異なります。

```html
<ul is="expanding-list">
  …
</ul>
```

通常のように `<ul>` を使用していますが、カスタム要素の名前が `is` 属性で指定されています。

**メモ:** 繰り返しますが、完全な JavaScript のソースコードはこちらにあります。

ライフサイクルコールバックの使用
----------------

カスタム要素のクラス定義内に、いくつかの異なるコールバックを定義できます。これらは要素のライフサイクルのさまざまな時点で起動します。

* `connectedCallback`: 文書に接続された要素にカスタム要素が追加されるたびに呼び出されます。これはそのノードが移動するために発生するので、要素の内容が完全に解釈される前に発生することがあります。

**メモ:** `connectedCallback` は要素の接続が終了したときにも呼び出されることがあります。 `Node.isConnected` を使用して確認してください。
* `disconnectedCallback`: カスタム要素が文書の DOM から切断されるたびに呼び出されます。
* `adoptedCallback`: カスタム要素が新しい文書に移動するたびに呼び出されます。
* `attributeChangedCallback`: カスタム要素の属性の 1 つが追加、削除、変更されるたびに呼び出されます。どの属性の変更が通知されたかは、静的な get `observedAttributes()` メソッドで指定されます。

これらの使用例を見てみましょう。以下のコードは life-cycle-callbacks の例から引用しています（実行可能なライブでも確認してください）。これは、ページ上に一定の大きさの色のついた四角形を生成する些細な例です。カスタム要素は次のようなものです。

```html
<custom-square l="100" c="red"></custom-square>
```

クラスのコンストラクターは非常に単純です。ここでは、要素にシャドウ DOM を割り当て、空の `<div>` および `<style>` 要素をシャドウルートに追加します。

```js
const shadow = this.attachShadow({ mode: "open" });

const div = document.createElement("div");
const style = document.createElement("style");
shadow.appendChild(style);
shadow.appendChild(div);
```

この例の主要な機能は `updateStyle()` です。これは要素を取得し、シャドウルートを取得し、その `<style>` 要素を見つけて、`width`, `height`, および`background-color` をそのスタイルに追加します。

```js
function updateStyle(elem) {
  const shadow = elem.shadowRoot;
  shadow.querySelector("style").textContent = `
 div {
 width: ${elem.getAttribute("l")}px;
 height: ${elem.getAttribute("l")}px;
 background-color: ${elem.getAttribute("c")};
 }
 `;
}
```

実際の更新はすべて、メソッドとしてクラス定義内に配置されているライフサイクルコールバックによって処理されます。 `connectedCallback()` は、要素が DOM に追加されるたびに実行されます。ここでは、 `updateStyle()` 関数を実行して、正方形がその属性で定義されたスタイルになっていることを確認します。

```js
connectedCallback() {
  console.log('Custom square element added to page.');
  updateStyle(this);
}
```

`disconnectedCallback()` および `adoptedCallback()` コールバックは、要素が DOM から削除されるか、別のページに移動されたときに通知する単純なメッセージをコンソールに記録します。

```js
disconnectedCallback() {
  console.log('Custom square element removed from page.');
}

adoptedCallback() {
  console.log('Custom square element moved to new page.');
}
```

`attributeChangedCallback()` コールバックは、要素の属性の 1 つが何らかの方法で変更されるたびに実行されます。そのプロパティからわかるように、属性、属性の名前、および古い属性値と新しい属性値を個別に操作することができます。ただし、この場合は、 `updateStyle()` 関数を再度実行して、新しい値に従って正方形のスタイルが更新されるようにします。

```js
attributeChangedCallback(name, oldValue, newValue) {
  console.log('Custom square element attributes changed.');
  updateStyle(this);
}
```

ある属性が変更されたときに起動する `attributeChangedCallback()` コールバックを取得するには、その属性を監視する必要があることに注意してください。これは、カスタム要素クラス内で `static get observedAttributes()` メソッドを定義することによって行われます。これは、監視したい属性の名前を含む配列を返すようにしてください。

```js
static get observedAttributes() { return ['c', 'l']; }
```

この例では、これはコンストラクターの最上部に配置されています。

**メモ:** 完全な JavaScript のソースはこちらにあります。

トランスパイラーとクラス
------------

古いブラウザーを対象とした Babel 6 や TypeScript では、クラスが期待通りにトランスパイルされない可能性があることに注意してください。 Babel 7 もしくは Babel 6 の babel-plugin-transform-builtin-classes を使用すると、 TypeScript で古いブラウザーではなく ES2015 をターゲットとすることができます。

ライブラリー
------

カスタム要素を作る際に抽象度を高めることを目的とした、ウェブコンポーネントで実装されたライブラリーがあります。これらのライブラリーには、 FASTElement, snuggsi, X-Tag, Slim.js, Lit, Smart, Stencil, hyperHTML-Element, DataFormsJS, Custom-Element-Builder などがあります。


シャドウ DOM の使用 - Web API

シャドウ DOM の使用
============

ウェブコンポーネントにおける重要な側面の一つが、カプセル化です。マークアップ構造、スタイル、動作を隠蔽し、コード上の他のコードから分離することで、他の部分でクラッシュすることを防ぎ、コードをきれいにしておくことができます。シャドウ DOM API はこの主要部分であり、隠蔽され分離された DOM を要素に取り付けるための方法を提供しています。この記事ではシャドウ DOM を使う基本を記述しています。

高水準のビュー
-------

この記事は、すでにあなたが DOM (Document Object Model) の概念を理解していることを想定しています。これはツリー上の構造で、接続されたノードがマークアップ文書（ウェブ文書の場合は通常 HTML 文書）に現れるさまざまな要素や文字列を表します。例として、以下のような HTML の断片を考えてみましょう。

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Simple DOM example</title>
  </head>
  <body>
    <section>
      <img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
      <p>
        Here we will add a link to the
        <a href="https://www.mozilla.org/">Mozilla homepage</a>
      </p>
    </section>
  </body>
</html>
```

この断片によって以下のような DOM 構造が構成されます。

![要素とテキストノードを持つDOMツリー、要素の属性名と内容を含めるために、空でないテキストノードのコンテンツ。](/ja/docs/Web/API/Web_components/Using_shadow_DOM/dom-screenshot.png)

*シャドウ* DOM により、通常の DOM ツリーの要素の下に隠れた DOM ツリーを取り付けることができます。このシャドウ DOM ツリーはシャドウルートから始まり、その下には普通の DOM ツリーと同様に任意の要素を追加することができます。

![文書、シャドウルート、シャドウホストの相互作用を示す図の SVG 版。](/ja/docs/Web/API/Web_components/Using_shadow_DOM/shadowdom.svg)

以下にシャドウ DOM における用語を定義します。

* **シャドウホスト**: シャドウ DOM が取り付けられた、通常の DOM ノード
* **シャドウツリー**: シャドウ DOM の中にある DOM ツリー
* **シャドウ境界**: シャドウ DOM と通常の DOM の境界
* **シャドウルート**: シャドウツリーの根ノード

シャドウ DOM 内のノードには、シャドウでないノードと全く同じように影響を与えることができます。たとえば、子を追加したり、属性を設定したり、element.style.foo を使用して個々のノードのスタイルを設定したり、 `<style>` 要素内でシャドウ DOM ツリー全体へのスタイルを追加したりすることができます。違いは、シャドウ DOM 内のどのコードもその外の何かに影響を与えることができず、便利なカプセル化ができることです。

なお、シャドウ DOM は決して新しいものではありません。ブラウザーは長い間、要素の内部構造をカプセル化するためにこれを使用してきました。例えば、既定のブラウザーコントロールが公開されている `<video>` 要素を思い浮かべてください。 DOM には `<video>` 要素しか表示されませんが、そのシャドウ DOM の内部には、一連のボタンやその他のコントロールが含まれています。 シャドウ DOM 仕様書により、独自のカスタム要素のシャドウ DOM を実際に操作することができるようになりました。

基本的な使い方
-------

任意の要素にシャドウルートを取り付けるには `Element.attachShadow()` メソッドを使用します。このメソッドはオプションオブジェクトを引数として取り、その中にはオプションが 1 つ、 `mode` オプションを `open` または `closed` の値で取ります。

```js
const shadowOpen = elementRef.attachShadow({ mode: "open" });
const shadowClosed = elementRef.attachShadow({ mode: "closed" });
```

`open` の場合は、シャドウ DOM にメインページに書かれた JavaScript からアクセスできます。以下のように `Element.shadowRoot` プロパティを利用してアクセスできます。

```js
const myShadowDom = myCustomElem.shadowRoot;
```

シャドウルートを `mode: "closed"` が設定された状態で取り付けた場合、外部からシャドウ DOM にアクセスすることができません。 `myCustomElem.shadowRoot` は `null` を返します。シャドウ DOM を含む既成の要素、例えば `<video>` などはこれに該当します。

なお、同じ JavaScript の領域内において、これはシャドウルートを隠す方法として完全に安全な訳ではありません。コードが `Element.prototype.attachShadow` を上書きして、常に `mode: "open"` を使用することが可能だとこのブログ記事が示しています。しかし、悪意のあるコードがグローバルを操作することが懸念される環境でない限り、このことを心配する必要はないでしょう。さらに、ウェブ拡張機能はウィンドウのグローバルにアクセスしないため、シャドウ DOM をウェブ拡張機能から確実に保護することができます。

シャドウ DOM をカスタム要素のコンストラクターの一部として取り付けた場合（シャドウ DOM の最も有用な用途です）、次のような方法を使用することになります。

```js
const shadow = this.attachShadow({ mode: "open" });
```

シャドウ DOM を要素に取り付けた場合、その操作は通常の DOM 操作と同じ DOM API を使うだけでよいのです。

```js
const para = document.createElement("p");
shadow.appendChild(para);
// etc.
```

簡単な例を一通り扱う
----------

カスタム要素内のシンプルなシャドウ DOM を見てみましょう。 `<popup-info>` （ライブ例を参照）です。この要素は画像アイコンとテキストを取り、アイコンをページに埋め込みます。アイコンがフォーカスされるとポップアップが表示され、さらなる情報を提供します。まずは `HTMLElement` を拡張して `PopUpInfo` というクラスを定義します。

```js
class PopUpInfo extends HTMLElement {
  constructor() {
    // コンストラクターでは常に super を最初に呼び出してください
    super();

    // ここに要素の機能を記述します
  }
}
```

クラス定義の中で、要素のコンストラクターを定義し、その中で要素のインスタンスが生成されたときに、その要素が持つすべての機能を定義します。

### シャドウルートの作成

最初にシャドウルートをカスタム要素に追加します。

```js
// シャドウルートを生成
const shadow = this.attachShadow({ mode: "open" });
```

### シャドウ DOM 構造の作成

次に、いくつかの DOM 操作を使用して、要素の内部シャドウ DOM 構造を作成します。

```js
// span の生成
const wrapper = document.createElement("span");
wrapper.setAttribute("class", "wrapper");
const icon = document.createElement("span");
icon.setAttribute("class", "icon");
icon.setAttribute("tabindex", "0");
const info = document.createElement("span");
info.setAttribute("class", "info");

// 属性の中身を取得し、 info の span の中に入れる
const text = this.getAttribute("data-text");
info.textContent = text;

// アイコンを挿入
const img = document.createElement("img");
img.src = this.hasAttribute("img")
  ? this.getAttribute("img")
  : "img/default.png";
img.alt = this.hasAttribute("alt") ? this.getAttribute("alt") : "";
icon.appendChild(img);
```

### シャドウ DOM のスタイル付け

そのあと、 `<style>` 要素を作り CSS でスタイルを付けます。

```js
// CSS を生成してシャドウ DOM に適用
let style = document.createElement("style");

style.textContent = `
.wrapper {
 position: relative;
}

.info {
 font-size: 0.8rem;
 width: 200px;
 display: inline-block;
 border: 1px solid black;
 padding: 10px;
 background: white;
 border-radius: 10px;
 opacity: 0;
 transition: 0.6s all;
 position: absolute;
 bottom: 20px;
 left: 10px;
 z-index: 3;
}

img {
 width: 1.2rem;
}

.icon:hover + .info, .icon:focus + .info {
 opacity: 1;
}`;
```

### シャドウ DOM をシャドウルートに追加

最後のステップは、生成した要素すべてをシャドウルートに取り付けることです。

```js
// 生成した要素をシャドウ DOM に取り付ける
shadow.appendChild(style);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);
```

### カスタム要素の使用

一度クラスを定義すれば、カスタム要素の使用で説明したように、その要素を定義し、ページに配置するだけで簡単に使用できるようになります。

```js
// 新しい要素を定義
customElements.define("popup-info", PopUpInfo);
```

```html
<popup-info
 img="img/alt.png"
 data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."></popup-info>
```

### 内部スタイルと外部スタイル

上記の例では `<style>` 要素を用いてシャドウ DOM にスタイルを適用しましたが、代わりに完全に `<link>` 要素から外部スタイルシートを参照することが可能です。

例えば、 popup-info-box-external-stylesheet のコードを少し見てみましょう（ソースコードはこちら）。

```js
// 外部スタイルシートをシャドウ DOM に適用
const linkElem = document.createElement("link");
linkElem.setAttribute("rel", "stylesheet");
linkElem.setAttribute("href", "style.css");

// 生成された要素をシャドウ DOM に添付
shadow.appendChild(linkElem);
```

なお、 `<link>` 要素はシャドウルートの描画をブロックしないので、スタイルシートのロード中にスタイル付けされていないコンテンツ (FOUC) が一瞬表示されるかもしれないことに注意してください。

最近のブラウザーの多くは、共通のノードからクローンされた、あるいは同一のテキストを持つ `<style>` タグに対して、単一のバッキングスタイルシートを共有できるようにする最適化を実装しています。この最適化によって、外部スタイルでも内部スタイルでも性能は同程度になるはずです。

関連情報
----

* カスタム要素の使用
* テンプレートとスロットの使用


テンプレートとスロットの使用 - Web API

テンプレートとスロットの使用
==============

この記事では、`<template>` と `<slot>` 要素を使用して柔軟なテンプレートを作成し、それをウェブコンポーネントのシャドウ DOM を表示するために使用する方法について説明します。

テンプレートの真実
---------

 ウェブページで同じマークアップ構造を繰り返し再利用する必要がある場合、同じ構造を何度も繰り返すよりも、何らかのテンプレートを使用する方が理にかなっています。
 これは以前から可能でしたが、HTML の `<template>` 要素によって、かなり容易になりました（最近のブラウザーはよく対応しています）。
 この要素とその内容は DOM 内で描画されませんが、JavaScript を使って参照することは可能です。

簡単な例を見てみましょう。

```html
<template id="my-paragraph">
  <p>My paragraph</p>
</template>
```

これはページ上に表示されず、以下のようなコードで JavaScript で参照を取得し、 DOM に追加することで表示されます。

```js
let template = document.getElementById("my-paragraph");
let templateContent = template.content;
document.body.appendChild(templateContent);
```

つまらない例ですが、すでに有用性は見えてきたでしょう。

ウェブコンポーネントを用いたテンプレートの使用
-----------------------

 テンプレートはそれ自体でも便利ですが、ウェブコンポーネントと組み合わせるとさらに効果的です。
 テンプレートをシャドウ DOM の内容として使用するウェブコンポーネントを定義してみましょう。
 同様に `<my-paragraph>` と呼ぶことにします。

```js
customElements.define(
  "my-paragraph",
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById("my-paragraph");
      let templateContent = template.content;

      const shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(templateContent.cloneNode(true));
    }
  },
);
```

ここで、テンプレートの内容を使用するために `Node.cloneNode()` メソッドを使用して複製したものをシャドウルートに追加していることに注意してください。

 また、その内容をシャドウ DOM に追加しているため、テンプレート内のスタイル情報を `<style>` 要素に含めることができ、それがカスタム要素内にカプセル化されます。
 これは、単に標準 DOM に追加しただけでは機能しません。

したがって、例えば次のようにすると、

```html
<template id="my-paragraph">
  <style>
 p {
 color: white;
 background-color: #666;
 padding: 5px;
 }
 </style>
  <p>My paragraph</p>
</template>
```

HTML 文書に次のように追加するだけで利用できるようになりました。

```html
<my-paragraph></my-paragraph>
```

スロットによる柔軟性の強化
-------------

 ここまではいいのですが、この要素はあまり柔軟ではありません。
 中には高々 1 つのテキストを表示できるだけなので、現時点では通常の段落よりも有用ではありません。 `<slot>` 要素を使用することで、各要素インスタンスに異なるテキストを表示することを宣言的に行えるようにすることができます。

スロットは `name` 属性で識別され、テンプレート内にプレースホルダーを定義することができます。このプレースホルダーは、その要素がマークアップで使用されたときに、任意のマークアップフラグメントで埋められるようになります。

ですから、この些細な例にスロットを追加したい場合、テンプレートの段落要素を次のように更新してください。

```html
<p><slot name="my-text">既定のテキスト</slot></p>
```

マークアップに要素が含まれるときにスロットの内容が定義されていない場合、またはブラウザーがスロットに対応していない場合、 `<my-paragraph>` はに単に代替内容である「既定のテキスト」が入ります。

スロットの内容を定義するために、`<my-paragraph>` 要素の中に HTML 構造を入れ、 `slot` 属性の値が埋めたいスロットの名前と同じになるようにします。前と同じように、これは好きなものを指定できます。

```html
<my-paragraph>
  <span slot="my-text">別なテキストを入れましょう。</span>
</my-paragraph>
```

以下のようにも設定できます。

```html
<my-paragraph>
  <ul slot="my-text">
    <li>別なテキストを入れましょう。</li>
    <li>リストの中です。</li>
  </ul>
</my-paragraph>
```

**メモ:** スロットに挿入することができるノードは「スロット可能 (Slottable)」ノードと呼ばれます。ノードがスロットに挿入されたとき、「スロットされている」と言います。

**メモ:** 無名の `<slot>` には、カスタム要素のトップレベルの子ノードのうち `slot` 属性を持たないすべてのノードが入ります。これにはテキストノードも含まれます。

 簡単な例での説明は以上です。
 もっと実行してみたい場合は、 GitHub 上にあります（ライブ実行版もあります）。

より踏み込んだ例
--------

記事の最後に、もう少し本格的なものを見てみましょう。

以下の一連のコードは、 `<slot>` を `<template>` と若干の JavaScript と組み合わせて使用する方法を示すコードスニペットです。

* **`<element-details>`** 要素を名前付きスロット付きでシャドウルートの中に作成する
* **`<element-details>`** 要素を、文書内で使用されたとき、要素の内容とそのシャドウルートの内容を組み合わせてレンダリングされるように設計します。つまり、要素の内容の断片は、そのシャドウルートの中で名前付きスロットを埋めるために使用されます。

 なお、 `<slot>` 要素は技術的には、 `<template>` 要素なしで、例えば、通常の `<div>` 要素内で使うことも可能であり、それでもシャドウ DOM 内容に対して `<slot>` のプレースホルダー機能を活用することができますし、そうすれば、最初にテンプレート要素の `content` プロパティにアクセス（してそれを複製）する必要があるという小さなトラブルも実際に避けることができます。
 しかし、一般的には `<template>` 要素内にスロットを追加する方がより実用的です。なぜなら、既にレンダリングされた要素に基づいてパターンを定義する必要があることはほとんどないからです。

また、まだレンダリングされていない場合でも、 `<template>` を使用することで、テンプレートとしてのコンテナーの目的がより意味的に明確になるはずです。また、 `<template>` には、 `<td>` のような、 `<div>` に追加すると消えてしまうような項目を直接追加することができます。

**メモ:** 完全な例は element-details で（ライブ実行版も）参照することができます。

### template をスロットと共に作成

まず最初に `<slot>` 要素を `<template>` 要素の中に作成し、名前付きスロットを含んだ新しい "element-details-template" という文書フラグメントを作成します。

```html
<template id="element-details-template">
  <style>
 details {
 font-family: "Open Sans Light", Helvetica, Arial;
 }
 .name {
 font-weight: bold;
 color: #217ac0;
 font-size: 120%;
 }
 h4 {
 margin: 10px 0 -8px 0;
 }
 h4 span {
 background: #217ac0;
 padding: 2px 6px 2px 6px;
 }
 h4 span {
 border: 1px solid #cee9f9;
 border-radius: 4px;
 }
 h4 span {
 color: white;
 }
 .attributes {
 margin-left: 22px;
 font-size: 90%;
 }
 .attributes p {
 margin-left: 16px;
 font-style: italic;
 }
 </style>
  <details>
    <summary>
      <span>
        <code class="name"
 ><<slot name="element-name">NEED NAME</slot>></code
 >
        <span class="desc"
 ><slot name="description">NEED DESCRIPTION</slot></span
 >
      </span>
    </summary>
    <div class="attributes">
      <h4><span>Attributes</span></h4>
      <slot name="attributes"><p>None</p></slot>
    </div>
  </details>
  <hr />
</template>
```

この `<template>` 要素にはいくつかの特徴があります。

* `<template>` には `<style>` 要素があり、 `<template>` が生成する文書の断片だけを対象とした CSS スタイルの集合を持ちます。
* `<template>` は `<slot>` とその `name` 属性を用いて、 3 つの名前付きスロット を生成しています。
    + `<slot name="element-name">`
    + `<slot name="description">`
    + `<slot name="attributes">`
* `<template>` には名前付きスロットを `<details>` 要素の中に持ちます。
### 新しい <element-details> 要素を <template> から生成

 次に、 **`<element-details>`** という名前の新しいカスタム要素を生成して、 `Element.attachShadow` でそのシャドウルートとして追加し、上記の `<template>` 要素で生成した文書の断片を取り付けてみましょう。
 これは、先ほどの簡単な例で見たのとまったく同じパターンを使っています。

```js
customElements.define(
  "element-details",
  class extends HTMLElement {
    constructor() {
      super();
      const template = document.getElementById(
        "element-details-template",
      ).content;
      const shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(template.cloneNode(true));
    }
  },
);
```

### <element-details> カスタム要素を名前付きスロットと共に使用する

では、 **`<element-details>`** 要素を文書内で実際に使ってみましょう。

```html
<element-details>
  <span slot="element-name">slot</span>
  <span slot="description"
 >A placeholder inside a web component that users can fill with their own
    markup, with the effect of composing different DOM trees together.</span
 >
  <dl slot="attributes">
    <dt>name</dt>
    <dd>The name of the slot.</dd>
  </dl>
</element-details>

<element-details>
  <span slot="element-name">template</span>
  <span slot="description"
 >A mechanism for holding client- side content that is not to be rendered
    when a page is loaded but may subsequently be instantiated during runtime
    using JavaScript.</span
 >
</element-details>
```

このコードについて以下の点に注意してください。

* このスニペットには **`<element-details>`** 要素が 2 つあり、どちらも `slot` 属性を使って `<element-details>` のシャドウルートに置いた名前付きスロットの `"element-name"` と `"description"` を参照しています。
* これら 2 つの **`<element-details>`** 要素のうち最初のものだけが `"attributes"` 名前付きスロット を参照しています。 2 番目の `<element-details>` 要素は `"attributes"` 名前付きスロット への参照を欠いています。
* 最初の `<element-details>` 要素は `"attributes"` 名前付きスロット を `<dl>` およびその子要素である `<dt>` と `<dd>` を使って参照しています。
### 最後に多少のスタイルを追加

最後に若干の CSS スタイルを、文書中の `<dl>`、`<dt>`、`<dd>` の各要素に追加ししす。

```css
dl {
  margin-left: 6px;
}
dt {
  color: #217ac0;
  font-family: Consolas, "Liberation Mono", Courier;
  font-size: 110%;
  font-weight: bold;
}
dd {
  margin-left: 16px;
}
```

```
body {
  margin-top: 47px;
}
```

### 結果

以上のコードを繋げてどのような結果がレンダリングされるかを確認しましょう。

このレンダリング結果について、以下の点に注意してください。

* 文書内で **`<element-details>`** 要素のインスタンスは `<details>` 要素を直接使用しませんが、 `<details>` をシャドウルートが表示させることでレンダリングされます。
* レンダリングされた `<details>` の出力結果で、**`<element-details>`** 要素の内容は名前付きスロットをシャドウルートから埋め込みます。言い換えれば、 **`<element-details>`** 要素の DOM ツリーはシャドウルートの内容と共に構成されます。
* 両方の **`<element-details>`** 要素おいて、 **Attributes** の見出しはシャドウルートから `"attributes"` 名前付きスロットの位置の前に、自動的に追加されます。
* 最初の **`<element-details>`** はシャドウルートから名前付きスロットを明示的に参照している `<dl>` 要素を持つため、`<dl>` の内容は シャドウルートから `"attributes"` 名前付きスロットを置き換えています。
* 2 つ目の **`<element-details>`** はシャドウルートから名前付きスロットを明示的に参照していないため、名前付きスロットの内容はシャドウルートの既定の内容が埋め込まれます。


NodeList: entries() メソッド - Web API

NodeList: entries() メソッド
========================

**`NodeList.entries()`** メソッドは、オブジェクト内にあるすべてのキーと値のペアを走査することができる`イテレーター`を返します。値は `Node` オブジェクトです。

構文
--

```js
entries()
```

返値
--

`イテレーター`を返します。

例
-

```js
const node = document.createElement("div");
const kid1 = document.createElement("p");
const kid2 = document.createTextNode("hey");
const kid3 = document.createElement("span");
node.appendChild(kid1);
node.appendChild(kid2);
node.appendChild(kid3);

const list = node.childNodes;

// for...of を使用
for (const entry of list.entries()) {
  console.log(entry);
}
```

結果は次のようになります。
```

Array [ 0, <p> ]
Array [ 1, #text "hey" ]
Array [ 2, <span> ]
```

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `NodeList.prototype.entries` のポリフィル (`core-js`)
* `Node`
* `NodeList`


NodeList: values() メソッド - Web API

NodeList: values() メソッド
=======================

**`NodeList.values()`** メソッドは、このオブジェクトに含まれるすべての値を走査することができる`イテレーター`を返します。値は `Node` です。

構文
--

```js
values()
```

返値
--

`イテレーター`を返します。

例
-

```js
const node = document.createElement("div");
const kid1 = document.createElement("p");
const kid2 = document.createTextNode("hey");
const kid3 = document.createElement("span");

node.appendChild(kid1);
node.appendChild(kid2);
node.appendChild(kid3);

const list = node.childNodes;

// for...of の使用
for (const value of list.values()) {
  console.log(value);
}
```

結果は次の通りです。
```

<p>
#text "hey"
<span>
```

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Polyfill of `NodeList.prototype.values` in `core-js`
* `Node`
* `NodeList`


NodeList: length プロパティ - Web API

NodeList: length プロパティ
======================

**`NodeList.length`** プロパティは、`NodeList` のアイテムの数を返します。

値
-

整数値で、`NodeList` 内のアイテムの数を表します。

例
-

`length` プロパティは DOM プログラミングでしばしば有益です。リストがすべて存在するかどうかを確認するために、リストの長さを検査するために使用することが多いからです。また、この例のように `for` ループのイテレーターとしてもよく使用されます。

```js
// 文書内のすべての段落
const items = document.getElementsByTagName("p");

// リスト中のすべてのアイテムに対して実行し、
// HTML の文字列として要素全体を追加
let gross = "";
for (let i = 0; i < items.length; i++) {
  gross += items[i].innerHTML;
}

// gross には HTML のすべての段落が入ります
```

仕様書
---

| Specification |
| --- |
| DOM Standard # ref-for-dom-nodelist-length① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


NodeList: keys() メソッド - Web API

NodeList: keys() メソッド
=====================

**`NodeList.keys()`** メソッドは、このオブジェクトに含まれるすべてのキーを走査することができる`イテレーター`を返します。キーは `unsigned integer` です。

構文
--

```js
keys()
```

返値
--

`イテレーター`を返します。

例
-

```js
const node = document.createElement("div");
const kid1 = document.createElement("p");
const kid2 = document.createTextNode("hey");
const kid3 = document.createElement("span");

node.appendChild(kid1);
node.appendChild(kid2);
node.appendChild(kid3);

let list = node.childNodes;

// for...of の使用
for (const key of list.keys()) {
  console.log(key);
}
```

結果は次の通りです。
```

0
1
2
```

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `NodeList.prototype.keys` のポリフィル (`core-js`)
* `Node`
* `NodeList`


NodeList: forEach() メソッド - Web API

NodeList: forEach() メソッド
========================

**`forEach()`** は `NodeList` インターフェイスのメソッドで、引数に渡されたコールバックを、リストのそれぞれの値のペアに対して 1 度ずつ挿入順に呼び出します。

構文
--

```js
forEach(callback)
forEach(callback, thisArg)
```

### 引数

`callback`

`someNodeList` の各要素に対して実行する関数です。3 つの引数を受け付けます。

`currentValue`

現在 `someNodeList` で処理されている要素です。

`currentIndex` 省略可

現在 `someNodeList` で処理されている `currentValue` のインデックスです。

`listObj` 省略可

`forEach()` を適用しようとしている `someNodeList` です。

`thisArg` 省略可

`callback` 内で `this` として使う値です。

### 返値

`undefined`.

例
-

```js
const node = document.createElement("div");
const kid1 = document.createElement("p");
const kid2 = document.createTextNode("hey");
const kid3 = document.createElement("span");

node.appendChild(kid1);
node.appendChild(kid2);
node.appendChild(kid3);

const list = node.childNodes;

list.forEach(function (currentValue, currentIndex, listObj) {
  console.log(`${currentValue}, ${currentIndex}, ${this}`);
}, "myThisArg");
```

上記のコードの結果は以下のようになります。
```

[object HTMLParagraphElement], 0, myThisArg
[object Text], 1, myThisArg
[object HTMLSpanElement], 2, myThisArg
```

仕様書
---

| Specification |
| --- |
| DOM Standard # interface-nodelist |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `NodeList.prototype.forEach` のポリフィル (`core-js`)
* `Node`
* `NodeList`


NodeList: item() メソッド - Web API

NodeList: item() メソッド
=====================

`NodeList` からインデックスでノードを返します。このメソッドは引数を提供する限り例外を発生しません。インデックスが範囲外の場合は `null` という値が返され、引数が指定されなかった場合は `TypeError` が発生します。

構文
--

```js
item(index)
```

JavaScript では、NodeList からインデックスでアイテムを取得するのに配列風の括弧構文も提供しています。

```js
nodeItem = nodeList[index];
```

### 引数

* `index` はノードを読み取るインデックスです。インデックスはゼロ基点です。
### 返値

`item` メソッドが返す `nodeList` 内の `index` 番目のノード。

### 例外

`TypeError`

引数が提供されなかった場合に発生します。

例
-

```js
const tables = document.getElementsByTagName("table");
const firstTable = tables.item(1); // または tables[1] - DOM 内の 2 番目の表を返す
```

仕様書
---

| Specification |
| --- |
| DOM Standard # ref-for-dom-nodelist-item① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: requestPictureInPicture() メソッド - Web API

HTMLVideoElement: requestPictureInPicture() メソッド
================================================

**`HTMLVideoElement`** の **`requestPictureInPicture()`** メソッドは、動画をピクチャインピクチャモードで表示するための非同期のリクエストを発行します。

動画がピクチャインピクチャになることは保証されていません。そのモードに入る権限が与えられている場合、返された `Promise` は解決され、動画は `enterpictureinpicture` イベントを受け取り、これでピクチャインピクチャになったことを知らせます。

構文
--

```js
requestPictureInPicture()
```

### 引数

なし。

### 返値

`Promise` で、ユーザーがその浮動ウィンドウのサイズを変更するときに使用することができる `PictureInPictureWindow` オブジェクトに解決します。

### 例外

`SecurityError` `DOMException`

この機能の使用が権限ポリシーによってブロックされた場合。

セキュリティ
------

ユーザーによる一時的な有効化が必要です。この機能が動作するには、ユーザーがページまたは UI 要素を操作する必要があります。

例
-

この例では、動画がピクチャインピクチャモードになるようにリクエストされ、浮動ウィンドウのリサイズを処理するためのイベントリスナーを設定します。

```js
function enterPictureInPicture() {
  videoElement.requestPictureInPicture().then((pictureInPictureWindow) => {
    pictureInPictureWindow.addEventListener(
      "resize",
      () => onPipWindowResize(),
      false,
    );
  });
}
```

仕様書
---

| Specification |
| --- |
| Picture-in-Picture # request-pip |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `<video>` 要素
* `HTMLVideoElement.disablePictureInPicture`
* `Document.pictureInPictureEnabled`
* `Document.exitPictureInPicture()`
* `Document.pictureInPictureElement`
* `:picture-in-picture`


HTMLVideoElement: disablePictureInPicture プロパティ - Web API

HTMLVideoElement: disablePictureInPicture プロパティ
===============================================

`HTMLVideoElement` の **`disablePictureInPicture`** プロパティは HTML の属性を反映し、ピクチャインピクチャ機能が現在の要素で無効になっているかどうかを示します。

値
-

論理値で、この要素でピクチャインピクチャ機能が無効な場合に `true` となります。これは、ユーザーエージェントがその機能をユーザーに提案したり、自動的にリクエストしたりしないことを意味しています。

仕様書
---

| Specification |
| --- |
| Picture-in-Picture # disable-pip |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: getVideoPlaybackQuality() メソッド - Web API

HTMLVideoElement: getVideoPlaybackQuality() メソッド
================================================

**`HTMLVideoElement`** の **`getVideoPlaybackQuality()`** メソッドは、どれだけのフレームが落ちるのかを示す指標を含む `VideoPlaybackQuality` (en-US) オブジェクトを返します。

返されるデータは、動画ストリームの品質を評価するために使用することができます。

構文
--

```js
getVideoPlaybackQuality()
```

### 引数

なし。

### 返値

`VideoPlaybackQuality` (en-US) オブジェクトで、この video 要素の再生品質についての情報を提供します。

例
-

この例では、再生処理でこれまでに経過した動画フレームの総数を示す要素を更新します。この値には、取りこぼしたフレームや破損したフレームも含まれるため、「再生されたフレームの総数」とは異なります。

```js
const videoElem = document.getElementById("my\_vid");
const counterElem = document.getElementById("counter");
const quality = videoElem.getVideoPlaybackQuality();

counterElem.innerText = quality.totalVideoFrames;
```

仕様書
---

| Specification |
| --- |
| Media Playback Quality # dom-htmlvideoelement-getvideoplaybackquality |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `<video>` 要素
* `VideoPlaybackQuality` (en-US) インターフェイス


HTMLVideoElement: enterpictureinpicture イベント - Web API

HTMLVideoElement: enterpictureinpicture イベント
============================================

`enterpictureinpicture` イベントは、`HTMLVideoElement` がピクチャインピクチャモードに入ることに成功した場合に発行されます。

このイベントはキャンセル不可で、バブリングしません。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("enterpictureinpicture", (event) => {});

onenterpictureinpicture = (event) => {};
```

イベント型
-----

`PictureInPictureEvent` です。`Event` を継承しています。

Event

PictureInPictureEventイベントプロパティ
---------

このインターフェイスには、親である `Event` から継承したプロパティもあります。

例
-

この例は HTMLVideoElement の `leavepictureinpicture` イベントのイベントリスナーを追加し、イベントハンドラーがイベントの発行に反応したときにメッセージを投稿します。

`addEventListener()` を使用した場合:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onEnterPip() {
  console.log("Picture-in-Picture mode activated!");
}

video.addEventListener("enterpictureinpicture", onEnterPip, false);

button.onclick = () => {
  video.requestPictureInPicture();
};
```

`onenterpictureinpicture` イベントハンドラープロパティを使用した場合:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onEnterPip() {
  console.log("Picture-in-Picture mode activated!");
}

video.onenterpictureinpicture = onEnterPip;

button.onclick = () => {
  video.requestPictureInPicture();
};
```

仕様書
---

| Specification |
| --- |
| Picture-in-Picture # eventdef-htmlvideoelement-enterpictureinpicture |
| Picture-in-Picture # dom-htmlvideoelement-onenterpictureinpicture |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `HTMLVideoElement`
* `Picture-in-Picture API`


HTMLVideoElement: videoHeight プロパティ - Web API

HTMLVideoElement: videoHeight プロパティ
===================================

`HTMLVideoElement` インターフェイスの **`videoHeight`** プロパティは読み取り専用で、動画の内在的な高さを CSS ピクセル単位で示します。
 単純に言えば、これはメディアの自然なサイズでの高さです。

値
-

 動画の内在的な高さを CSS のピクセル数で示す整数値。
 要素の `readyState` が `HTMLMediaElement.HAVE_NOTHING` の場合、このプロパティの値は 0 です。これは、動画やポスターのフレームサイズ情報がまだ利用できないためです。

### 内在的な幅と高さについて

ユーザーエージェントは、この要素のメディアの内在的な幅と高さを、このメディアの幅と高さの生のピクセル数から計算し始め、以下のような要素を考慮します。

* このメディアのアスペクト比。
* メディアのクリーンアパーチャ（対象とする縦横比に一致する、メディアを中心とした長方形）。
* 対象とする機器の解像度。
* そのメディア形式が要求する他の要素。

要素がレンダリング動画ではなくポスターフレームを表示している場合、ポスターフレームの内在サイズが `<video>` 要素のサイズとみなされます。

 メディアの内在サイズが変更された時点で、要素の `readyState` が `HAVE_NOTHING` でない場合、`resize` イベントが `<video>` 要素に送られます。
 これは、要素がポスターフレームの表示から動画コンテンツの表示に切り替わるときや、表示される動画トラックが変わるときに発生します。

例
-

この例では、`resize` イベントのハンドラーを作成し、`<video>` 要素のサイズをそのコンテンツの内在サイズに一致するように変更します。

```js
let v = document.getElementById("myVideo");

v.addEventListener(
  "resize",
  (ev) => {
    let w = v.videoWidth;
    let h = v.videoHeight;

    if (w && h) {
      v.style.width = w;
      v.style.height = h;
    }
  },
  false,
);
```

 これは `videoWidth` と `videoHeight` の両方が 0 でない場合にのみ変更を適用することに注意してください。
 これにより、寸法についてまだ利用できる真の情報がない場合に、無意味な変更が適用されるのを避けることができます。

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-video-videoheight-dev |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: videoWidth プロパティ - Web API

HTMLVideoElement: videoWidth プロパティ
==================================

`HTMLVideoElement` インターフェイスの **`videoWidth`** プロパティは読み取り専用で、この動画の内在的な幅を CSS ピクセル数で表します。
 単純に言えば、これは自然なサイズでのメディアの幅です。

詳しくは、`HTMLVideoElement.videoHeight` > 内在的な幅と高さについてを参照してください。

値
-

 動画の内在的な幅を CSS のピクセル数で指定する整数値。
 要素の `readyState` が `HTMLMediaElement.HAVE_NOTHING` の場合、このプロパティの値は 0 です。これは、動画やポスターのフレームサイズ情報がまだ利用できないためです。

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-video-videowidth-dev |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLVideoElement: leavepictureinpicture イベント - Web API

HTMLVideoElement: leavepictureinpicture イベント
============================================

`leavepictureinpicture` イベントは、`HTMLVideoElement` がピクチャインピクチャモードを終了することに成功した場合に発行されます。

このイベントはキャンセル不可で、バブリングしません。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("leavepictureinpicture", (event) => {});

onleavepictureinpicture = (event) => {};
```

イベント型
-----

`PictureInPictureEvent` です。`Event` を継承しています。

Event

PictureInPictureEventイベントプロパティ
---------

このインターフェイスには、親である `Event` から継承したプロパティもあります。

例
-

この例は HTMLVideoElement の `leavepictureinpicture` イベントのイベントリスナーを追加し、イベントハンドラーがイベントの発行に反応したときにメッセージを投稿します。

`addEventListener()` を使用した場合:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onExitPip() {
  console.log("Picture-in-Picture mode deactivated!");
}

video.addEventListener("leavepictureinpicture", onExitPip, false);

button.onclick = () => {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  }
};
```

`onleavepictureinpicture` イベントハンドラープロパティを使用した場合:

```js
const video = document.querySelector("#video");
const button = document.querySelector("#button");

function onExitPip() {
  console.log("Picture-in-Picture mode deactivated!");
}

video.onleavepictureinpicture = onExitPip;

button.onclick = () => {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  }
};
```

仕様書
---

| Specification |
| --- |
| Picture-in-Picture # eventdef-htmlvideoelement-leavepictureinpicture |
| Picture-in-Picture # dom-htmlvideoelement-onleavepictureinpicture |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `HTMLVideoElement`
* `Picture-in-Picture API`


ReadableStreamDefaultReader: read() メソッド - Web API

ReadableStreamDefaultReader: read() メソッド
========================================

**`read()`** は `ReadableStreamDefaultReader` インターフェイスのメソッドで、ストリームの内部キュー内の次のチャンクへのアクセスを提供するプロミスを返します。

構文
--

```js
read()
```

### 引数

なし。

### 返値

`Promise` です。ストリームの状態に応じて、結果にて履行または拒否されます。
 ありうる状況ものは次の通りです。

* チャンクが使用可能な場合、プロミスが `{ value: theChunk, done: false }` の形式のオブジェクトで履行されます。
* ストリームが閉じられると、プロミスが `{ value: undefined, done: true }` という形式のオブジェクトで履行されます。
* ストリームがエラーになると、プロミスが関連するエラーでプロミスが拒否されます。
### 例外

`TypeError`

ソースオブジェクトが `ReadableStreamDefaultReader` ではないか、ストリームに所有者がいません。

例
-

### 例 1 - 簡単な例

この例は、基本的な API の使用方法を示していますが、例えば、行の境界で終了しないストリームチャンクなどの複雑な問題には対処しません。

この例では、`stream` は以前に作成したカスタムの `ReadableStream` です。 `getReader()` を使用して作成した `ReadableStreamDefaultReader` を使用して読み取ります（完全なコードについては、単純なランダムストリームの例を参照）。 各チャンクを順番に読み取り、ストリームの読み取りが完了するまで UTF-8 のバイトの配列として UI に出力します。 ストリームの読み取りが完了すると、再帰関数から戻り、ストリーム全体を UI の別の部分に出力します。

```js
function fetchStream() {
  const reader = stream.getReader();
  let charsReceived = 0;

  // read() は、値を受け取ったときに解決する promise を返します
  reader.read().then(function processText({ done, value }) {
    // 結果オブジェクトには2つのプロパティが含まれます
    // done - ストリームがすべてのデータを既に提供している場合は true
    // value - 一部のデータ。 done が true の場合、常に undefined
    if (done) {
      console.log("Stream complete");
      para.textContent = result;
      return;
    }

    // フェッチしたストリームの値は Uint8Array です
    charsReceived += value.length;
    const chunk = value;
    let listItem = document.createElement("li");
    listItem.textContent = `Received ${charsReceived} characters so far. Current chunk = ${chunk}`;
    list2.appendChild(listItem);

    result += chunk;

    // さらに読み、この関数を再度呼び出します
    return reader.read().then(processText);
  });
}
```

### 例 2 - テキストを 1 行ずつ処理する

この例は、テキストファイルをフェッチし、テキスト行のストリームとして処理する方法を示しています。 行の境界で終了せず、`Uint8Array` から文字列に変換するストリームチャンクを処理します。

```js
async function\* makeTextFileLineIterator(fileURL) {
  const utf8Decoder = new TextDecoder("utf-8");
  let response = await fetch(fileURL);
  let reader = response.body.getReader();
  let { value: chunk, done: readerDone } = await reader.read();
  chunk = chunk ? utf8Decoder.decode(chunk, { stream: true }) : "";

  let re = /\r\n|\n|\r/gm;
  let startIndex = 0;

  for (;;) {
    let result = re.exec(chunk);
    if (!result) {
      if (readerDone) {
        break;
      }
      let remainder = chunk.substr(startIndex);
      ({ value: chunk, done: readerDone } = await reader.read());
      chunk =
        remainder + (chunk ? utf8Decoder.decode(chunk, { stream: true }) : "");
      startIndex = re.lastIndex = 0;
      continue;
    }
    yield chunk.substring(startIndex, result.index);
    startIndex = re.lastIndex;
  }
  if (startIndex < chunk.length) {
    // 最後の行は改行文字で終わっていません
    yield chunk.substr(startIndex);
  }
}

for await (let line of makeTextFileLineIterator(urlOfFile)) {
  processLine(line);
}
```

仕様書
---

| Specification |
| --- |
| Streams Standard # ref-for-default-reader-read① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `ReadableStreamDefaultReader()` コンストラクター
* 読み取り可能なストリームの使用


ReadableStreamDefaultReader: ReadableStreamDefaultReader() コンストラクター - Web API

ReadableStreamDefaultReader: ReadableStreamDefaultReader() コンストラクター
===================================================================

**`ReadableStreamDefaultReader()`** コンストラクターは、`ReadableStreamDefaultReader` オブジェクトのインスタンスを作成して返します。

**メモ:** 通常、このコンストラクターを手動で使用することはありません。 代わりに、`ReadableStream.getReader()` メソッドを使用してください。

構文
--

```js
new ReadableStreamDefaultReader(stream)
```

### 引数

`stream`

読み取り対象となる `ReadableStream`。

### 返値

`ReadableStreamDefaultReader` オブジェクトのインスタンス。

### 例外

`TypeError`

指定された `stream` 引数が `ReadableStream` ではないか、別のリーダーによる読み取りのために既にロックされています。

例
-

次の簡単な例では、`getReader()` を使用して作成した `ReadableStreamDefaultReader` を使用して、以前に作成したカスタムの `ReadableStream` を読み取ります（完全なコードについては、単純なランダムストリームの例を参照）。 各チャンクを順番に読み取り、ストリームの読み取りが完了するまで UI に出力します。 ストリームの読み取りが完了すると、再帰関数から戻り、ストリーム全体を UI の別の部分に出力します。

```js
function fetchStream() {
  const reader = stream.getReader();
  let charsReceived = 0;

  // read() は、値を受け取ったときに解決する promise を返します
  reader.read().then(function processText({ done, value }) {
    // 結果オブジェクトには2つのプロパティが含まれます。
    // done - ストリームがすべてのデータを既に提供している場合は true。
    // value - 一部のデータ。 done が true の場合、常に undefined。
    if (done) {
      console.log("Stream complete");
      para.textContent = result;
      return;
    }

    // フェッチしたストリームの値は Uint8Array です
    charsReceived += value.length;
    const chunk = value;
    let listItem = document.createElement("li");
    listItem.textContent = `Received ${charsReceived} characters so far. Current chunk = ${chunk}`;
    list2.appendChild(listItem);

    result += chunk;

    // さらに読み、この関数を再度呼び出します
    return reader.read().then(processText);
  });
}
```

仕様書
---

| Specification |
| --- |
| Streams Standard # ref-for-default-reader-constructor① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ストリーム API の概念
* 読み取り可能なストリームの使用
* `ReadableStream`
* `ReadableStreamDefaultController`


ReadableStreamDefaultReader: closed プロパティ - Web API

ReadableStreamDefaultReader: closed プロパティ
=========================================

**`closed`** は `ReadableStreamDefaultReader` インターフェイスの読み取り専用プロパティで、ストリームが閉じられた場合、またはリーダーのロックが解除された場合に履行され、ストリームがエラーの場合に拒否されるプロミス (`Promise`) を返します。このプロパティを使用すると、ストリーミング処理の終わりに応答するコードを書くことができます。

値
-

`Promise` です。

例
-

このスニペットでは、以前に作成したリーダーに問い合わせて、ストリームが閉じられているかどうかを確認します。 閉じられるとプロミスが履行され、メッセージをコンソールに出力します。

```js
reader.closed.then(() => {
  console.log("reader closed");
});
```

仕様書
---

| Specification |
| --- |
| Streams Standard # ref-for-generic-reader-closed② |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `ReadableStreamDefaultReader()` コンストラクター
* 読み取り可能なストリームの使用


ReadableStreamDefaultReader: cancel() メソッド - Web API

ReadableStreamDefaultReader: cancel() メソッド
==========================================

**`cancel()`** は `ReadableStreamDefaultReader` インターフェイスのメソッドで、ストリームをキャンセルし、コンシューマーがストリームに興味を失ったことを通知します。 提供された reason 引数は、基になるソースに与えられ、使用する場合もしない場合もあります。

キャンセルは、ストリームを完全に終了し、読み取り待ちのチャンクがキューに入っている場合でも、それ以上データを必要としない場合に使用します。 キャンセルが呼び出された後、そのデータは失われ、ストリームは読み取り不能になります。 これらのチャンクをまだ読み取り、ストリームを完全に取り除くわけではない場合は、 `ReadableStreamDefaultController.close()` を使用します。

**メモ:** リーダーがアクティブな場合、`cancel()` メソッドは、関連付けられたストリームの場合 (`ReadableStream.cancel()`) と同じように振る舞います。

構文
--

```js
cancel()
cancel(reason)
```

### 引数

`reason` 省略可

人間が読むことができるキャンセルの理由です。この値は使われたり使われなかったりします。

### 返値

`Promise` です。 `reason` 引数で指定された値で履行されます。

### 例外

`TypeError`

ソースオブジェクトが `ReadableStreamDefaultReader` ではないか、ストリームに所有者がいません。

例
-

次の簡単な例では、`getReader()` を使用して作成した `ReadableStreamDefaultReader` を使用して、以前に作成したカスタムの `ReadableStream` を読み取ります（このコードは、単純なランダムストリームの例に基づいています）。 各チャンクを順番に読み取り、ストリームの読み取りが完了するまで UI に出力します。 ストリームの読み取りが完了すると、再帰関数から戻り、ストリーム全体を UI の別の部分に出力します。

ストリームが完了したら（`if (done)`）、`reader.cancel()` を実行してストリームをキャンセルし、それ以上使用する必要がないことを通知します。

```js
function fetchStream() {
  const reader = stream.getReader();
  let charsReceived = 0;

  // read() は、値を受け取ったときに解決する promise を返します
  reader.read().then(function processText({ done, value }) {
    // 結果オブジェクトには2つのプロパティが含まれます
    // done - ストリームがすべてのデータを既に提供している場合は true
    // value - 一部のデータ。 done が true の場合、常に undefined
    if (done) {
      console.log("Stream complete");
      reader.cancel();
      para.textContent = result;
      return;
    }

    // フェッチしたストリームの値は Uint8Array です
    charsReceived += value.length;
    const chunk = value;
    let listItem = document.createElement("li");
    listItem.textContent = `Received ${charsReceived} characters so far. Current chunk = ${chunk}`;
    list2.appendChild(listItem);

    result += chunk;

    // さらに読み、この関数を再度呼び出します
    return reader.read().then(processText);
  });
}
```

仕様書
---

| Specification |
| --- |
| Streams Standard # ref-for-generic-reader-cancel② |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `ReadableStreamDefaultReader()` コンストラクター
* 読み取り可能なストリームの使用


ReadableStreamDefaultReader: releaseLock() メソッド - Web API

ReadableStreamDefaultReader: releaseLock() メソッド
===============================================

**`releaseLock()`** は `ReadableStreamDefaultReader` インターフェイスのメソッドで、ストリームのリーダーのロックを解除します。

ロックを解除したときに関連するストリームにエラーが発生した場合、リーダーはその後同様にエラーが発生したようになります。 そうでない場合、リーダーは閉じた状態になります。

リーダーのロックは、保留中の読み取りリクエストが残っている間、つまり、リーダーの `ReadableStreamDefaultReader.read()` メソッドによって返されたプロミスが終了していない場合、解除できません。 これにより、`TypeError` が発生します。

構文
--

```js
releaseLock()
```

### 引数

なし。

### 返値

なし (`undefined`)。

### 例外

`TypeError`

ソースオブジェクトが `ReadableStreamDefaultReader` でないか、読み取り要求が保留中です。

例
-

```js
function fetchStream() {
  const reader = stream.getReader();

  // ...

  reader.releaseLock();

  // ...
}
```

仕様書
---

| Specification |
| --- |
| Streams Standard # ref-for-default-reader-release-lock② |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `ReadableStreamDefaultReader()` コンストラクター
* 読み取り可能なストリームの使用


AudioContext: createMediaStreamSource() メソッド - Web API

AudioContext: createMediaStreamSource() メソッド
============================================

`createMediaStreamSource()` は `AudioContext` インターフェイスのメソッドで、指定のメディアストリームから（言い換えると `navigator.getUserMedia` インスタンスから） `MediaStreamAudioSourceNode` オブジェクトを生成します。ここからの音声は再生や編集ができます。

メディアストリームの音声ソースノードの詳細は`MediaStreamAudioSourceNode`のページを参照してください。

構文
--

```js
createMediaStreamSource(stream)
```

### 引数

`stream`

操作のために音声グラフに加えたい `MediaStream` オブジェクト。

### 返値

指定したソースストリームから取得したメディアを持つ音声ノードを表す新しい `MediaStreamAudioSourceNode` オブジェクトです。

例
-

この例では、メディア（音声＋映像）ストリームを `navigator.getUserMedia` から獲得し、それを `<video>` 要素に渡し、映像は再生しますが音声は再生しないようにします。音声は `MediaStreamAudioSourceNode` に渡します。次に、音声をローパスフィルター `BiquadFilterNode` (en-US) （低音を強めるように働きます）に渡し、そして `AudioDestinationNode` に渡します。

`<video>` 要素の下のスライダーはローパスフィルターの増幅量を操作します—スライダーで値を大きくすると、より低音が強くなります。

**メモ:** この例の実行とソースの閲覧もできます。

```js
const pre = document.querySelector("pre");
const video = document.querySelector("video");
const myScript = document.querySelector("script");
const range = document.querySelector("input");

// getUserMediaのブロック - ストリームを得る
// MediaStreamAudioSourceNodeに渡す
// 映像はvideo要素に出力する

if (navigator.mediaDevices) {
  console.log("getUserMedia supported.");
  navigator.mediaDevices
    .getUserMedia({ audio: true, video: true })
    .then((stream) => {
      video.srcObject = stream;
      video.onloadedmetadata = (e) => {
        video.play();
        video.muted = true;
      };

      // MediaStreamAudioSourceNode を生成し、
      // それに HTMLMediaElement を渡す
      const audioCtx = new AudioContext();
      const source = audioCtx.createMediaStreamSource(stream);

      // 二次フィルターを生成する
      const biquadFilter = audioCtx.createBiquadFilter();
      biquadFilter.type = "lowshelf";
      biquadFilter.frequency.value = 1000;
      biquadFilter.gain.value = range.value;

      // AudioBufferSourceNode を gainNode に、
      // そして gainNode を destination に接続する
      // これでマウスを動かすことで音楽のボリュームを調整することができる
      source.connect(biquadFilter);
      biquadFilter.connect(audioCtx.destination);

      // マウスが動いたとき新しい座標を得る
      // そして増幅量を更新する

      range.oninput = () => {
        biquadFilter.gain.value = range.value;
      };
    })
    .catch((err) => {
      console.log(`The following gUM error occurred: ${err}`);
    });
} else {
  console.log("getUserMedia not supported on your browser!");
}

// pre 要素にスクリプトを書き出す

pre.innerHTML = myScript.innerHTML;
```

**メモ:** `createMediaStreamSource()` を呼び出した結果、メディアストリームからの音声再生は `AudioContext` の処理グラフに再ルーティングされます。そのため、ストリームの再生/一時停止は、メディア要素 API とプレーヤーコントロールを通して行うことができます。

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-createmediastreamsource |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用


AudioContext: sinkchange イベント - Web API

AudioContext: sinkchange イベント
=============================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

`AudioContext` インターフェイスの **`sinkchange`** イベントは、出力音声デバイスが変更された (そしてその結果 `AudioContext.sinkId` が変更された) 時発火します。

構文
--

`addEventListener()` のようなメソッドでイベント名を用いるか、イベントハンドラープロパティを設定します。

```js
addEventListener("sinkchange", (event) => {});

onsinkchange = (event) => {};
```

イベント型
-----

`Event` です。

例
-

`sinkchange` イベントのリスナーは、音声出力デバイスの変更を報告するのに利用できます。`sinkId` に `AudioSinkInfo` オブジェクトが入っている場合、音声がどの出力デバイスでも再生されないようになったことを表すことに注意してください。

```js
audioCtx.addEventListener("sinkchange", () => {
  if (typeof audioCtx.sinkId === "object" && audioCtx.sinkId.type === "none") {
    console.log("音声がどのデバイスでも再生されなくなりました");
  } else {
    console.log(`音声出力デバイスが ${audioCtx.sinkId} に変更されました`);
  }
});
```

動くコードは、SetSinkId test example を参照してください。

仕様書
---

| Specification |
| --- |
| Web Audio API # eventdef-audiocontext-sinkchange |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* SetSinkId test example
* Change the destination output device in Web Audio
* `AudioContext.setSinkId()`
* `AudioContext.sinkId`


AudioContext: AudioContext() コンストラクター - Web API

AudioContext: AudioContext() コンストラクター
=====================================

**`AudioContext()`** コンストラクターは新しい `AudioContext` オブジェクトを生成します。このオブジェクトは音声モジュールが相互に接続された音声処理のグラフを表現しています。このグラフ中で用いられる音声モジュールは `AudioNode` として表現されます。

構文
--

```js
new AudioContext()
new AudioContext(options)
```

### 引数

`options` 省略可

コンテキストを設定するために使用するオブジェクト。利用できるプロパティは以下のとおりです。

`latencyHint` 省略可

 コンテキストを使用する再生の種類。定義済みの文字列（`"balanced"`、`"interactive"`、`"playback"`）、またはコンテキストの推奨する最大レイテンシーを秒単位で示す倍精度浮動小数点数値です。
 ユーザーエージェントは、このリクエストに応じても応じなくても構いません。
 コンテキストを作成した後、 `AudioContext.baseLatency` の値を調べて真のレイテンシーを決定します。

* `"balanced"`: ブラウザーはレイテンシー値を選択する際、音声出力のレイテンシーと消費電力のバランスをとります。
* `"interactive"` （既定値）: 音声は、ユーザー操作に反応したり、動画やゲームのアクションなどの視覚的な合図に合わせる必要があるなど、インタラクティブな要素に関与します。
 ブラウザーは音声にグリッチを発生させない使用可能な最低のレイテンシーを選択します。これは消費電力の増加を要求される可能性があります。
* `"playback"`: ブラウザーは、レイテンシーを犠牲にして消費電力を最小限に抑え、再生時間を最大化するレイテンシーを選択します。
 音楽再生など、操作を必要としない再生に有益な機能です。

`sampleRate` 省略可

 新しいコンテキストに使用するサンプリングレートを示します。この値は、新しいコンテキストを構成するサンプリングレートを示す浮動小数点数で、 1 秒あたりのサンプル数でなければなりません。
 また、 `AudioBuffer.sampleRate` で対応している値でなければなりません。
 値は通常 8,000Hz から 96,000Hz の間で、既定値は出力機器によって異なりますが、サンプリングレート 44,100Hz が最も一般的です。
 もし `sampleRate` プロパティがオプションに含まれていなかったり、音声コンテキストを作成するときにオプションが指定されていなかったりした場合 は、新しいコンテキストの出力機器が推奨するサンプリングレートが既定で使用されます。

`sinkId` 省略可
Experimental

`AudioContext` に使用するオーディオ出力機器のシンク ID を指定します。これは以下の値のうちの一つを取ります。

* シンク ID を表す文字列です。これは例えば、 `MediaDevices.enumerateDevices()` が返す `MediaDeviceInfo` オブジェクトの `deviceId` プロパティから取得したものです。
* シンク ID を表す文字列です。シンク ID を表す文字列です。

### 返値

新しい `AudioContext` インスタンスです。

### 例外

`NotSupportedError` `DOMException`

指定した `sampleRate` がコンテキストで対応していない場合に発生します。

使用上の注意
------

仕様書では、ユーザーエージェントが対応すべき音声コンテキストの数や、レイテンシの最小・最大要件（もしあれば）などについてあまり詳しく説明していないため、これらの詳細はブラウザーによって異なる可能性があります。重要であれば、必ず値を調べてください。

特に、仕様書では同時に開くための音声コンテキストの最大数や最小数を示していないため、これはブラウザーの実装に任せられています。

### Google Chrome

#### Chrome におけるタブごとの音声コンテキストの制約

バージョン 66 以前の Google Chrome では、 1 つのタブにつき最大 6 つの音声コンテキストにしか対応していませんでした。

#### Chrome での標準外の例外

`latencyHint` プロパティの値が有効でない場合、Chrome は "The provided value '...' is not a valid enum value of type AudioContextLatencyCategory" というメッセージと共に `TypeError` 例外を発生します。

例
-

この例では、インタラクティブ音声用の新しい `AudioContext` を作成し（遅延を最適化）、サンプルレートを 44.1kHz、音声出力を固有のものにします。

```js
const audioCtx = new AudioContext({
  latencyHint: "interactive",
  sampleRate: 44100,
  sinkId: "bb04fea9a8318c96de0bd...", // truncated for brevity
});
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-audiocontext |

ブラウザー互換性
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `new OfflineAudioContext()` コンストラクター


AudioContext: resume() メソッド - Web API

AudioContext: resume() メソッド
===========================

**`resume()`** は `AudioContext` インターフェイスのメソッドで、一時停止された音声コンテキストの時間の流れを再開します。

`OfflineAudioContext` でこのメソッドを呼び出すと、 `INVALID_STATE_ERR` 例外が発生します。

構文
--

```js
resume()
```

### 引数

なし。

### 返値

コンテキストが再開されたときに解決する `Promise` です。このプロミスは、コンテキストが既に閉じている場合は拒否されます。

例
-

次のスニペットは AudioContext states のデモ（ライブ実行）から取ったものです。suspend/resume ボタンをクリックすると、`BaseAudioContext.state` を問い合わせます。もし `running` ならば、 `suspend()` が呼び出されます。 `suspended` ならば、 `resume()` が呼ばれます。両方ともプロミスが解決すると、ボタンのラベルが適切なものに更新されます。

```js
susresBtn.onclick = () => {
  if (audioCtx.state === "running") {
    audioCtx.suspend().then(() => {
      susresBtn.textContent = "Resume context";
    });
  } else if (audioCtx.state === "suspended") {
    audioCtx.resume().then(() => {
      susresBtn.textContent = "Suspend context";
    });
  }
};
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-resume |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用
* ウェブオーディオ API


AudioContext: close() メソッド - Web API

AudioContext: close() メソッド
==========================

`close()` は `AudioContext` インターフェイスのメソッドで、音声コンテキストを閉じて使っていたシステムの音声リソースを全て解放します。

この関数は、他の参照も同様に解放されない限り、 `AudioContext` が生成したオブジェクトは自動的には解放しません。しかし、これは音声リソースを強制的に解放します。よって、音声コンテキストの更なる生成と使用はできなくなり、音声コンテキストの時間の流れは止まり、音声データの処理は停止します。 `AudioContext` の生成をブロックするリソースがすべて解放されたとき、返された `Promise` が解決します。このメソッドは `OfflineAudioContext` で呼ばれたとき `INVALID_STATE_ERR` 例外が発生します。

構文
--

```js
close()
```

### 引数

なし。

### 返値

`undefined` で解決する `Promise` です。

例
-

次のスニペットは AudioContext states デモ（すぐ実行）から取ったものです。stop ボタンをクリックすると、 `close()` が呼び出されます。プロミスに成功すると、リセットされ最初の状態に戻ります。

```js
stopBtn.onclick = () => {
  audioCtx.close().then(() => {
    startBtn.removeAttribute("disabled");
    susresBtn.setAttribute("disabled", "disabled");
    stopBtn.setAttribute("disabled", "disabled");
  });
};
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-close |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用
* ウェブオーディオ API


AudioContext: suspend() メソッド - Web API

AudioContext: suspend() メソッド
============================

`suspend()` は `AudioContext` インターフェイスのメソッドで、音声コンテキストの時間の流れを一時停止します。音声ハードウェアへのアクセスを一時的に停止し、処理に必要だった CPU/バッテリーの使用を減らすことが出来ます。これは、アプリケーションがしばらくの間音声を扱わない間に、音声ハードウェアに電源を供給しないようにしたいときに便利です。

`OfflineAudioContext` でこのメソッドを呼び出すと、 `INVALID_STATE_ERR` 例外が発生します。

構文
--

```js
suspend()
```

### 引数

なし。

### 返値

`Promise` であり、これは `undefined` で解決します。コンテキストが既に閉じている場合、プロミスは失敗します。

例
-

次のスニペットは AudioContext states デモ（ライブ実行）から取ったものです。suspend/resume ボタンをクリックすると、 `AudioContext.state` を問い合わせます。もし `running` ならば、 `suspend()` が呼び出されます。 `suspended` ならば、 `resume()` が呼び出されます。両方ともプロミスに成功するとボタンのラベルが適したものに更新されます。

```js
susresBtn.onclick = () => {
  if (audioCtx.state === "running") {
    audioCtx.suspend().then(() => {
      susresBtn.textContent = "Resume context";
    });
  } else if (audioCtx.state === "suspended") {
    audioCtx.resume().then(() => {
      susresBtn.textContent = "Suspend context";
    });
  }
};
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-suspend |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用
* ウェブオーディオ API


AudioContext: createMediaStreamDestination() メソッド - Web API

AudioContext: createMediaStreamDestination() メソッド
=================================================

`createMediaStreamDestination()` は `AudioContext` インターフェイスのメソッドで、 WebRTC の `MediaStream` と関連付けられた `MediaStreamAudioDestinationNode` オブジェクトを生成します。この MediaStream はローカルファイルに格納されたり他のコンピューターに送信されたりする音声ストリームを表します。

`MediaStream` はノードが生成されたときに作成され、`MediaStreamAudioDestinationNode`の `stream` プロパティを通じてアクセスすることができます。このストリームは `navigator.getUserMedia` で得られた `MediaStream` と同じような使い方ができます。例えば、`RTCPeerConnection` インターフェイスの `addStream()` メソッドでリモートの端末に送ることができます。

詳細は `MediaStreamAudioDestinationNode` のページを参照してください。

構文
--

```js
createMediaStreamDestination()
```

### 引数

なし。

### 返値

`MediaStreamAudioDestinationNode` です。

例
-

次の簡単な例では、`MediaStreamAudioDestinationNode` と `OscillatorNode` と `MediaRecorder` (そのため現時点では、このサンプルは Firefox と Chrome でしか動作しません) を作成します。`MediaRecorder` は `MediaStreamDestinationNode` からの情報を記録するように設定されています。

ボタンをクリックするとオシレーター（振動子）が開始し、`MediaRecorder` も開始します。再びボタンを押して止めると、オシレーターと `MediaRecorder` の両方が停止します。`MediaRecorder` が停止すると `dataavailable` イベントが発火され、イベントデータが `chunks`配列にプッシュされます。その後、`stop` イベントが発火すると、新しい `blob` が opus タイプで作られます—そこには `chunks`配列のデータが書き込まれていて、その blob の URL を指す新しいウィンドウ（タブ）が開きます。

そこで opus ファイルの再生と保存ができます。

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>createMediaStreamDestination() demo</title>
  </head>
  <body>
    <h1>createMediaStreamDestination() demo</h1>

    <p>Encoding a pure sine wave to an Opus file</p>
    <button>Make sine wave</button>
    <audio controls></audio>
    <script>
 const b = document.querySelector("button");
 let clicked = false;
 const chunks = [];
 const ac = new AudioContext();
 const osc = ac.createOscillator();
 const dest = ac.createMediaStreamDestination();
 const mediaRecorder = new MediaRecorder(dest.stream);
 osc.connect(dest);

 b.addEventListener("click", (e) => {
 if (!clicked) {
 mediaRecorder.start();
 osc.start(0);
 e.target.textContent = "Stop recording";
 clicked = true;
 } else {
 mediaRecorder.stop();
 osc.stop(0);
 e.target.disabled = true;
 }
 });

 mediaRecorder.ondataavailable = (evt) => {
 // それぞれのチャンク (blob) を配列に入れる
 chunks.push(evt.data);
 };

 mediaRecorder.onstop = (evt) => {
 // blob を作成し開く
 const blob = new Blob(chunks, { type: "audio/ogg; codecs=opus" });
 document.querySelector("audio").src = URL.createObjectURL(blob);
 };
 </script>
  </body>
</html>
```

**メモ:** Github で実際に動作する例を閲覧したり、ソースコードを読むことができます。

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-createmediastreamdestination |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用


AudioContext: createMediaStreamTrackSource() メソッド - Web API

AudioContext: createMediaStreamTrackSource() メソッド
=================================================

**`createMediaStreamTrackSource()`** は `AudioContext` インターフェイスのメソッドで、指定された `MediaStreamTrack` からデータを受け取る音源を表す `MediaStreamTrackAudioSourceNode` を作成して返します。

このメソッドが `createMediaStreamSource()` と異なる点は、指定された `MediaStream` の中の `id` が辞書順（アルファベット順）で最初の音声トラックからデータを受け取る `MediaStreamAudioSourceNode` を作成する点です。

構文
--

```js
createMediaStreamTrackSource(track)
```

### 引数

`track`

新しいノードのすべての音声データの取得元として使用する `MediaStreamTrack` です。

### 返値

指定の音声トラックから得られる音声データの取得元として働く `MediaStreamTrackAudioSourceNode` オブジェクトを返します。

例
-

この例では、ユーザーのマイクへのアクセスを要求するために `getUserMedia()` を使います。アクセスができるようになると、音声コンテキストを作成し、`getUserMedia()` が返したストリームの最初の音声トラックから音声を取得する `MediaStreamTrackAudioSourceNode` を `createMediaStreamTrackSource()` により作成します。

そして、`createBiquadFilter()` により `BiquadFilterNode` (en-US) を作成し、音源から流れてくる音声にローシェルフフィルターを適用するように意図通り設定します。すると、マイクからの出力が新しいバイクワッドフィルターに流れ、フィルターの出力が音声コンテキストの出力先 (`destination`) に順に流れるようになります。

```js
navigator.mediaDevices
  .getUserMedia({ audio: true, video: false })
  .then((stream) => {
    audio.srcObject = stream;
    audio.onloadedmetadata = (e) => {
      audio.play();
      audio.muted = true;
    };

    const audioCtx = new AudioContext();
    const audioTracks = stream.getAudioTracks();
    const source = audioCtx.createMediaStreamTrackSource(audioTracks[0]);

    const biquadFilter = audioCtx.createBiquadFilter();
    biquadFilter.type = "lowshelf";
    biquadFilter.frequency.value = 3000;
    biquadFilter.gain.value = 20;

    source.connect(biquadFilter);
    biquadFilter.connect(audioCtx.destination);
  })
  .catch((err) => {
    // getUserMedia() のエラーを処理する
  });
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-createmediastreamtracksource |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API
* ウェブオーディオ API の使用
* `MediaStreamTrackAudioSourceNode`


AudioContext: outputLatency プロパティ - Web API

AudioContext: outputLatency プロパティ
=================================

**`outputLatency`** は `AudioContext` の読み取り専用プロパティで、現在の音声コンテキストにおける出力遅延の見積を提供します。

この値は、ブラウザーが音声バッファーを再生のために音声グラフからホストシステムの音声サブシステムに渡してから、バッファー内の最初のサンプルが実際に音声出力デバイスで処理されるまでの秒数です。

この値は、プラットフォームおよび利用可能なハードウェアによって変わります。

値
-

出力遅延の秒数を表す double 値です。

例
-

```js
const audioCtx = new AudioContext();
console.log(audioCtx.outputLatency);
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-outputlatency |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用
* ウェブオーディオ API


AudioContext: getOutputTimestamp() メソッド - Web API

AudioContext: getOutputTimestamp() メソッド
=======================================

**`getOutputTimestamp()`** は `AudioContext` インターフェイスのメソッドで、現在の音声コンテキストに関係する 2 つの音声タイムスタンプが格納された新しい `AudioTimestamp` オブジェクトを返します。

2 つの値とは、以下のものです。

* `AudioTimestamp.contextTime`: コンテキストの `AudioContext.currentTime` で用いられるのと同じ単位と始点の、現在音声出力デバイスで出力されているサンプルフレームの時刻（すなわち、出力音声ストリームの位置）です。
 基本的には、これは音声コンテキストが最初に作られてからの時間です。
* `AudioTimestamp.performanceTime`: `performance.now()` で用いられるのと同じ単位と始点の、`contextTime` の値に対応するサンプルフレームが音声出力デバイスで出力される時刻の推定値です。これは、音声コンテキストを含む文章が最初に描画されてからの時間です。
構文
--

```js
getOutputTimestamp()
```

### 引数

なし

### 返値

`AudioTimestamp` オブジェクトです。このオブジェクトは以下のプロパティを持ちます。

* `contextTime`: `BaseAudioContext` の `currentTime` で用いられる時間座標系上の点で、音声コンテキストが最初に作られてからの時間です。
* `performanceTime`: `Performance` インターフェイスで用いられる時間座標系上の点で、音声コンテキストを含む文章が最初に描画されてからの時間です。
例
-

以下のコードでは、play ボタンが押されると音声ファイルの再生を開始し、`requestAnimationFrame` によるループを開始します。このループでは、継続して `contextTime` と `performanceTime` を出力します。

この例のコード全体は output-timestamp で見ることができます。(動く例を見る)

```js
// play ボタンを押す
playBtn.addEventListener("click", () => {
  // ユーザーの操作があったので、audioCtx を作ることができる
  if (!audioCtx) {
    audioCtx = new AudioContext();
  }
  source = new AudioBufferSourceNode(audioCtx);
  getData();
  source.start(0);
  playBtn.disabled = true;
  stopBtn.disabled = false;
  rAF = requestAnimationFrame(outputTimestamps);
});

// stop ボタンを押す
stopBtn.addEventListener("click", () => {
  source.stop(0);
  playBtn.disabled = false;
  stopBtn.disabled = true;
  cancelAnimationFrame(rAF);
});

// タイムスタンプ出力用の補助関数
function outputTimestamps() {
  const ts = audioCtx.getOutputTimestamp();
  output.textContent = `Context time: ${ts.contextTime} | Performance time: ${ts.performanceTime}`;
  rAF = requestAnimationFrame(outputTimestamps); // 自身を再登録する
}
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-getoutputtimestamp |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioContext: setSinkId() メソッド - Web API

AudioContext: setSinkId() メソッド
==============================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`setSinkId()`** は `AudioContext` インターフェイスのメソッドで、`AudioContext` の音声出力機器を設定します。sink ID が明示的に設定されていない場合は、既定のシステム音声出力機器が使われます。

音声機器を既定でない機器に設定するには、開発者は音声機器にアクセスする許可を得る必要があります。必要な場合、`MediaDevices.getUserMedia()` を呼ぶことによりユーザーに必要な許可を求めるプロンプトを表示することができます。

さらに、この機能は `speaker-selection` (en-US) 権限ポリシー によりブロックされる場合があります。

構文
--

```js
setSinkId(sinkId)
```

### 引数

`sinkId`

出力音声機器として設定する機器のシンク ID です。以下の型のいずれかです。

文字列

シンク ID を表す文字列です。たとえば、`MediaDevices.enumerateDevices()` が返す `MediaDeviceInfo` オブジェクトの `deviceId` プロパティで取得できます。

`AudioSinkOptions`

シンク ID の様々なオプションを表すオブジェクトです。現在、これは 1 個のプロパティ `type` を取り、その値は `none` です。この値を設定すると、音声を音声出力機器で再生せずに処理させることができます。これは、処理と並行して再生する必要がないときにエネルギーの消費を最小化するのに有用なオプションです。

### 返値

`undefined` の値で解決する `Promise` を返します。

シンク ID を既存の値（すなわち、`AudioContext.sinkId` が返す値）に設定しようとすると、エラーは発生しませんが、処理がすぐに停止します。

### 例外

`InvalidAccessError` `DOMException`

選択された音声出力機器へのアクセスに失敗したとき発生します。

`NotAllowedError` `DOMException`

ブラウザーに音声機器にアクセスする許可がないとき発生します。

`NotFoundError` `DOMException`

渡された `sinkId` がシステムで検出されたどの音声機器にも一致しないとき発生します。

例
-

SetSinkId test example (ソースコードを見る) では、`AudioBufferSourceNode` により 3 秒間のホワイトノイズを生成し、`GainNode` に通して少し音量を下げる音声グラフを作成します。

さらに、音声出力機器をその場で変えることができるドロップダウンメニューを用意します。そのために、

1. ドロップダウンメニューに配置するボタンを用意します。まず、`MediaDevices.getUserMedia()` を呼び、機器を列挙するために必要な許可を得るためのプロンプトを開きます。次に、`MediaDevices.enumerateDevices()` を用いてすべての利用可能な機器を取得します。ループにより、各機器を `<select>` 要素の選択肢として利用可能にします。さらに、音声をどの出力でも再生したくないときのために選択肢「None」を作成します。

```js
mediaDeviceBtn.addEventListener('click', async () => {
  if ("setSinkId" in AudioContext.prototype) {
    selectDiv.innerHTML = '';

    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    const devices = await navigator.mediaDevices.enumerateDevices();

    // 簡潔にするため、ドロップダウン作成のためのほとんどの DOM 関係のスクリプトは省略

    const audioOutputs = devices.filter(
       (device) => device.kind === 'audiooutput' && device.deviceId !== 'default'
    );

    audioOutputs.forEach((device) => {
      const option = document.createElement('option')
      option.value = device.deviceId;
      option.textContent = device.label;
      select.appendChild(option);
    });

    const option = document.createElement('option')
    option.value = 'none';
    option.textContent = 'None';
    select.appendChild(option);

    //...
```

2. `<select>` 要素に `change` イベントリスナーを追加し、新しい値が選択された時にシンク ID を変更して音声出力機器を変更できるようにします。ドロップダウンで「None」が選択された場合は `{ type : 'none' }` オブジェクトを引数として `setSinkId()` を呼ぶことにより音声機器が選択されていない状態にし、それ以外の場合は `<select>` 要素の `value` 属性に格納された音声機器 ID を引数として呼びます。

```js
    // ...

    select.addEventListener('change', async () => {
      if(select.value === 'none') {
        await audioCtx.setSinkId({ type : 'none' });
      } else {
        await audioCtx.setSinkId(select.value);
      }
    })
  }
});
```

出力機器の変更は音声の再生中にも、再生前にも、再生と再生の間にもできます。

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-setsinkid |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* SetSinkId test example
* Change the destination output device in Web Audio
* `AudioContext.sinkId`
* `sinkchange`


AudioContext: createMediaElementSource() メソッド - Web API

AudioContext: createMediaElementSource() メソッド
=============================================

`createMediaElementSource()` は `AudioContext` インターフェイスのメソッドで、新しい `MediaElementAudioSourceNode` オブジェクトを作成するために使用されます。 HTML 内に存在する`<audio>` または `<video>` を指定すると、その音声を再生し、操作することができます。

メディア要素の音声ソースノードについての詳細は、 `MediaElementAudioSourceNode` を参照して下さい。

構文
--

```js
createMediaElementSource(myMediaElement)
```

### 引数

`myMediaElement`

音声処理グラフに与えて操作したい `HTMLMediaElement` オブジェクトです。

### 返値

`MediaElementAudioSourceNode` です。

例
-

以下の例では、 `createMediaElementSource()` を使用して `<audio>` から音源を作成します。再生される音源は `GainNode` を介し `AudioDestinationNode` に渡されます。マウスポインターが動くと `updatePage()` 関数が呼ばれ、マウスポインターの Y 座標の値をウィンドウの高さで割った比率を元に現在のゲインを計算します。また、マウスポインターを上下に動かすことで、再生している音楽の音量を上げ下げできます。

**メモ:** ライブで実行する例と、ソースを見ることができます。

```js
const audioCtx = new AudioContext();
const myAudio = document.querySelector("audio");

// MediaElementAudioSourceNodeを作成
// HTMLMediaElementをそこへ接続
const source = audioCtx.createMediaElementSource(myAudio);

// ゲインノードを作成
const gainNode = audioCtx.createGain();

// マウスポインターの Y 座標と
// 画面の高さを保持するための変数を作成
let curY;
const HEIGHT = window.innerHeight;

// マウスが動いたら新しいY座標を取得し、
// ゲインの値を設定する
document.onmousemove = updatePage;

function updatePage(e) {
  curY = e.pageY;
  gainNode.gain.value = curY / HEIGHT;
}

// AudioBufferSourceNode を gainNode へ接続
// gainNode を destination へ接続
// これで音楽の再生と、マウスカーソルで音量を調節できるようになる
source.connect(gainNode);
gainNode.connect(audioCtx.destination);
```

**メモ:** `createMediaElementSource()`を呼び出した結果、 `HTMLMediaElement` からの音声再生は AudioContext の処理グラフに再ルーティングされます。そのため、メディアの再生/一時停止は、メディア要素 API とプレーヤコントロールを通して行うことができます。

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-createmediaelementsource |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用


AudioContext: baseLatency プロパティ - Web API

AudioContext: baseLatency プロパティ
===============================

**`baseLatency`** は `AudioContext` インターフェイスの読み取り専用プロパティで、`AudioDestinationNode` すなわち音声グラフの終端から音声バッファーをホストシステムで再生の準備ができている音声サブシステムに渡すときに発生する処理の遅延の秒数を表す `double` の値を返します。

**メモ:** コンテキストの生成時に `latencyHint` オプションを用いることで特定の遅延を要求することができます。しかし、ブラウザーはこのオプションを無視する可能性があります。

値
-

ベース遅延の秒数を表す `double` の値です。

例
-

```js
// デフォルトの遅延 ("interactive")
const audioCtx1 = new AudioContext();
console.log(audioCtx1.baseLatency); // 0.00

// より大きい遅延 ("playback")
const audioCtx2 = new AudioContext({ latencyHint: "playback" });
console.log(audioCtx2.baseLatency); // 0.15
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-baselatency |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用
* ウェブオーディオ API


AudioContext: sinkId プロパティ - Web API

AudioContext: sinkId プロパティ
==========================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`sinkId`** は `AudioContext` インターフェイスの読み取り専用プロパティで、現在の音声出力機器のシンク ID を返します。

値
-

このプロパティは、どのようにシンク ID が設定されているかにより、以下の値のいずれかを返します。

空文字列

シンク ID が明示的に設定されていない場合、デフォルトのシステム音声出力機器が用いられ、`sinkId` は空文字列を返します。

文字列

シンク ID が（`setSinkId()` を用いるか、`AudioContext()` コンストラクターのオプション `sinkId` を用いて）文字列として設定されている場合、`sinkId` は同じ文字列を返します。

`AudioSinkInfo` オブジェクト

シンク ID が（`setSinkId()` を用いるか、`AudioContext()` コンストラクターのオプション `sinkId` を用いて）オプションオブジェクトとして設定されている場合、`sinkId` は最初のオプションオブジェクトで設定された値と同じ値を持つ `AudioSinkInfo` オブジェクトを返します。

例
-

SetSinkId test example では、`AudioBufferSourceNode` により 3 秒間のホワイトノイズを生成し、`GainNode` を通して少し音量を下げる音声グラフを作成します。さらに、ユーザーが音声出力機器を変えることができるドロップダウンメニューを提供します。

Play ボタンがクリックされると、音声グラフを組み立て、再生を開始し、`sinkId` の値に基づいて現在の機器の情報を記録します。これは以下のような動作になります。

* 空文字列は、まだ既定の機器が使われていることを表します。
* 値がオブジェクトである場合は、`type: 'none'` が格納されたオプションオブジェクトを設定しているため、音声はどの機器でも再生されません。
* それ以外の場合は、値はシンク ID の文字列のはずなので、記録します。

```js
playBtn.addEventListener("click", () => {
  const source = audioCtx.createBufferSource();
  source.buffer = myArrayBuffer;
  source.connect(gain);
  gain.connect(audioCtx.destination);
  source.start();

  if (audioCtx.sinkId === "") {
    console.log("音声は既定の機器で再生されています");
  } else if (
    typeof audioCtx.sinkId === "object" &&
    audioCtx.sinkId.type === "none"
  ) {
    console.log("音声はどの機器でも再生されていません");
  } else {
    console.log(`音声は機器 ${audioCtx.sinkId} で再生されています`);
  }
});
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audiocontext-sinkid |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* SetSinkId test example
* Change the destination output device in Web Audio
* `AudioContext.setSinkId()`
* `sinkchange`


CSSKeyframesRule.name - Web API

CSSKeyframesRule.name
=====================

**`name`** は `CSSKeyframeRule` インターフェイスのプロパティで、 `animation-name` プロパティで使用されるアニメーションの名前を取得したり設定したりします。

### 値

文字列です。

例
-

 この CSS には keyframes アットルールがあります。これは `document.styleSheets[0].cssRules` で返される最初の `CSSRule` になります。
 `myRules[0]` は `CSSKeyframesRule` オブジェクトを返し、 `name` は "slidein" に設定されます。

```css
@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}
```

```js
let myRules = document.styleSheets[0].cssRules;
let keyframes = myRules[0]; // CSSKeyframesRule
console.log(keyframes.name); // "slidein"
```

仕様書
---

| Specification |
| --- |
| CSS Animations Level 1 # dom-csskeyframesrule-name |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSKeyframesRule: cssRules プロパティ - Web API

CSSKeyframesRule: cssRules プロパティ
================================

**`cssRules`** は `CSSKeyframeRule` インターフェイスの読み取り専用プロパティで、 `CSSRuleList` で keyframes アットルールのルールを返します。

### 値

`CSSRuleList` です。

例
-

 この CSS には keyframes アットルールがあります。これは `document.styleSheets[0].cssRules` で返される最初の `CSSRule` になります。
 `myRules[0]` は `CSSKeyframesRule` オブジェクトを返します。 `cssRules` プロパティは 2 つのルールを含む `CSSRuleList` を返します。

```css
@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}
```

```js
let myRules = document.styleSheets[0].cssRules;
let keyframes = myRules[0]; // CSSKeyframesRule
console.log(keyframes.cssRules); // 2 つのルールを含む CSSRuleList オブジェクト
```

仕様書
---

| Specification |
| --- |
| CSS Animations Level 1 # dom-csskeyframesrule-cssrules |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSKeyframesRule: appendRule() メソッド - Web API

CSSKeyframesRule: appendRule() メソッド
===================================

**`appendRule()`** は `CSSKeyframeRule` インターフェイスのメソッドで、 `CSSKeyFrameRule` をルールの末尾に追加します。

構文
--

```js
appendRule(rule)
```

### 引数

`rule`

keyframe ルールの入った文字列です。

### 返値

なし (`undefined`)。

例
-

 この CSS には keyframes アットルールがあります。これは `document.styleSheets[0].cssRules` で返される最初の `CSSRule` になります。
 `myRules[0]` は `CSSKeyframesRule` オブジェクトを返します。その `cssRules` プロパティは 1 つのルールの入った `CSSRuleList` を返します。

`appendRule` でもう 1 つのルールを追加すると、 `cssRules` プロパティは 2 つのルールが入った `CSSRuleList` を返します。

```css
@keyframes slidein {
  from {
    transform: translateX(0%);
  }
}
```

```js
let myRules = document.styleSheets[0].cssRules;
let keyframes = myRules[0]; // a CSSKeyframesRule
keyframes.appendRule("to {transform: translateX(100%);}");
console.log(keyframes.cssRules); // 2 つのルールが入った CSSRuleList オブジェクト
```

仕様書
---

| Specification |
| --- |
| CSS Animations Level 1 # interface-csskeyframesrule-appendrule |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSKeyframesRule: findRule() メソッド - Web API

CSSKeyframesRule: findRule() メソッド
=================================

**`findRule()`** は `CSSKeyframeRule` インターフェイスのメソッドで、指定されたキーフレームセレクターに一致する `CSSKeyFrameRule` を検索します。

構文
--

```js
findRule(select)
```

### 引数

`select`

見つけるルールのキーフレームセレクターの入った文字列です。次のどちらかになります。

* 0% から 100% までのパーセント値をカンマで区切ったリスト
* または `from` か `to` のキーワード

なお、指定するキーフレームセレクターの値の数と順序は、対象となるキーフレームルールのものと一致していなければなりません。ホワイトスペースは無視されます。

### 返値

最後にルールに一致した `CSSKeyframeRule` を返します。ルールが見つからなかった場合は、何も返されません。

例
-

 この CSS には keyframes アットルールがあります。これは `document.styleSheets[0].cssRules` で返される最初の `CSSRule` になります。
 `myRules[0]` は `CSSKeyframesRule` オブジェクト 1 つを返します。 findRule("to") を呼び出すと、 2 番目のルールを表す `CSSKeyframeRule` が返されます。

```css
@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}
```

```js
let myRules = document.styleSheets[0].cssRules;
let keyframes = myRules[0]; // CSSKeyframesRule
console.log(keyframes.findRule("to")); // CSSKeyframeRule オブジェクト
```

仕様書
---

| Specification |
| --- |
| CSS Animations Level 1 # interface-csskeyframesrule-findrule |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSKeyframesRule: deleteRule() メソッド - Web API

CSSKeyframesRule: deleteRule() メソッド
===================================

**`deleteRule()`** は `CSSKeyframeRule` インターフェイスのメソッドで、指定されたキーフレームセレクターに一致する `CSSKeyFrameRule` を削除します。

構文
--

```js
deleteRule(select)
```

### 引数

`select`

削除するルールのキーフレームセレクターの入った文字列です。次のうちのいずれかを指定します。

* 0% から 100% までのパーセント値をカンマで区切ったリスト
* または `from` か `to` のキーワード

なお、指定するキーフレームセレクターの値の数と順序は、対象となるキーフレームルールのものと一致していなければなりません。ホワイトスペースは無視されます。

### 返値

なし (`undefined`)。

例
-

 この CSS には keyframes アットルールがあります。これは `document.styleSheets[0].cssRules` で返される最初の `CSSRule` になります。
 `myRules[0]` は `CSSKeyframesRule` オブジェクトを返します。 `cssRules` プロパティは
 2 つのルールを持った `CSSRuleList` を返します。

`deleteRule()` でルールを 1 つ削除した後は、 `cssRules` プロパティはルールを 1 つ持った `CSSRuleList` を返します。

```css
@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}
```

```js
let myRules = document.styleSheets[0].cssRules;
let keyframes = myRules[0]; // CSSKeyframesRule
keyframes.deleteRule("to");
console.log(keyframes.cssRules); // 1 つのルールを持った CSSRuleList を返す
```

仕様書
---

| Specification |
| --- |
| CSS Animations Level 1 # dom-csskeyframesrule-deleterule |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


XRInputSource: targetRaySpace プロパティ - Web API

XRInputSource: targetRaySpace プロパティ
===================================

`XRInputSource` の **targetRaySpace`** プロパティは読み取り専用で、仮想空間におけるターゲット光線の位置と方向を表す `XRSpace` (en-US) （通常は `XRReferenceSpace`） を返します。その正の値はターゲット光線の原点の位置を示し、その方向はコントローラー機器自体の方向を示します。これらの値は、入力ソースの `targetRayMode` のコンテキストで解釈され、機器を入力ソースとして完全に解釈するために使用することができます。

仮想空間における入力コントローラーの位置と方向を表す `XRSpace` を取得するには、 `gripSpace` プロパティを使用してください。

値
-

`XRSpace` (en-US) オブジェクト—ふつうは `XRReferenceSpace` または `XRBoundedReferenceSpace` で、仮想空間における入力コントローラーの対象とする光線の位置と方向を表します。

返される `XRSpace` のネイティブの原点は、対象とする光線が射出される点に位置し、空間の方向は対象とする光線が向いている方向を示します。

使用上の注意
------

すべての入力ソースは、 `targetRayMode` に関係なく、有効な `targetRaySpace` を持ちます。しかし、この空間の正確な意味はモードによって異なります。

* すべての視線入力（`targetRayMode` の値が `gaze`）は、視線入力が視聴者の頭から決まりますので、対象とする視線空間として同じ `XRSpace` (en-US) オブジェクトを共有します。この共有空間は `XRSession` (en-US) メソッド `requestReferenceSpace()` が返す空間と同じ場所を表しますが、将来的な API の拡張を可能にするために異なるオブジェクトとして維持されます。
* トラッキングポインター入力（`targetRayMode` が `tracked-pointer` であるもの）によって報告されるターゲット視線空間は、実際には入力機器の正の空間位置と方向に基づいています。

フレームのレンダリング中に対象の光線の位置と方向を決定するには、 `XRFrame` (en-US) の `getPose()` (en-US) メソッドに渡し、返す `XRPose` (en-US) オブジェクトの `transform` (en-US) を使用して、必要な空間情報を収集します。

例
-

このコードでは、1 フレームに 1 回呼び出される関数の一部を示しています。この関数は、`null` ではない `targetRaySpace` を持つ入力を見ていきます。このプロパティに値が示す入力は、ユーザーから外側に対象とする光線を表します。

このような各入力に対して、この例では `targetRayMode` が `tracked-pointer` である入力を見ていきます。これは、その入力が実際には注視デバイス、画面タップ、マウスクリックではなく、ターゲティングデバイスを表すことを意図していることを示しています。トラッキングポインターの場合、関数 `myRenderTargetRayAsBeam()` が呼び出され、入力コントローラーの仮想位置から、ポインタが指している方向にビームをレンダリングします。

このコードは、仮想空間内でユーザーの手の位置を表すコントローラーやオブジェクトを描画したり、他にも入力関連のタスクを実行し続ける必要があります。

```js
function updateInputSources(session, frame, refSpace) {
  for (const source of session.getInputSources()) {
    const targetRayPose = frame.getPose(inputSource.targetRaySpace, refSpace);

    if (targetRayPose) {
      if (source.targetRayMode === "tracked-pointer") {
        myRenderTargetRayAsBeam(targetRayPose);
      }
    }

    // …
  }
}
```

仕様書
---

| Specification |
| --- |
| WebXR Device API # dom-xrinputsource-targetrayspace |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebXR 機器 API
* 入力と入力ソース (en-US)
* WebXR アプリケーションでのゲームパッドの使用


XRInputSource: gripSpace プロパティ - Web API

XRInputSource: gripSpace プロパティ
==============================

`XRInputSource` の **`gripSpace`** 読み取り専用プロパティは、ネイティブの原点がユーザーの手に保持している（またはユーザーの手の一部の）ように見える仮想オブジェクトのレンダリングに使用するポーズを追跡する `XRSpace` (en-US) を返します。 例えば、ユーザーが仮想の真っ直ぐな棒を持っている場合、この `XRSpace` のネイティブの原点は、ユーザーの拳のおおよその重心にあります。

値
-

仮想空間での入力機器の位置と向きを表す `XRSpace` (en-US) オブジェクトです。 機器の画像をシーンにレンダリングするのに適しています。 入力ソースが本質的に追跡できない場合、`gripSpace` は `null` です。 例えば、`targetRayMode` が `tracked-pointer` である入力のみが `gripSpace` を提供します。

コントローラーがまっすぐな棒のような形をしていて、ユーザーの拳で握られていると想像してみてください。 グリップ空間の本来の原点は、ユーザーの拳の重心にあり、ユーザーの手の位置を追跡します。

**左手のグリップ空間の座標系。**

![グリップ空間が、世界に対するプレーヤーの手のローカル座標系をどのように示しているかを示す図。](/ja/docs/Web/API/XRInputSource/gripSpace/gripspace-lefthand-light.svg)

**右手のグリップ空間の座標系。**

![グリップ空間が、世界に対するプレーヤーの手のローカル座標系をどのように示しているかを示す図。](/ja/docs/Web/API/XRInputSource/gripSpace/gripspace-righthand-light.svg)

上の図に示すように、座標系は次のように方向付けられています。

* x 軸は、ユーザーの手のひらに垂直であり、手の甲から外側に伸びる方向は、コントローラーがユーザーの右手にある場合は +X 、コントローラーが左手にある場合は -X です。
* z 軸は、棒の長さに沿い、ユーザーの手のひらに平行で、グリップの長さに沿います。 -Z はユーザーの親指の方向であり、+Z は反対方向です。
* y 軸は、他の 2 つの軸間の関係によって示されます。 いつものように、それは他の 2 つの軸の外積です（X 軸と Z 軸の両方から 90° 離れています）。
例
-

この例では、フレームレンダリングコールバックから取得した `gripSpace` を使用して、仮想環境でのコントローラーの位置と向きを表すメッシュをレンダリングします。

```js
for (const source in xrSession.inputSources) {
  if (source.gripSpace) {
    const gripPose = frame.getPose(source.gripSpace, xrRefSpace);

    if (gripPose) {
      myDrawMeshUsingTransform(controllerMesh, gripPose.transform.matrix);
    }
  }
}
```

このループは、`gripSpace` の値を持つ各入力ソースについて、`gripSpace` によって記述される位置と向きを表す `XRPose` (en-US) を取得します。 有効なポーズが返された場合、メソッド `myDrawMeshUsingTransform()` を呼び出して、グリップポーズの変換行列を使用して変換されたコントローラーのメッシュを描画します。

仕様
--

| Specification |
| --- |
| WebXR Device API # dom-xrinputsource-gripspace |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


XRInputSource: targetRayMode プロパティ - Web API

XRInputSource: targetRayMode プロパティ
==================================

`XRInputSource` の **`targetRayMode`** プロパティは読み取り専用で、入力ソースのターゲット光線を生成する方法と、それをユーザーに提示する方法を示します。

一般的には、ターゲティングシステムのソースから、ユーザーが見ている、または指している方向のターゲット光線に沿って、ターゲット光線が描かれます。光線のスタイルは一般的に自由で、光線の終点を示す方法も自由です。ターゲットとなるポイントやオブジェクトは、図形を描いたり、ターゲットとなる表面やオブジェクトをハイライトすることで示されるかもしれません。

ターゲット光線はハンドコントローラーが影響します。

![ハンドコントローラからターゲット光線を照射している画面](/ja/docs/Web/API/XRInputSource/targetRayMode/example-target-ray.gif)

ターゲット光線は、単純な線（理想的には距離に応じて消えていく）から、上のスクリーンショットにあるような SF の「フェイザー」スタイルのようなアニメーション効果まで、さまざまなものがあります。

値
-

ターゲット光線を生成してユーザーに提示する際に、どの方法を使用するかを示す文字列です。指定できる値は次の通りです。

`gaze` (視線)

ユーザーは、ユーザーが見ている方向を検出する視線追跡システム（または**視線入力**）を使用しています。 ターゲット光線は、ビューアーの目を起点として描画され、ビューアーが見ている方向に追従します。

`screen` (画面)

ターゲット光線の方向は、タッチスクリーン、マウス、またはその他の触覚入力機器をタップして示します。

`tracked-pointer` (追跡ポインター)

ターゲティングは、ユーザーがターゲットの方向に向けるハンドヘルド機器またはハンドトラッキングシステムを使用して行われます。 ターゲット光線は、手 (または手の中のオブジェクト) からターゲット方向に伸びます。方向はプラットフォーム固有のルールを使用して決定されますが、そのようなルールが存在しない場合は、ユーザーが人差し指を手からまっすぐに向けていると仮定して方向が選択されます。

使用上の注意
------

入力ソースの `targetRaySpace` は、ターゲット光線の位置と向きを示し、光線をレンダリングする場所を決定するために使用できます。

例
-

このコードの断片は、フレームごとに 1 回呼び出される関数の一部を示しています。 `null` 以外の `targetRaySpace` を持つ入力を探します。 このプロパティの値を持つ入力は、ターゲット光線をユーザーから外側に投影する入力を表します。

このような入力ごとに、この例では、 `targetRayMode` が `tracked-pointer` である入力を探します。 これは、入力が実際には、視線入力機器、画面タップ、またはマウスクリックではなく、ターゲティング機器を表すことを目的としていることを示しています。 追跡ポインターの場合、関数 `myRenderTargetRayAsBeam()` が呼び出され、入力コントローラーの仮想位置から、それが指している方向に外側にビームをレンダリングします。

コードは、仮想空間でのユーザーの手の位置を表すコントローラーや任意のオブジェクトの描画、その他の入力関連のタスクなどを引き続き実行する必要があります。

```js
function updateInputSources(session, frame, refSpace) {
  for (const source of session.getInputSources()) {
    const targetRayPose = frame.getPose(inputSource.targetRaySpace, refSpace);

    if (targetRayPose) {
      if (source.targetRayMode === "tracked-pointer") {
        myRenderTargetRayAsBeam(targetRayPose);
      }
    }

    // …
  }
}
```

詳細とより完全な例については、入力と入力ソース (en-US)の記事を参照してください。

仕様書
---

| Specification |
| --- |
| WebXR Device API # dom-xrinputsource-targetraymode |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebXR 機器 API
* 入力と入力ソース (en-US)
* WebXR アプリケーションでのゲームパッドの使用


XRInputSource: hand プロパティ - Web API

XRInputSource: hand プロパティ
=========================

**`hand`** は `XRInputSource` インターフェイスの読み取り専用プロパティで、ハンドトラッキング機器へのあくせすを提供する `XRHand` (en-US) オブジェクトです。

値
-

`XRHand` (en-US) オブジェクト、または `XRSession` (en-US) が `hand-tracking` 機能記述子でリクエスト (en-US)されていない場合は `null` です。

例
-

```js
navigator.xr
  .requestSession({ optionalFeatures: ["hand-tracking"] })
  .then(/\* … \*/);

function renderFrame(session, frame) {
  // …

  for (const inputSource of session.inputSources) {
    if (inputSource.hand) {
      // render a hand model, perform gesture detection, etc.
    }
  }
}
```

仕様書
---

| Specification |
| --- |
| WebXR Hand Input Module - Level 1 # dom-xrinputsource-hand |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `XRHand` (en-US)


XRInputSource: handedness プロパティ - Web API

XRInputSource: handedness プロパティ
===============================

`XRInputSource` の **`handedness`** は読み取り専用プロパティで、WebXR 入力ソースがユーザーのどの手に関連付けられているか、またはまったく関連付けられていないかを示します。

値
-

文字列で、入力コントローラーがユーザーの手に握られているかどうか、もしそうならばどちらの手なのかを表します。値は次のうちの一つです。

`none`

入力コントローラーは、ユーザーのいずれの手にも関連付けられていません。

`left`

入力コントローラーは、ユーザーの左手に握られているか、着用されているか、取り付けられています。

`right`

入力コントローラーは、ユーザーの右手に握られているか、着用されているか、取り付けられています。

使用上の注意
------

入力ソースがユーザーの手に関連付けられた機器でない場合（握られているか、取り付けられているか、着用されているかに関係なく）、`handedness` の値は `none` です。 これは、例えば、ヘッドセットに組み込まれたコントロールや、頭や体に取り付けられた入力機器など、手で持つものではない入力ソースを示している場合があります。

例
-

`handedness` の重要な使用方法の 1 つは、コントローラーがどちらの手にあるかを判別して、仮想空間でその手（またはその手が制御している機器）の表現を描画できるようにすることです。

```js
function updateInputSources(session, frame, refSpace) {
  for (const source of session.inputSources) {
    if (source.gripSpace) {
      const gripPose = frame.getPose(source.gripSpace, refSpace);

      if (gripPose) {
        myRenderHandObject(gripPose, inputSource.handedness);
      }
    }
  }
}
```

この関数は、すべてのアニメーションフレームで（または必要な滑らかさの程度とパフォーマンスの制約に応じて定期的に）呼び出され、入力ソースのリストをスキャンして、 `gripSpace` が `null` ではないものを探します。 `gripSpace` が存在する場合、それは入力ソースが何らかのハンドヘルド機器であることを意味するため、可能であれば視覚的にレンダリングする必要があります。

`gripSpace` が `null` 以外の場合、この関数は、現在の参照空間に変換された `gripSpace` のポーズを取得します。 それが有効であると仮定すると、`myRenderHandObject()` と呼ばれる関数が、グリップのポーズと `handedness` の値を使用して呼び出されます。そして、正しい手に配置され形成された適切なモデルを描画します。

仕様書
---

| Specification |
| --- |
| WebXR Device API # dom-xrinputsource-handedness |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebXR 機器 API
* 入力と入力ソース (en-US)
* WebXR アプリケーションでのゲームパッドの使用


XRInputSource: profiles プロパティ - Web API

XRInputSource: profiles プロパティ
=============================

`XRInputSource` の **`profiles`** は読み取り専用プロパティで、文字列の配列を返します。 各文字列は、入力ソースの構成プロファイルを記述します。 プロファイル文字列は、具体性の高い順にリストされ、最も具体的なプロファイルが最初にリストされます。

**メモ:** WebXR セッションがインラインモードの場合、`profiles` リストは常に空です。

値
-

`XRInputSource` オブジェクトが表す入力機器の構成プロファイルをそれぞれ記述した文字列の配列。 各入力プロファイルは、入力ソースの好ましい視覚的表現と振る舞いを指定します。

### 入力プロファイル名

入力プロファイル名は、入力ソースが使用するように構成できる視覚的表現と振る舞いを説明する文字列です。 各文字列は、

* スペースはありません。 代わりに、単語はハイフン（"-"）文字で区切られます。
* プラットフォームがそれを利用可能にする場合、USB のベンダー ID と製品 ID が提供される場合がありますが、信頼することはできません。
* 特定の機器を一意に識別しません。 むしろ、製品が使用できる構成を識別します。
* 該当する場合、機器の handedness に関する情報を提供しません。

WebXR 入力プロファイルレジストリー（WebXR Input Profiles Registry）は、機器開発者とブラウザー開発者が、使用するブラウザーや他のユーザーエージェントに関係なく、特定の機器が同じプロファイル文字列を報告するようにするために使用します。

### 一般的な入力プロファイル名

以下の入力プロファイル名は一般的なもので、機器を最も大まかな意味で記述するフォールバックとして機能します。

* generic-button
* generic-hand-select-grasp
* generic-hand-select
* generic-hand
* generic-touchpad
* generic-touchscreen
* generic-trigger-squeeze-thumbstick
* generic-trigger-squeeze-touchpad-thumbstick
* generic-trigger-squeeze-touchpad
* generic-trigger-squeeze
* generic-trigger-thumbstick
* generic-trigger-touchpad-thumbstick
* generic-trigger-touchpad
* generic-trigger
例
-

profiles` のリストは、詳細度の逆順です。つまり、最も詳細な記述が最初で、最も詳細でない記述は最後です。リストの最初の項目は、通常、コントローラーの正確なモデル、またはコントローラーと互換性のあるモデルを示します。

例えば、Oculus Touch コントローラーの `profiles` の項目 0 は `oculus-touch` です。次の項目は `generic-trigger-squeeze-thumbstick` で、トリガー、スクイーズコントロール、サムスティックを備えた一般的な機器を示しています。 Oculus Touch コントローラーは実際にはサムスティックではなくサムパッドがありますが、全体的な記述が「十分に近い」ので、名前に照合するプロファイル内の詳細がコントローラを有益に解釈します。

```js
inputSource.profiles;
// ['oculus-touch', 'generic-trigger-squeeze-thumbstick']
```

仕様
--

| Specification |
| --- |
| WebXR Device API # dom-xrinputsource-profiles |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebXR 機器 API
* 入力と入力ソース (en-US)


XRInputSource: gamepad プロパティ - Web API

XRInputSource: gamepad プロパティ
============================

読み取り専用の `XRInputSource` の **`gamepad`** プロパティは、 XR 入力ソースがゲームパッドまたは同等の機器である場合、ボタンと軸の状態を記述した `Gamepad` オブジェクトを返します。機器がゲームパッドのようなものでない場合、このプロパティの値は `null` です。

返される `Gamepad` インスタンスはゲームパッド API で説明されているとおりに動作します。ただし、いくつか注意すべきことがあります。

* `XRInputSource` に属する `Gamepad` インスタンスは `navigator.getGamepads()` が返す配列には含まれません。ゲームパッドは厳密に WebXR ハードウェアに関連付けられるものであり、汎用のゲーム機器ではありません。
* `Gamepad.id` は空文字列 (`""`) です。
* `Gamepad.index` は `-1` です。
* `Gamepad.connected` は `XRInputSource` がアクティブな XR 入力ソースのリストから除去されるか、 `XRSession` (en-US) が終わるまでは `true` です。
* `Gamepad.axes` で報告される軸がタッチパッドの軸を表す場合、関連する `GamepadButton.touched` プロパティが `false` のとき、値は 0 になります。
* `Gamepad.mapping` は "xr-standard" を返します。
例
-

### gamepad 入力ソースの使用

```js
for (const source of frame.session.inputSources) {
  const gamepad = source.gamepad;
  if (gamepad) {
    if (gamepad.buttons[2].pressed) {
      // 何かする
    }
  }
}
```

仕様書
---

| Specification |
| --- |
| WebXR Gamepads Module - Level 1 # dom-xrinputsource-gamepad |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ToggleEvent: oldState プロパティ - Web API

ToggleEvent: oldState プロパティ
===========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`oldState`** は `ToggleEvent` インターフェイスの読み取り専用プロパティで、この要素が遷移する前の状態を表す文字列です。

値
-

文字列です。取りうる値は `"open"`（ポップオーバーが表示されている）または `"closed"`（ポップオーバーが非表示になっている）です。

例
-

```js
const popover = document.getElementById("mypopover");

// ...

popover.addEventListener("beforetoggle", (event) => {
  if (event.oldState === "open") {
    console.log("Popover is being hidden");
  } else {
    console.log("Popover is being shown");
  }
});
```

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-toggleevent-oldstate |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ポップオーバー API


ToggleEvent: newState プロパティ - Web API

ToggleEvent: newState プロパティ
===========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`newState`** は `ToggleEvent` インターフェイスの読み取り専用プロパティで、この要素が遷移した後の状態を表す文字列です。

値
-

文字列です。取りうる値は `"open"`（ポップオーバーが表示されている）または `"closed"`（ポップオーバーが非表示になっている）です。

例
-

```js
const popover = document.getElementById("mypopover");

// ...

popover.addEventListener("beforetoggle", (event) => {
  if (event.newState === "open") {
    console.log("Popover is being shown");
  } else {
    console.log("Popover is being hidden");
  }
});
```

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-toggleevent-newstate |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ポップオーバー API


ToggleEvent: ToggleEvent() コンストラクター - Web API

ToggleEvent: ToggleEvent() コンストラクター
===================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`ToggleEvent()`** コンストラクターは、新しい `ToggleEvent` オブジェクトを生成します。

構文
--

```js
new ToggleEvent(type, init)
```

### 引数

`type`

文字列で、イベントの方を表します。`ToggleEvent` の場合、これは常に `toggleevent` です。

`init`

以下のプロパティを持つオブジェクトです。

`newState`

文字列で、この要素が遷移した後の状態を表します。取りうる値は `"open"` および `"closed"` です。

`oldState`

文字列で、この要素が遷移する前の状態を表します。取りうる値は `"open"` および `"closed"` です。

例
-

開発者がこのコンストラクタを手動で使用することはないでしょう。関連するイベントが発行された結果、ハンドラーが呼び出されると、新しい `ToggleEvent` オブジェクトが生成されます。

例えば次の通りです。

```js
const popover = document.getElementById("mypopover");

// ...

popover.addEventListener("beforetoggle", (event) => {
  if (event.newState === "open") {
    console.log("Popover is being shown");
  } else {
    console.log("Popover is being hidden");
  }
});
```

仕様書
---

| Specification |
| --- |
| HTML Standard # toggleevent |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ポップオーバー API


AnalyserNode: AnalyserNode() コンストラクター - Web API

AnalyserNode: AnalyserNode() コンストラクター
=====================================

**`AnalyserNode()`** はウェブオーディオ API のコンストラクターで、新しい `AnalyserNode` オブジェクトインスタンスを生成します。

構文
--

```js
new AnalyserNode(context)
new AnalyserNode(context, options)
```

### 引数

`context`

`AudioContext` または `OfflineAudioContext` への参照です。

`options` 省略可

以下のプロパティを持つオブジェクトです。すべて省略可能です。

`fftSize`

周波数領域を解析するための FFT の望ましい初期サイズです。
 既定値は `2048` です。

`maxDecibels`

 FFT 解析のための dB 単位の望ましい初期最大出力です。
 既定値は `-30` です。

`minDecibels`

 FFT 解析のための dB 単位の望ましい初期最小出力です。
 既定値は `-100` です。

`smoothingTimeConstant`

FFT 解析のための望ましい初期スムーズ化定数です。既定値は `0.8` です。

`channelCount`

 ノードへの任意の入力へのアップミキシングとダウンミキシング接続時に使用するチャンネル数を決定するための整数を表します。（詳しくは `AudioNode.channelCount` を参照してください。）Its usage and precise definition depend on the value of `channelCountMode`.
 使い方や正確な定義は `channelCountMode` の値に依存します。

`channelCountMode`

ノードの入出力間でチャンネルを一致させる方法を記述する列挙値を表します。（既定など、詳細は`AudioNode.channelCountMode`を参照してください。）

`channelInterpretation`

 チャンネルの意味を記述する列挙値を表します。この解釈は音声のアップミキシングとダウンミキシングがどのように行われるかを定義します。
 使用可能な値は `"speakers"` または `"discrete"` です。（既定値など、詳しくは `AudioNode.channelCountMode` を参照してください。）

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-analysernode-analysernode |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `BaseAudioContext.createAnalyser()`、同様のファクトリーメソッド


AnalyserNode: fftSize プロパティ - Web API

AnalyserNode: fftSize プロパティ
===========================

**`fftSize`** は `AnalyserNode` インターフェイスのプロパティで、このプロパティは符号なし long 値で、周波数領域データを取得するために高速フーリエ変換 (FFT) を行う際に使用するウィンドウサイズをサンプル数で表します。

値
-

符号なし整数で、FFT のウィンドウサイズをサンプル数で表します。値を大きくすると、周波数領域での精度は高くなりますが、振幅領域での精度は低くなります。

2 のべき乗で、 2^5 と 2^15 の間でなければなりません。すなわち `32`, `64`, `128`, `256`, `512`, `1024`, `2048`, `4096`, `8192`, `16384`, `32768` のいずれかです。既定値は `2048` です。

### 例外

`IndexSizeError` `DOMException`

設定した値が 2 のべき乗でないか、許容範囲外である場合に発生します。

例
-

 次の例では、 `AudioContext` で `AnalyserNode` を作成し、 `requestAnimationFrame` と `<canvas>` で時刻領域のデータを繰り返し収集し、現在の音声入力の「オシロスコープ」出力を描画する基本的な使用方法を示します。
 より完全な応用例/情報については、 Voice-change-O-matic のデモを調べてください（関連するコードは app.js の 108 ～ 193 行目を参照）。

```js
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const analyser = audioCtx.createAnalyser();

// …

analyser.fftSize = 2048;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);

// draw an oscilloscope of the current audio source

function draw() {
  drawVisual = requestAnimationFrame(draw);

  analyser.getByteTimeDomainData(dataArray);

  canvasCtx.fillStyle = "rgb(200, 200, 200)";
  canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);

  canvasCtx.lineWidth = 2;
  canvasCtx.strokeStyle = "rgb(0, 0, 0)";

  canvasCtx.beginPath();

  const sliceWidth = (WIDTH \* 1.0) / bufferLength;
  let x = 0;

  for (let i = 0; i < bufferLength; i++) {
    const v = dataArray[i] / 128.0;
    const y = (v \* HEIGHT) / 2;

    if (i === 0) {
      canvasCtx.moveTo(x, y);
    } else {
      canvasCtx.lineTo(x, y);
    }

    x += sliceWidth;
  }

  canvasCtx.lineTo(canvas.width, canvas.height / 2);
  canvasCtx.stroke();
}

draw();
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-analysernode-fftsize |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API の使用