ブラウザ上でお絵かき2005年09月27日 02時37分

Ajax を使った手書き文字認識」を見て。ここでは線を描くのに絶対配置の span 要素を大量生成しているけど、最近のブラウザってベクター描画エンジン付きのものが多いわけで。WinIE 5 以降の VML 、Opera 8 ・ Firefox 1.5 以降の SVG 、Safari 1.3 ・ Firefox 1.5 以降の canvas 要素といった具合に。

ということで各ブラウザでベクター描画エンジンが使えればそれを使い、なければ絶対配置の HTML 要素を大量生成することで、ブラウザ上でお絵かきできるというものを作ってみた。元に戻す / やり直すこともできる。線を描くだけで塗りつぶしはできないが。

その線を描くために作ったのが DrawingCanvas クラス。以下のようにすることで三角形が描ける。実際の描画部分には SVG Tiny 、HTML Canvas 、CSS Positioning 、VML の 4 つのバックエンドがあり、ブラウザによってそれらを切り替えている。

var canvas = new DrawingCanvas(element, width, height);
canvas.setBgColor("#fff");
canvas.setLineColor("#000");
canvas.setLineWidth(5);

canvas.startLine(10, 10);
canvas.lineTo(50, 50);
canvas.lineTo(50, 10);
canvas.lineTo(10, 10);
canvas.endLine();

