NHN Cloud Meetup 編集部
Webワードの基礎作成(1)
2018.01.04
275
Webワードの基礎作成(1)
Webワードプロセッサ(以下、Webワード)は、思ったより古い歴史を持っています。Google Docsが2006年に導入され、よく知られるようになりましたが、Webワードはすでに十数年の歴史があるソフトウェア分野です。ThinkFreeはJavaアプレットを基盤にブラウザ上で動作するWebワードを標榜したが、JavaスクリプトなどのWeb言語で作成されていないため、Webワードとは見做せないでしょう。ネイティブワードプロセッサ(以下、ネイティブワード)は、各OSを基盤に独自のグラフィックツールキットとC ++やJavaのようなプログラミング言語で実装されていますが、Webワードはブラウザで動作するので、対応ブラウザであれば、どのコンピュータからでも文書の編集ができるという長所があります。
ここではWebワードを作成する基本的な原理を紹介します。
Webワードの必要性と種類
まずは、Webワードが必要とされる理由、Webワードの基準と種類について調べてみよう。
Webワードの必要性
大きな利点は、ブラウザさえあればOSに関係なく目的のコンテンツを表現できるということです。しかし、ドキュメントの編集に関しては、ほとんどが特定のOS、ソフトウェア、文書フォーマットを使用するという制約があります。
Web技術の発達によってWebで可能なことが増えてきていますが、Webワードは対応ブラウザであれば、どんなOSであっても、特定のオフィスソフトウェアがインストールされていないコンピュータであっても、ドキュメントが作成できます。文書はHTML、JavaScript、SVG、CanvasなどのWeb言語で表現されるため、ユーザーの立場から見ると、文書フォーマットを考慮する必要がありません。
Webワードの分類基準
ネイティブワードの基準と照合した場合、一般的に、Webワードも文書ページの表現機能と編集機能が必要です。ページ表現機能がない場合、ネイティブワードで文書を作成したユーザーが、Webワードに切り替えたとき、最も異質に感じる可能性が高いでしょう。私たちが利用する文書(試験紙を含む)と官公庁、企業で使用される文書は、それがデジタル文書であるにもかかわらず、本の習慣が強いためか、ページ表現を提供するワードで作成されたものが多いようです。
ページ表現と編集をサポートするWebワード
ページ表現をもつ主なWebワードを紹介します。
Webワードの実装には様々な問題があるでしょう。主なものとして以下のような課題があります。
実装での考慮事項
- ページ表現と編集機能の構成の複雑さ
- カーソルコントロールとDOM操作の複雑さ
- 多言語対応、各種フォント提供の難しさ
- ネイティブワードの表現を類似させる難しさ
- 行間隔
- 段落の間隔
- Web上での行と段落の縦Align(Top、Middle、Bottom)の表現の違い
- フォントレンダリングの相違性
- 各種CSS(ブラウザのレンダリングエンジン)と特定の文書フォーマットの表現の違い
このように、Webワードは思ったより多くの機能に対応していますが、まだ不便さがあります。ODF(Open Document Format)のODT(Open Document Text-ODFの文書フォーマット)は、むしろ文書の内容に忠実なスペックで、これを実装したソフトウェアでは文書表現が若干異なることもあります。文書表現の中心には文書のページ表現機能と編集機能があります。
Webワードの実装
先に述べたように、Webワードの中核基準と第一歩は、ページ表現と編集機能だと考えられます。なぜなら、コンテンツの入力、削除、挿入、貼り付け、画像、表機能などの実装を行った上で、ページ関連機能を実装したとき、大部分をページ表現に合わせて新たに実装する必要があるためです。
重要なのは、文字入力や表現方法の選択です。
contentEditable
文字入力と文書表現をCanvasで表現したエディタもあり、WebODFのODT EditorようにSVGを使うこともできます。HTMLを使う一方で、カーソルの入力機能と、カーソルのレンダリングを別々に実装するToast UI Editorもあります。contentEditableは問題も多いですが、最も早く編集機能に対応できる方法です。
contentEditableの利点
- ある程度のレベルの機能を早く実装できる
- ブラウザの入力システムを活用し、特に英語以外の組み合わせ入力が必要なアジア言語をサポートする場合に有利
- ブラウザのカーソルコントロールを活用し、方向キー、Home/End、PageUp/PageDown、Del、カーソルのレンダリング活用可能
- ブラウザの基本的なコピー&ペースト活用可能
contentEditableの欠点
ブラウザの実装に依存することから生じる欠点もあります。
- ブラウザ別にフォント表現とCSSのボックス表現が若干異なる(IE11の場合、フォントサイズ9が10より大きく見えたり、他のブラウザに比べて字間が狭く表現されるフォントがある)
- バグがあってもブラウザがパッチしてくれるまで手段がない(IE11以下のバージョンはサポートが中止されており、バグレポートがあっても、パッチはEdgeにのみ反映される)
- div blockタグの場合、contentEditable属性が指定されると、Resize Handler枠ができて見た目がよくない。Resize Handlerが見えないように処理すべきだが、規定された方法を探すのが難しい(IE11、Firefoxで検証したところ、特にIE11でcontentEditable属性を入れて取り除いても、しばしば除去したResize Handlerが復元する)
HTMLでページの表現方法
HTMLは通常、縦方向にレンダリングし、A4用紙のような紙の概念では文書を表現しません。page-break-before、page-break-afterのような機能は、出力時と改ページのような機能を実装するときに非常に便利ですが、ページの表現に用いることは難しいでしょう。
ページ表現機能の簡単な要件を定義してみよう。
- 段落がページ間にわたる場合、段落を単位に分けて、前と次ページに表現できる
- 文字入力/削除をしながら、リアルタイムで表現する
この要件に基に、HTML文書を分割する段階(ページレイアウト)を調べてみよう。
ページを分ける段階
ページレイアウトは、以下のような段階でアクセスできます。
まず、内容が表現される空間を作るためにページの高さと余白を定義します。(A4用紙なら210mm x 297mm、余白を除いたサイズが実際の文書が表現される大きさ。DOMでPagecontainerにタグが必要であることを前提に説明します。)
- n番目のPagecontainerタグ内に全体htmlを入れる(nは1から始まる)
- n番目のページ内部のblockタイプのタグを上から順番に探索しながら(ページのbottom <blockのbottom)である最初のタグを探す。なければ終了する
- 見つかったblockタグはページに分けて表現する必要があるため、blockを行単位で分ける
- 分割された行を上から順番に探索しながら(ページのbottom <行bottom)である最初の行を探す
- 見つかった行を基準にblockを分離してblock-1、block-2にする
- n+1Pagecontainerタグを作る
- block-2から以降のすべてのタグをn+1番目のタグに移動する
- 2の手順を繰り返す
段落を行分割する段階
- 段落(blockタグ)の文字1つ1つをspanタグで囲む(Textノードだけでは文字の座標を把握できないので、タグで囲む必要がある)
- タグで囲んだ文字を順番に回りながら(n番目の文字のbottom <n+1番目の文字のtop)の文字を探す
- n+1番目の文字を改行された行で処理する
- 2を繰り返して段落をすべての行に分ける
- 各行の最大bottomを探す
- 【ページを分ける段階】の4で各行のbottomを使用する
- 挿入したspanタグをすべて削除して、元の段落(blockタグ)に戻す
ページレイアウトを実行すると、以下のように文書をページの形で表現したWebワード画面が構成されます。
ニュースソース : https://www.atmarkit.co.jp/ait/articles/1808/22/news043.html
再度ページレイアウトの実行が必要なイベント
ページレイアウトの実行が必要な編集操作があります。例えば、
- 文字を含んだ内容(画像、テキストボックス、表など)の入力、削除(貼り付けを含む)
- 文字を含んだ内容のスタイル変更(文字サイズ、フォント、段落/行間隔の変更、箇条書き、インデントなど)
- ページ形状編集(縦/横、ページサイズ変更)
- 改ページ表示挿入/削除
これらのイベントが発生すると、ページレイアウトを行う必要があります。
パフォーマンス
Webワードでページ表現と編集機能を搭載している製品は思ったより多くはありません。その理由の1つがパフォーマンスです。上記のような原理でページ表現をすると、ブラウザが演算すべきDOM操作やレイアウトが非常に多くなります。特に段落を分割する過程においては、DOMの操作量が多く、レイアウトした結果まで受け取って文字の位置値を処理する必要があり、作業コストが極めて大きいでしょう。
すべてのWebワードをテストしたわけではありませんが、通常、このような方法で実装した場合、一字一字のタイピングが遅いという印象を受けるでしょう。入力した内容が多いほど、より反応が遅くなるでしょう。Google Docsで単純に文字だけの内容でテストしたところ、10ページを超えると書き込みが少しずつ難しくなるという印象を受けました。
計算を減らす方法として、2つのTipsを紹介します。
- 変更されたページと段落(blockタグ)以降のタグのみを対象に再計算する
- 改ページが挿入された場合は、当該ページの前ページまで計算する
パフォーマンスを考慮しながら実装する際、注意すべき点は、JavaScriptの最適化手法を最大限に活用することです。そしてブラウザ”force layout”の誘発も最小限に抑える必要があります。アンチパターンを確認して性能を阻害するコードを削除しよう。レイアウトやリフローの概念を理解して不要なレイアウトが起きないようにしましょう。ご存知のようにDOMの特定プロパティは読み取り専用でも強制的にレイアウトが起こります。
次の記事では
次回は実際のコードを使って、簡単なページ表現と編集機能の実装方法を紹介します。contentEditableを使ったページの編集機能の処理と、文書の内容を変更した後(文字の挿入、削除など)、再びページレイアウトを行う過程について紹介します。
今後の傾向
WebGL、WebAssembly、HTML5のFile、DBなど多くのAPIの登場を見ると、Webを1つのプラットフォームと見做し、伝統的に行っていた業務、機能、サービスをWeb上で処理しようとしています。この傾向は今後も発展し続けるでしょう。ネイティブワードからWebワードへの移行もその一環と考えられます。Chromebookでは最初からネイティブワードがなく、Google Docsを使用したWebワードのみを提供しています。これからもネイティブワードからWebワードへの移行はさらに加速すると思われます。