LoginSignup
9
8

More than 3 years have passed since last update.

Reactで超簡単、タグで挟み込むだけの仮想ウインドウの実装

Last updated at Posted at 2019-09-01

Reactで超簡単、タグで挟み込むだけの仮想ウインドウの実装

1.今回のブツ

キャプチャ

2.仮想ウインドウとは

 Webコンテンツを表示する際、そのコンテンツを表示しているアプリケーションは、モバイルも含めてウインドウ単位でUIが構成されています。デスクトップ用のOSはマルチウインドウ、モバイルの場合はシングルウインドウを切り替えていく方式になっています。

 今回は仮想ウインドウということで、ブラウザのWebコンテンツを表示する領域に仮想的なウインドウを作ります。この仮想ウインドウがあると、流れの異なる入出力を同時に表示させることが出来ます。その他、突発的なデータ入力の際、入力フォームを埋め込む位置をレイアウトの中に用意しなくて済むようになります。

3.仮想ウインドウを作る上で考えるべき事

 PC用のOSのようなマルチウインドウシステムは、実際に実現しようとするといくつか面倒な部分があります。マウスやタップイベントの処理、イベントが発生したウインドウとそのパーツの把握、ウインドウの重ね合わせ順序や位置とサイズ、処理する内容はそこそこな量になります。さらにウインドウの中に子ウインドウを埋め込む場合の処理や、どれがアクティブウインドウでどれを非アクティブにしなければならないのか、実際に組んでみると、マルチウインドウシステムでは大変な作業が行われているのです。

 ちなみにWindows3.1時代はCPUが貧弱、しかもウインドウシステムの出来も良くなかったので、マウスをぐるぐると移動させるだけで、あっという間にCPU使用率100%に達するような状態でした。ウインドウシステムを組む上では、こういった負荷の部分も気にしながら実装する必要があります。

4.Reactでの実装

 独自の仮想ウインドウフレームワークは npm に上げてありますが、今回はReact用で簡単に使えるものを作ることが目標です。タグで囲むだけで自動的に仮想ウインドウになったら便利ですよね。目標はこれです。

index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import { JSWFWindow } from "@jswf/react";

function App() {
  return (
    <>
      <JSWFWindow>
        この中に入れたコンテンツが仮想ウインドウ上に表示される
      </JSWFWindow>
    </>
  );
}

ReactDOM.render(<App />, document.getElementById("root") as HTMLElement);

 はい、仮想ウインドウが表示されました。目標達成です。

5.React用仮想ウインドウコンポーネント

 作ろうと思い立って一週間、最低限の動作はするようになったので紹介します。

インストール方法

npm -D i @jswf/react

使い方

.tsx
<JSWFWindow>挟み込む</JSWFWindow>

以上です。

結果

image.png

Propsパラメータ

現時点でこんな感じのパラメータが設定できます

Name Type Info
x number | null X Position
y number | null Y Position
width number Width
height number Height
moveable boolean trueだとクライアント領域のドラッグで移動
borderSize number サイズ変更用の見えないフレームのサイズ
titleSize number タイトルバーのサイズ
title string タイトル
active boolean trueでアクティブ
overlapped boolean falseにするとウインドウが親ウインドウ内にのみ表示
windowStyle number WindowStyle ビットの込み合わせ
TITLE:タイトルバー
MAX:最大化ボタン
MIN:最小化ボタン
CLOSE:クローズボタン
FRAME:枠の表示
RESIZE:サイズ変更
windowState WindowState WindowState ウインドウの状態
NORMAL:通常
MAX:最大化
MIN:最小化
HIDE:非表示
onUpdate function(p:WindowInfo) | null ウインドウの状態が変化するとコールバックされる

メソッド

  • foreground()
    • ウインドウをフォアグラウンドにする
  • setWindowState(state: WindowState | undefined)
    • ウインドウの状態を変更する
    • state
      • WindowState.NORMAL
      • WindowState.MAX
      • WindowState.MIN
      • WindowState.HIDE

6.サンプルソースの紹介

 createRefでコンポーネントのインスタンスを受け取るようにすれば、直接操作することも可能です。

index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import { JSWFWindow, WindowState, WindowStyle, WindowInfo } from "@jswf/react";

function App() {
  const frame = React.createRef<JSWFWindow>();
  const [info, setInfo] = React.useState<WindowInfo | null>(null);
  return (
    <>
      <JSWFWindow ref={frame} title="Window1" x={50} y={100}>
        この中に入れたコンテンツは仮想ウインドウ上に表示されます
      </JSWFWindow>

      <JSWFWindow title="Window2" width={600} height={500} windowStyle={~WindowStyle.CLOSE}>
        ウインドウ位置を設定しなかった場合、中央に表示されます
        <br />
        windowStyleで使用する機能を設定できます

        <JSWFWindow title="ChildWindow" overlapped={false} width={200} height={200}>
          overlappedをfalseにするとクライアント領域内に表示され、trueにすると重ね合わせだけ調整されます
        </JSWFWindow>

      </JSWFWindow>

      <JSWFWindow title="更新テスト" y={50} onUpdate={p => setInfo(p)}>
        <pre>{info && JSON.stringify(info,["realX","realY","realWidth","realHeight"],' ')}</pre>
      </JSWFWindow>

      <button onClick={() => {
          frame.current!.foreground();
          frame.current!.setWindowState(WindowState.NORMAL);
        }}>
        Window1を復活させる
      </button>
    </>
  );
}

ReactDOM.render(<App />, document.getElementById("root") as HTMLElement);

7.関連リンク

8.まとめ

 Reactはそこそこ前にちょっと触った程度だったので、とりあえずコンポーネントを作ることから始めました。そろそろ入門用のチュートリアルでもやろうかと思っています。

 仮想ウインドウコンポーネントに関しては、自分の開発でも必要になるのでこれから機能を増やしていこうと思っています。なにか要望があれば、コメントをください。

9
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8