1036文字
5分
編集

Safari 16.4リリース、多数のWeb APIとECMAScript機能を追加

Safari 16.4がリリースされた。

多数のWeb APIがサポートされるようになった。モダンブラウザの中でSafariのみがサポートしていなかったものが多く、ポリフィルを含める必要がなくなるのは大きな前進である。

#Fullscreen API

特定の要素を全画面モードで表示したり、それを解除したりできるAPIである。ブラウザゲームや間取り図の拡大などで有用かもしれない。ただし、離脱用のUIを作らない限りESCキーなどで離脱する必要があるため、ユーザーのことをよく考え利用した方が良い。

js
document.addEventListener(
  "keydown",
  (e) => {
    if (e.key === "Enter") {
      toggleFullScreen();
    }
  },
  false
);

function toggleFullScreen() {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen();
  } else if (document.exitFullscreen) {
    document.exitFullscreen();
  }
}

#Screen Orientation API

画面の向きを取得できるAPIである。

js
const orientation = screen.orientation;
orientation.addEventListerner("change", () => {
  console.log(orientation.type, orientation.angle);
});

rotateBtn.addEventListener("click", async () => {
  const oppositeOrientation = screen.orientation.type.startsWith("portrait")
    ? "landscape"
    : "portrait";
  scrren.orientation
    .lock(oppositeOrientation)
    .then(() => {
      console.log(`Locked to ${oppositeOrientation}`);
    })
    .catch((error) => {
      console.error(error);
    });
});

unlockBtn.addEventListener("click", () => {
  screen.otientation.unlock();
});

#Screen Wake Lock API

端末が自動で画面を暗くしたり、ロックしたりするのを防ぐAPIである。アプリケーションの継続が必要なケースや、QRコードを表示しておく必要があるアプリなどで有用である。

js
const wakeLock = await navigator.wakeLock.request("screen");
wakeLock.addEventListener("release", () => {
  console.log("Happy release wakeLock!!");
});

await heavyTask();

await wakeLock.release();

ページのタブを切り替えるなどでドキュメントの可視性が変化すると解除されてしまう点には注意が必要である。必要に応じて、visibilityChangeイベントを監視し、ロックを掛け直す必要がある。

js
document.addEventListener("visibilitychange", async () => {
  if (wakeLock !== null && document.visibilityState === "visible") {
    wakeLock = await navigator.wakeLock.request("screen");
  }
});

#OffscreenCanvas

OffscreenCanvasは、端的に言えばDOMとCanvas APIの分離である。

従来のCanvasを利用した高度なアニメーションの描画はメインスレッドを圧迫し、ユーザー操作を阻害するという問題があった。OffscreenCanvasでは、アニメーションの描画をWeb WorkerのWorkerスレッドで行うことで、この問題が解消される。

今までも、DOMの操作は出来ないものの重いデータ処理をWeb Workerなどで行うことで、負荷を軽減することは出来たが、OffscreenCanvasはTransferableオブジェクトであり、実質オフスクリーンでレンダリングできるDOMから分離されたCanvasであるため、描画までをWeb Workerで担うことができる。

js
const offscreenCanvas = canvas.transferControllToOffscreen();
const worker = new Worker("worker.js");
worker.postMessage({ canvas: offscreenCanvas }, [offscreenCanvas]);

// worker.js
onmessage = (event) => {
  const offscreenCanvas = event.data.canvas;
  const ctx = offscreenCanvas.getContext("webgl");
  // ...
};

#Web Push API

今まではAndroidなどでしかサポートされていなかったWeb Pushが、iOS 16.4でサポートされた。 ホーム画面に追加されたWebアプリから、Push API、Notifications API、Service Workerなどを駆使して、ユーザーにプッシュ通知を送ることが可能になった。

またホーム画面に追加されたWebアプリでカウントを表示できるBadging APIなどもサポートされ、今後PWAの利用が広がると期待される。

#ECMAScript features

Safari 16.4は非常に巨大なリリースであり、JavaScriptの多くの機能も新たにサポートされた。

#Array.formAsync

Array.fromfor 相当なのに対して、Array.fromAsyncfor await 相当である。 Async iterableを処理する方法として Promise.all などがあるが、Promise.all が並列実行であるのに対して、Array.fromAsync は順次実行される。

#Array#group, Array#groupToMap

Array#group は、配列を指定した関数の戻り値でグルーピングしたオブジェクトを返す。 一方、Array#groupToMap は、配列を指定した関数の戻り値でグルーピングした Map を返す。

js
const animals = [
  { name: "たま", type: "猫" },
  { name: "みけ", type: "猫" },
  { name: "ぽち", type: "犬" },
];
console.log(animals.group((animal) => animal.type));
/* result
{
  猫: [
    { name: 'たま', type: '猫' },
    { name: 'みけ',  type: '猫' },
  ],
  犬: [
    { name: 'ぽち', type: '犬', },
  ],
}
*/
console.log(animals.groupToMap((animal) => animal.type).get("猫"));
/* result
[
  { name: 'たま', type: '猫' },
  { name: 'みけ',  type: '猫' },
]
*/

#Import Maps

ブラウザで実行されるimportによって読み込まれるパッケージのURLを指定する手段である。

html
<head>
  <script type="importmap">
    {
      "imports": {
        "react": "https://unpkg.com/react@18/umd/react.development.js",
        "react-dom": "https://unpkg.com/react-dom@18/umd/react-dom.development.js"
      }
    }
  </script>
</head>
<body>
  <script type="module">
    import { createRoot } from "react-dom/client";
    import React from "react";
  </script>
</body>

#参考文献