CSS Positioning バックエンド (絶対配置の HTML 要素を大量生成) の作成にあたっては線分描画のアルゴリズム (Fussy's HOMEPAGE) を参考にした。Bresenham ね、なるほど。(しかしこうしたアルゴリズムを自分で考えずに、すぐ検索に走ってしまうのは悪い癖か?)

作成にあたってつまずいた点などは以下のとおり。

  • Opera 8 がサポートしているのは SVG Tiny 。よって SVG DOM には対応していない。
  • Opera 8 では SVG 要素を文書に追加 / 削除しただけでは描画に反映されない。そのあと要素の属性値などを変更する必要がある。
  • Canvas の save() / restore() はパスの線の太さ・色といった状態を保存 / 復元するのであって、描画された画像そのものを保存 / 復元するわけではない。

コメント

_ 高橋登史朗 ― 2005年09月28日 20時46分

感動しました(^^。

_ 高橋 ― 2005年09月29日 22時28分

残念ながら、Safari 2だと真っ白けで動かないそうです。Safari1.25は動きましたが、v2を私は持っていないので、確認できませんでした。<canvas>タグ書いておけば描けるそうなんですけれど、試せないのでわかりません。。。

_ nanto_vi ― 2005年09月30日 23時03分

興味を持ってくださりありがとうございます。しかし Safari 2 では動きませんか。うーん……。
Canvas バックエンドにはなるけどそれ以上動かないということでしょうか? Safari 1.2で動くということはイベントハンドリングの問題ではなさそうですし…… Safari 2 は canvas 要素の動的な生成に対応していないとか?

どなたか以下のテストが Safari 2 (というより 1.3 以上?) ではどうなるか試していただけないでしょうか? Firefox 1.5 Beta では無事描画されるのですが。
http://www.ne.jp/asahi/nanto/moon/2005/09/30/canvas-test.html

_ 高橋 ― 2005年10月01日 21時11分

1と2は動くけど3、4は反応なしだそうです。
createCanvasAfter()がうまくいっていないのでしょうか?
canvas.id = "id" + (new Date()).getTime();
canvas.width = 100;
canvas.height = 100;
を普通に
canvas.setAttribute('id','id' + (new Date()).getTime());
canvas.setAttribute('width' , '100px');
canvas.setAttribute('height' , '100px');
とかはどうでしょう?
あるいは、DOMだから、
canvas.width = 100;
ではなく
canvas.width = '100px';
とか??

うーん、やっぱりMacの新しいのを買うしかないかなぁ、、、

_ nanto_vi ― 2005年10月02日 06時50分

ダメですか。それではテスト第二段、これでだめならもうお手上げです。
http://www.ne.jp/asahi/nanto/moon/2005/10/02/canvas-test.html

うーん、それにしても一体なぜなんでしょう?
Safari 2 (WebCore-413) の ChangeLog (*) には

2004-11-22 David Hyatt
Make sure you can use document.createElement to make a <canvas> element.
* khtml/xml/dom_docimpl.cpp:
(DocumentImpl::createHTMLElement):

とあるのに……。

* http://darwinsource.opendarwin.org/10.4/WebCore-413/ChangeLog

_ 高橋 ― 2005年10月02日 16時18分

今度は3だけ駄目だそうです。
解決したぽいですね(^^)

_ 高橋 ― 2005年10月02日 16時25分

でも、こうなると、、なんとなくcreateCanvasAfter1(refElement)が納得できない(^^;のと、XHTMLとかですと createCanvasAfter4(refElement)なのかなぁ、、、。

_ nanto_vi ― 2005年10月06日 06時03分

修正版をアップしました。

結局 Safari は属性を指定する際、DOM オブジェクトのプロパティとして指定するのではなく、setAttribute を使ってやらないとダメということですかね。

ちなみに width 、height に指定する値は、WHAT-WG の仕様書 [1] によると正の整数、Apple の解説 [2] によると img 要素のそれと同じ値だそうで。どちらもピクセル指定のときは単位なしでいいみたいです。

[1] http://www.whatwg.org/specs/web-apps/current-work/#dynamic
[2] http://developer.apple.com/documentation/AppleApplications/Reference/SafariHTMLRef/index.html

_ 高橋 ― 2005年10月06日 11時48分

今電気店の展示Macでテストしました。Safari2オーケーです(^^;

_ 高橋 ― 2005年10月06日 16時39分

ところで、クロスブラウザベクター描画ライブラリとしてこれはとても便利なので、勝手に期待をふくらませているんですけれど(^^;、今ポリラインだけで800行なんですよね、、、。

_ 高橋 ― 2005年10月06日 16時46分

、、、もしかして、たとえば、DrawingCanvas()のswitchあたりで各ブラウザ対応スクリプトだけをAjaxインクルードすれば、もっと行数増やしていろいろしても軽くできるかも?

_ nanto_vi ― 2005年10月07日 22時38分

そうですね。JSANあたりを使って動的にスクリプトをロードすればちょっとは軽くなるんでしょうが。

ただ、申し訳ありませんが、私にとってこれは「ブラウザにはこんな機能もある」というのを例示するために作っただけなので、積極的に機能を追加していく気は正直あまりないのです。

誰かがこれをヒントにもっとすごい「何か」を作ってくれるといいななどと思ってはいるのですが。

_ 高橋 ― 2005年10月07日 23時31分

いえいえ、ここまででも充分グッジョブです。どうか、私の勝手な期待を重荷には感じないで、マイペースで行ってください。わたしにとっては、長年答えのでていなかったクロスブラウザなベクターグラフィック処理へのほつれた糸が突然綺麗な形でそろったので、それだけで感動しています。今ちょうどAjax本を書いていたりしますので、(運命と思って<オーバー^^?)ぜひエフェクトなサンプルあたりで取り上げさせていただければと思っています。

_ 高橋 ― 2005年10月09日 18時32分

>誰かがこれをヒントに<s>もっとすごい</s>「何か」を作ってくれるといいな

すごいのは無理ですが(^^;
一応、言い出した責任で、Ajaxによるブラウザ別インクルードを試してみました^^。
Ajax版
http://jsgt.org/lib/vector/2/sample2.htm
ノーマル版
http://jsgt.org/lib/vector/3/sample3.htm

ベンチマークは一概には言えませんけれど、Firefox1.02では効果があるようでした。
ソースは整理していないので、、、、、、です。

_ 高橋 ― 2005年10月09日 22時26分

こんなの作ってみました。
http://jsgt.org/lib/vector/graph/sample1.htm

_ Ogawa ― 2008年01月22日 22時36分

JavaScript+htmlで折れ線グラフをクライアントPCで動かしたいのですが、どうすれば良いのか解りません。ご教授願いませんでしょうか?

_ nanto_vi ― 2008年01月23日 15時55分

「動かしたい」というのはアニメーションをつけたいということですか。
そうならば「Ajaxで簡単リソースモニター - Ogawa::Memoranda」<http://as-is.net/blog/archives/001066.html> で似たようなことがされています。
基本的にはタイマーをかけてそのつど描画しなおすという形になります。

_ Ogawa ― 2008年01月23日 22時47分

表現が不味くてすいません!
CSV形式ファイルをJavaScriptで読み込みブラウザで折れ線グラフを表示したいのです。

具体的にはイントラネットのWebサーバに置かれたCSVファイルを読み込みブラウザーで折れ線グラフを表示したいのです。これをJavaScript+(html)でできないかな!?と思いまして。Ajaxを使わないと無理ですか!?(Ajaxをよく知らない少年です。)

_ nanto_vi ― 2008年01月24日 17時22分

それでしたら高橋さんの「Ajaxでクロスブラウザベクターグラフ」<http://jsgt.org/mt/archives/01/000514.html> が参考になると思います。今なら折れ線グラフ描画用のライブラリもいろいろあると思いますが。
非同期で外部のデータを読み込み、何かしらの処理したのなら、結果的に (広義の) Ajax を使ったことになりますね。

_ Ogawa ― 2008年01月26日 02時19分

nanto_viさんありがとうございます。
Ajaxについて勉強してみたいと思います。

_ K-MA ― 2008年06月14日 03時10分

nanto_viさん、はじめまして。
ブラウザ上でお絵かきを一部参考&利用させていただきました。
ありがとうございます。

Ajaxで8人まで同時にお絵かき出来る機能を以下のコミュニティ
サイトに盛り込ませていただきました。
https://www.nagise.jp/
すぐに見れないのが悲しいところですが。。
「何か」に当てはまっていれば幸いでございます。。
遅ればせながらご報告させていただきます。

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※投稿には管理者が設定した質問に答える必要があります。

名前:
メールアドレス:
URL:
次の質問に答えてください:
「ハイパーテキストマークアップ言語」をアルファベット4文字でいうと?

コメント:

トラックバック

このエントリのトラックバックURL: http://nanto.asablo.jp/blog/2005/09/27/89628/tb

_ JavaScript++かも日記 - 2005年09月28日 19時51分

ブラウザ上でお絵かき http://www.ne.jp/asahi/nanto/moon/2005/09/27/canvas.html http://nanto.asablo.jp/blog/2005/09/27/89628 VML バックエンド HTML Canvasバックエンド  SVG Tiny バックエンド CSS Positioning バックエンドといったモードで動作していて芸が細かいですねー。ラインセンスは修正 BSD ライセンス。...

_ きまぐれブログ - 2005年10月15日 22時47分

このごろ超多忙で全然更新できてないので、気になったニュースやウェブサイトを簡単に紹介します。
(ほぼはてなブックマークからの抜粋です_| ̄|○)

_ Ogawa::Memoranda - 2005年11月14日 02時14分

クラスタなどのリソースモニターをAjaxを使って実現すると、Ganglia Monitoring Systemみたいな味気なさ(最近はチェックしていないのでカッコヨクなっていたらスマソ)が解決したり、Centralized Serverで行う実質的なレンダリング(一般的にはHTML生成)のオーバーヘッドが抑制できたりするのではないかとふと思いついてしまいました。まあJava Appletを使えば済...

_ フリックスの日記 - 2005年11月20日 04時08分

入門Ajaxを一通り読んだ。 ISBN:4797332646:detail けっこう読み応えがありましたよ。 最後の方に描画機能について書いてありました。 そこに DrawingCanvas というクラスが紹介されているのですが、それはあるサイトのブログで紹介され、更にこのクラスの作者さんとこの本の著者である高橋さんとのやりとりで出来上がったものの様です。 まだ実際に触ってはいませんが、これまで行ってきた仕事で活用させていただきたいと思います! [http://nanto.asablo.jp/blo ...

_ はろーねっと - 2006年04月23日 16時17分

こんにちは。ブラウザ上でお絵かき: Days on the Moonを興味深く読ませていただきました。勉強になりました。

_ Days on the Moon - 2006年05月18日 04時28分

高橋登史朗さんが DrawingCanvas.js を使ったグラフ描画のデモを公開してくださっています。すばらしいですね。これぞまさしく Ajax という感じです。
しかし、Pentium M 1.3 GHz 、メモリ 256 MB

_ dhrnameのウェブ日誌 - 2007年03月02日 22時26分

かなり、前の記事ですが、JavaScriptを使って、ほとんどのブラウザで絵を描けるというのは、すばらしいです。 ブラウザ上でお絵かき http://nanto.asablo.jp/blog/2005/09/27/89628