LoginSignup
2

More than 5 years have passed since last update.

CodeMirrorで他クライアントのカーソル(キャレット)の位置を表示する方法

Posted at

「CodeMirror」でリアルタイムに同時に、エディタ編集中の他の人(他クライアント)のカーソル(キャレット)の位置を表示する方法を説明します。

本記事の内容を応用すれば、下図のような感じで、他のクライアントのカーソルの位置を様々な色で表示することも可能です。

cattaz_cursor.png

この機能は、富士通研究所のOSSであるMarkdownベースのコラボレーションツール「Cattaz」に実装しています。

Cattazの公式ページ

GitHub - Cattaz

前置き

カーソルを表示する部分に焦点を当て説明するため、以下の説明については省略します。

  • CodeMirrorエディタの入力イベントの取得
  • CodeMirrorエディタ間の通信

方法

CodeMirrorの以下のAPIを利用します。

setBookmark

このAPIを利用することで、自ら生成したDOMノード(マーカー/表示したいデザイン)をエディタ上の指定した位置に挿入できます。

つまり、他クライアントから送られてきたカーソルの位置情報の場所に、何かしらスタイルを装飾したDOMノードを追加できます。

それにより、他クライアントのカーソル位置を表示することができます。

以下に、DOMノードを生成して、そのDOMノードを指定したエディタ上の位置に「setBookmark」でセットするコードの例を示します。

(ES2015(ES6)でのコードの書き方で説明)

// cm:CodeMirrorのインスタンス
// cursorPos:他クライアントから送られてきたカーソルの位置(CodeMirrorにおける {line, ch} のこと)

// DOMノード(マーカー/表示したいデザイン)を生成
const cursorCoords = cm.cursorCoords(cursorPos);
const cursorElement = document.createElement('span');
cursorElement.style.borderLeftStyle = 'solid';
cursorElement.style.borderLeftWidth = '2px';
cursorElement.style.borderLeftColor = '#ff0000';
cursorElement.style.height = `${(cursorCoords.bottom - cursorCoords.top)}px`;
cursorElement.style.padding = 0;
cursorElement.style.zIndex = 0;

// 上記で生成したDOMノードを他クライアントから送られてきたカーソルの位置にセット
// setBookmarkの第1引数:他クライアントから送られてきたカーソルの位置
// 第2引数内のwidget:生成したDOMノード
marker = cm.setBookmark(cursorPos, { widget: cursorElement });

DOMノード生成の部分は、自分の好きなようなスタイルにすると、かっこよくできます。

上記の例は、普通のカーソルのような縦線のデザインです。

setBookmarkで付加したDOMノードは、そのままですとエディタ上の挿入した位置に残り続けるため、他のクライアントからカーソル位置が送られてくる度に、一度以下のようにsetBookmarkのclear()メソッドで挿入したDOMノードを削除し、それから新規にDOMノードを再度挿入すると良いです。

// 挿入したDOMノードのクリア
// marker:setBookmarkのインスタンス
marker.clear();

処理の一連の流れ

処理の大まかな一連の流れの例は以下です。

  1. CodeMirrorエディタの入力イベントからカーソルの位置を取得する
  2. 取得したカーソルの位置を Websocket通信などを用いて他クライアントへ送信する
  3. 他クライアントから送られてきたカーソルの位置を受信したクライアントは、前にsetBookmarkで挿入したDOMノードが存在していたら削除する
  4. 受信したカーソルの位置に、マーカーとなるDOMノードをsetBookmarkで挿入する

また、各クライアントから受信したカーソル位置を各クライアントごとに管理すれば、複数のクライアントのカーソルを同時に表示できるようになります。

まとめ

以上のようにして、CodeMirrorのAPIの「setBookmark」を利用すれば、他クライアントのカーソルの位置を表示できます。

この機能は「Cattaz」にも実装していますので(2018年1月9日現在)、そちらのソースコードも見ると参考になるかもしれません。

GitHub - Cattaz

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
2