手前味噌ながらTwEgakuは良くできてるな……。もちろんバグはあるし、足りてない物だらけなんだけども。
消しゴム機能の“消し味”が最高だ。この消しゴム機能は全ての手書きアプリがパクるべきだろう。
書き味もウェブサイトなのに筆圧対応で気持ちが良い。
TwEgakuで文字が表示しない
あれ
やりたかったことは「ペンの太さをもう少し太くしたい」というだけのことだったが、Podmanで開発用のDB立てたり、ライブラリのアップデートしたり、Biome入れたり、無限ループでやらかしたり、なんだかんだやっていたら、大変な難産になった。今日2024年6月16日の一日で8000行の差分が生えた。Biomeがめちゃくちゃに差分を生み出していた。
あれ
2年前に作ったサービスの開発環境を作って、ライブラリとかアップデートしたらバグった。マイナスからのスタートや。
このサービスがどうして動いていたのか分からない。2年前の私がReactを何も理解していなかったことだけはわかる。
ご迷惑をおかけしております
ご迷惑をおかけしており、申し訳ございません。
開発環境で無限ループを起こしてしまい、現在ログインがしづらい状況となっております。
- 本番環境と開発環境の認証基盤が共用されている
- 開発環境での開発中に無限ループを起こしてしまい、多量のログイン認証を流してしまった。
しばらく時間が経過すると直るものと思われますので、今しばらくお待ちいただけますと幸いです。
あれ
あれ
あれ
今更これに気づいた
TwEgakuで手書きを編集できる状態で埋め込めるのは面白そうだが、私の技術が追いついてないので、しばらく先になりそう。TwEgakuをObsidianにiframeで埋め込もうとしたがログインできなかったので、この辺を解決する技術を学ばないといけない。oEmbedとか言うのを使うと良いっぽい?
スクロールが埋め込まれた先に奪われるので、ややうっとおしそうな予感。
画面遷移で編集画面に行けるだけでも相当に便利だと思うので、これ以上何とかするモチベは少し欠けるところがある。
TwEgakuの日本語化
説明画像一覧
https://twegaku.towasys.com/d8ea86ba58444a43b79ddf2c63d6d568
https://twegaku.towasys.com/aab93698662f428ba2c1780d73427d2d
https://twegaku.towasys.com/ba0daa68512b43a7a5f22c62f99385da
https://twegaku.towasys.com/a90290898eb54694b301e21ae16b1eb7
https://twegaku.towasys.com/3b32a338e8f14807bf3c0ec85d9cf23e
https://twegaku.towasys.com/90b08368e39b4785868a9d3fa119d343
https://twegaku.towasys.com/7c59616c092844aa9c1ccad3f34b91aa
TwEgakuに向けたご感想・ご意見
あれ
TwEgakuで描いたものが保存されなくなってた。
サービスが動かない状態で2か月放置してたってマ?
2か月ぶりにプログラム見てるからなんもわからんになってる
nginxの設定を「ワー」ってしたらなんか直った
なんもわからん
多分キャッシュが悪い
こいついつもキャッシュのせいにしてんな
あれ
あれ
あれ
TwEgaku リリースノート
2023年1月8日
- サーバーにいい感じのキャッシュプログラム(octpepper)を構築
- バズっても大丈夫(なはず)になった
- 検索の高速化にも使えるはずなので、追々やりたい
2023年1月5日
- トップページの説明用画像をクリックすると、
https://twegaku.towasys.com/undefined
にリダイレクトされるバグを無理やり修正- 問題の原因は大体洗い出したが、良い解決法が見つからなかったためいったん臭いものにふたをした
- なぜかリンクから遷移したときに
/[board_id]
リダイレクトされない- 要求ヘッダーが想定した値になっていない
- なぜか
getServerSideProps
でcontext.res.end()
後にウェブページのレンダリングが生じる - なぜか
getServerSideProps
からpropsで渡したboard_idの値が取得できず、undefinedになる
- なぜかリンクから遷移したときに
- 再発したら根治を目指す
- 問題の原因は大体洗い出したが、良い解決法が見つからなかったためいったん臭いものにふたをした
2023年1月5日
- boardの新規作成後に、最初の手書きが消えるバグを修正
- 無限ローディングが起こっていた
2023年1月4日
- ダークモード対応
- 上部メニューの歯車からダークモードを設定可能
2022年12月24日
- pngファイルの出力を高速化
- SNS(特にFediverse)にTwEgakuのリンクを投稿しても、サーバーが止まりにくくなった
- まだ最適化の余裕があるので、負荷が問題になってきたら頑張る
- WebPの出力に対応
- ~.svgを~.webpにすると使える
- pngの10%ぐらいファイルサイズが小さい
- エンコードがpngより時間がかかるらしいけど、それ以外にかかる時間の方が圧倒的に長いので、ほとんど差がない
- リンク投稿時のサムネイル画像はこちらにしておいた
2022年12月22日
- Share機能を追加し、ブラウザが対応していれば、Twitterなどに共有できるようにした
- トップページで手書きを試せるようにした
- ドロップダウンメニューのデザインを変更
- 消しゴムのサーバー負荷を軽減した
- Firefoxでログインできないバグを修正
- Android Chromeでドロップダウンメニューを閉じられないバグを修正
2022年12月21日
- TwitterでTwEgakuのリンクを投稿すると、サムネイルとして画像が表示されるようにした
- UIのボタンを大きくして押しやすくした
- 検索できないことがあるバグを修正
- 非ログイン時にboardに表示される、トップページへのボタンを変更した
2022年12月20日
- ログインした状態でブラウザーを再起動すると、トップページでリダイレクトを繰り返すバグを修正
- 消しゴムの当たり判定を表示
- 消しゴムを早く降ると、当たり判定が大きくなる機能を追加
- 検索アルゴリズムを変更
- 検索精度が上がってるはず……
2022年12月19日
- たくさん書くとカクついていたのをカクつきにくくした
- WebGL2での線の描画を高速化した
- トップページの手書きの例を増やした
2022年12月18日 午後
- 手書き検索の速度をアップ
- 手書き検索の精度をアップ
2022年12月18日
- 手書きの描画を高速化
- 描画をSVGからWebGL2.0に移行
- スタイルを当てて、見た目を変更してた人には影響があるかも
- ポリゴン描画方式の変更で、手書きにブツブツが出なくなった
- 手書きの追従性UP
- 書く時の快適度が上がった
- 視点移動が滑らかになった
- 手書きが多くなるとカクつきがちだった。特にChromeで
- 描画をSVGからWebGL2.0に移行
- 消しゴムの処理を改善
- 線がすぐ消えるように変更
- 通信失敗で「消したのに消えてない」が起きる率を低減
- サーバーの負荷軽減
- まとめて削除命令がサーバーに飛んでいたので、処理が重たかった。時間方向に分散させた
2022年12月16日
- なげなわで手書きを選択して検索する機能を追加
- PWA起動時のリダイレクトを不要にした
- 内部品質向上
- 視点移動アルゴリズムのリファクタリング
- 「移動 → 拡大縮小 → 移動 → 移動」 ってなってたのを一つの行列にまとめた
- 処理が軽くなるかと思ったがそれほど変わらなかった
- headerとfooterの固定方法(CSS)を
fixed
からflex
に変更- headerやfooterに要素を追加するのが楽になった
- 視点移動アルゴリズムのリファクタリング
2022年12月14日
- トップページのデザインを変更
- ロゴを表示
- 手書きの例を表示
- 登録時のパスワード要件を変更
- 特殊文字を不要に変更
- パスワードの文字数を最低8文字以上から最低10文字以上に変更
2022年12月13日
- 手書き一覧画面(boards)で、手書きの量が多いboardの視認性を向上
- 線の太さを一定にした
- 手書きの表示時に、作成者でなければ広告を表示
- 作成者が編集する際には広告は表示されないので邪魔になることはない
- ログイン時にboardsへのリダイレクトを早くした
- 検索機能使用時の通信量と描画負荷を低減した
- 手書き画面で表示領域を記録し、再表示時やほかの人が表示する際に過去の表示領域を再現
2022年12月12日
- 意図しない線が描画されるバグを修正(消しゴムの軌跡が描画されていた)
- ボード(手書き)の一覧画面の通信量を削減(svgファイルをサーバーから取得するのではなく、軌跡データをサーバーから取得して、それをsvgとして描画するようにした)
- ボード(手書き)の一覧画面の描画負荷を削減(軌跡データをsvgのpolygonで描画するのではなく、svgのpolylineで描画し、svg内の要素数を削減)
2022年12月11日
- 画像ページ(/[board_id])での視点移動・拡大縮小を実装
- ~~.svgのファイルに背景色を設定し、SNSでカード表示されたときに見やすくした
2022年12月10日
- OGPに対応し、SNSなどにURLを投稿すると、画像などの情報をカードで表示
- ~~.svgにアクセスすると、編集可能なデータであればそのまま編集可能にした
- iOSで画面端をスワイプすると、画面を戻れるようにした
- PWAに対応し、インストールできるようにした
- svgファイルのサイズを約半分に小さくした
2022年12月9日
- 指での手書きを無効化するボタンを追加
- 手書きの一覧表示画面追加
- svgファイルのホスティング機能追加
- 利用者認証機能追加
- 検索機能追加
- 線の平滑化機能追加
2022年11月27日
- iPadでの拡大縮小を無効化
- iPadでの指での手書きを有効化
- iPadでApple Pencil使用時にスクロールする問題を解決
2023年1月5日日記
朝早く目が覚めたのでTwEgakuのバグを修正しておいた。
8:30になって会社に向けて家を出た。
転職先(新しい会社)(R社)の入社日だった。
3人から入れ代わり立ち代わりに会社や手続きなどの説明を受けた。疲れた。3対1なので圧倒的に集中力に彼我の差がある。よく耐えた。
朝10時から同じ部のみんなで初詣に行った。
11時ごろから新年会(昼食会)だった。酒(ビール)を飲んでる人も結構いた。ワーオ。緩いぜ。私は酒に弱くて1杯で結構酔うので、烏龍茶で済ませておいた。偉い。
だいたい定時で退社した。勤怠をつけるのを忘れた。こういうのは大体忘れる。翌日修正をシステムに登録することとする。
帰宅途中にマクドで適当にセットを食べて帰った。
帰宅してすぐにシャワーを浴びた。めっちゃ偉い。
デライトの待欄を見てたらTwEgakuのバグ報告をいただいていたので直す。仕事終わりにめっちゃ作りこむの大変なのでちまちました修正が多くなりそう。
明日に向けて早寝したいが眠気がない。眠気を養う。
あれ
次ノートPC買うならMacbookかしら。
iOSアプリ開発体制構築計画。
TwEgakuで収益が上がったらiOSアプリ作りたい。Apple Pencil(第2世代)のダブルタップに対応させたいという欲がある。
iOSアプリうんぬん以前に、利用者増やさねばなぁ……
iOSアプリを作れば利用者増えるだろうか。
あれ
TwEgakuも検索流入したいけど、内容が語じゃないからGoogle検索不能なんだよな……
SNSなどからの流入・口コミをやっていくしかない。ほかの手も考えたい。
いや、せめてTwEgakuのトップページがGoogleに掲載されてほしい。
TwEgakuをObsidianにiframeで埋め込もうとしたがログインできなかった
Obsidianに外部サイトをiframeで埋め込む話を見かけて、「TwEgaku埋め込めば文書内に手書き可能な手書きを埋め込めるじゃん」「SNSで共有したらバズりそう」などと思ったが、iframeで埋め込んだTwEgakuでログインするとリダイレクトが繰り返される(遷移先でログイン状態を維持できない)バグが発現するのであった。
『iframe内にログインの必要なページを表示すると、ログインができないのですが、一般的に起こる現象でしょうか?対処法はありますか?』という話もあり、そもそもiframe全般としてログインするシステムと相性が悪いらしい。
ObsidianでDynalistを使う話も見つけた。Dynalistはログインが必要なサービスなので、何か方法があるのかもしれない。
と思ったが、Dynalistでログインを試したらこちらもログインができなかった。まそっぷ。
iPadのObsidianだからダメなのかと思い、WindowsのObsidianを試したが、これもダメだ。
調べたらObsidian側にバグ報告されていた。『Can no longer login a Google account inside iframet』
手書きのPNG変換にかかる時間
開発機
convert-svg-to-pngを使う場合
SVGの描画:14秒ぐらい。
PNGの描画:1秒ぐらい(実際はSVGの生成の時間が乗っかるのでトータル15秒ぐらい)
PNGの生成に時間がかかっているかと思ったが、そもそもSVGの生成が大変遅い件。JavaScriptでSVGを生成しているのでそれもそうか。
力技でWebGL2を使ってPNGに変換する場合
SVGの描画:しらね
PNGの描画:400msぐらい(トータルで)
大変な力業でサーバーサイドでWebGL2を走らせて変換してるので、大変に保守性が低い。なお開発環境は強めのGPUが乗っかっているが、サーバーにはGPUはない模様。CPUでもWebGL2動くはずだからええねん。
手書きデータの画像化
開発環境負荷試験用画像
TwEgakuでの手書き検索の様子
あれ
TwEgaku利用者増やしてぇですわよ
ウェブアプリだけじゃなくて、Androidアプリ、iOSアプリ作って、アプリストアに公開した方が利用者増えるかしら
Androidアプリは作る意味薄いし、iOSアプリはApple Pencil(第2世代)のタップ対応のために作りたいけどアプリストアの年貢がキツイ
年貢を支払える見込みがあるならいいんだけども
どっかのインフルエンサーが紹介記事とか書いてバーッて広まらんかのう……
< URL取得時に+が付いたらいいなあ
TwEgakuのWebGL化
あれ
WebGL2.0で三角形が描画できたッ!
人様のサイトに従って書いただけでなんとかなった。ありがてぇ……
https://webgl2fundamentals.org/webgl/lessons/ja/webgl-fundamentals.html
見よ!この長大なプログラムを!
gl2 = canvas.getContext('webgl2');
if (!gl2) {
console.log('webgl2 is unsupported');
return;
}
console.log("webgl2 is supported");
const vertex_shader = createShader(gl2, gl2.VERTEX_SHADER, `#version 300 es
// an attribute is an input (in) to a vertex shader.
// It will receive data from a buffer
in vec4 a_position;
// all shaders have a main function
void main() {
// gl_Position is a special variable a vertex shader
// is responsible for setting
gl_Position = a_position;
}
`);
const fragment_shader = createShader(gl2, gl2.FRAGMENT_SHADER, `#version 300 es
// fragment shaders don't have a default precision so we need
// to pick one. highp is a good default. It means "high precision"
precision highp float;
// we need to declare an output for the fragment shader
out vec4 outColor;
void main() {
// Just set the output to a constant reddish-purple
outColor = vec4(1, 0, 0.5, 1);
}
`);
const gl2_program = createProgram(gl2, vertex_shader, fragment_shader);
const position_attribute_location = gl2.getAttribLocation(gl2_program, "a_position");
var position_buffer = gl2.createBuffer();
gl2.bindBuffer(gl2.ARRAY_BUFFER, position_buffer);
// three 2d points
var positions = [
0, 0,
0, 0.5,
0.7, 0,
];
gl2.bufferData(gl2.ARRAY_BUFFER, new Float32Array(positions), gl2.STATIC_DRAW);
const vao = gl2.createVertexArray();
gl2.bindVertexArray(vao);
gl2.enableVertexAttribArray(position_attribute_location);
var size = 2; // 2 components per iteration
var type = gl2.FLOAT; // the data is 32bit floats
var normalize = false; // don't normalize the data
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0; // start at the beginning of the buffer
gl2.vertexAttribPointer(position_attribute_location, size, type, normalize, stride, offset)
console.log({gl2_canvas:gl2.canvas});
// webglUtils.resizeCanvasToDisplaySize(gl2.canvas); // webglUtilsが見つからないためコメントアウト
// webglUtils.resizeCanvasToDisplaySize(gl2.canvas); と同等と思われる処理を追加
gl2.canvas.setAttributeNS(null, "height", `${gl2.canvas.clientHeight}`);
gl2.canvas.setAttributeNS(null, "width", `${gl2.canvas.clientWidth}`);
gl2.viewport(0, 0, gl2.canvas.width, gl2.canvas.height);
// Clear the canvas
gl2.clear(gl2.COLOR_BUFFER_BIT);
gl2.clearColor(1.0, 1.0, 1.0, 1.0);
// Tell it to use our program (pair of shaders)
gl2.useProgram(gl2_program);
// Bind the attribute/buffer set we want.
gl2.bindVertexArray(vao);
var primitiveType = gl2.TRIANGLES;
var offset = 0;
var count = 3;
gl2.drawArrays(primitiveType, offset, count);
function createProgram(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
var success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
function createShader(gl2, type, source: string) {
var shader = gl2.createShader(type);
gl2.shaderSource(shader, source);
gl2.compileShader(shader);
var success = gl2.getShaderParameter(shader, gl2.COMPILE_STATUS);
if (success) {
return shader;
}
console.log(gl2.getShaderInfoLog(shader));
gl2.deleteShader(shader);
}
if (canvas && canvas_geometry.canvas_x && canvas_geometry.canvas_y && canvas_geometry.canvas_width && canvas_geometry.canvas_height) {
const clientRect = canvas.getBoundingClientRect();
const scale = Math.min(clientRect.width / canvas_geometry.canvas_width, clientRect.height / canvas_geometry.canvas_height)
const x = (canvas_geometry.canvas_x - (canvas_geometry.canvas_width * scale) / 2) + clientRect.width / 2;
const y = (canvas_geometry.canvas_y - clientRect.height / 2) + (canvas_geometry.canvas_height * scale) / 2;
const scale_center_x = clientRect.width / 2 - x;
const scale_center_y = clientRect.height / 2 - y;
// canvas_move_to(canvas, x, y, scale, scale_center_x, scale_center_y);
}
あれ
やはり大量の手書きの軌跡を描画して滑らかに視点移動しようとすると、泣きながらWebGLを触るしかないのか。
下手にライブラリを使うよりも、生のAPIを薄々で使った方が速いし、素性が良い。ただし地獄。
「WebGL行くぞッ」と思ってもWebGLとWebGL2.0があり、どちらも情報が薄い。獣道がうっすら見えるだけで知の高速道路をウェイできない。
Two.jsを試したが、期待する視点移動速度は得られなかった
WebGLで描画するように設定しても、ChromeではSVG並みに遅い。
group#Two.Groupに全描画要素を入れ、以下のコードを実行
group.scale = scale;
group.position = = new Two.Vector(scale_center_x - scale * scale_center_x + canvas_x, scale_center_y - scale * scale_center_y + canvas_y);
コードを見てみたところ、JavaScriptで行列の積算が行われている。そりゃ遅い。Shaderで演算されることを期待していた。
https://github.com/jonobr1/two.js/blob/ea7491d0b2741dde4f62f5fedf035910368ac433/src/matrix.js#L251
2022年12月14日日記
あれ
TwEgakuではオブジェクト消しゴム以外、というかなぞった個所だけ消せるピクセル消しゴムは実装しない予定。お絵描きアプリはもっといいアプリがほかにあるし、私が絵をかかないのでお絵描きアプリを作るのも難しい。
消しゴムの潔さも良い
他のドローツールの使い勝手の理解に乏しいが、少なくとも自分の知ってる消しゴムツールとは、なぞった部分を正確に消す律儀さがあり、使いにくさを感じるものであった。
TwEgakuはエイヤッで消せるので、書き直しの爽快感が自分の性に合っている。
GyazoからTwEgakuに拝借したもの
- 爆速共有という価値観・あり方。
<img>
経由でアクセスするとファイルの内容が返される一方で、ファイルのアドレスにブラウザでアクセスすると普通のウェブサイトとして見られる機能。- https://i.gyazo.com/1e7ecef40774e6184d5d4f48e9f3cb40.png にアクセスするとウェブサイトとしてみることができる。一方で
<img src="https://i.gyazo.com/1e7ecef40774e6184d5d4f48e9f3cb40.png" />
も機能する。マジ神機能。 - これをパクッて、
~.svg
にブラウザでアクセスすると作成者は編集できるし、それ以外の人にはトップページへのボタンと広告付きのページを表示してある。自画自賛だし拝借した機能だが神機能。
- https://i.gyazo.com/1e7ecef40774e6184d5d4f48e9f3cb40.png にアクセスするとウェブサイトとしてみることができる。一方で
あれ
手書きであることと、手書きで図を検索できるという性質によって、既存の手書きノートを代替してしまいたい。つまるところ学生が狙いだ。キーボード入力ができなくても、というか文字で表せないものでも、描くことができる。授業では図を描くことが多いだろうし、簡単なマークをつけて重要なところを示したりしたい。
学生にiPad利用者が多い(いわゆる学タブ)そうだが、さすがに富裕層でもなければApple Pencilは持っていないだろう。筆圧のないスタイラスを押していった方が母数が大きいかもしれない。
日本の学生が脳内にあるが、全説明・UIが英語になってるのが気になってきた。追々日本語対応したい。ただ、UIを考える上では英語で作っておかないと後で困ることになる。日本語の文言は小さくなりがちなので、英語にするとデザインが崩壊する。
TwEgakuの機能追加はそろそろ打ち止め
諸々、粗が目立つようになってきたので、それらの改善に力を入れる。派手な機能変更はそろそろ打ち止めになり、こまごましたところを改善していく。
コードの匂いや、検索品質や、大量に手書きしたときの視点移動の重さ、トップページのデザインの悪さ、周知戦略、などといったところが気になってきている。
模倣でもされない限りは手書きでの輪郭法の導入も見送る。正直デライトでやればよい。というかデザインを含めた統合が難しすぎる。今のところ良い方法が思いつかない。デライトの凄さを思い知る。
模倣者が出るほど流行るといいなぁ……というかそもそもGyazoのリスペクト(模倣)だったりするので、模倣されてもなんも文句が言えない。
模倣されて敵わないとなったときには……フフフ……実は隠し玉がある。
『次世代手書きメモサービス「TwEgaku」を知ってるかい?』
< 修正いたしました
ご迷惑をおかけします。ご報告に感謝します。
TwEgakuのパスワード要件から以下の点を変更しました。
- 特殊文字を無くす
- パスワードの文字列を最低8文字から最低10文字以上に変更
Chromeのパスワード自動生成でも問題なく動くことを、こちらの方で確認いたしました。
もし引き続き問題がありましたらご連絡ください。
現在のパスワード要件
- 10 文字以上
- 少なくとも 1 つの数字を含む
- 少なくとも 1 つの大文字を含む
- 少なくとも 1 つの小文字を含む
あれ
TwEgakuのトップページに既存の手書きを表示するのはすごくよさそうです。
「トップページの説明とかを充実させないといけないなぁ」と思っていたのと、「他の人の手書きを見たい」(監査のためにも)と思っていたところでした。複数の問題を解決が解決できそうです。
ただ秘匿情報は書けない仕組みになってしまいますね……。ちょっと検討します。
私の手書きの一部を選択して表時するだけでも、サービスの説明としてかなりマシになりそうな感じはします。
てか表紙絵の仕組みがすげえ。なんで文字として選択できるんだ…
どういう動作なのか詳しく教えてもらえると嬉しいです。完全にこちらの意図していない挙動なので、良さそうなら残すためにもどんな動作なのか知っておきたいです。
現時点での予想では、Safariが画像認識して文字選択できるようにしている気がします。
広告導入したら戦車の車窓みたいになってきた
あれ
あれ
あれ
ウェブアプリとか作って儲からない経験をしてると、私を雇用してる会社が雇用できるだけの収益上げてんのすげぇなと思う
あれ
手書きをSVGに変換してるけど、スクショとったときのPNGよりファイルサイズでけぇぞ!!
PNGの2倍はあると思っていただきたい。何とかしたい。
手書き検索機能と手書き一覧機能はSVGファイルを取りに行ってるので、SVGファイルがでっけーと、サーバーの帯域食うし、モバイルネットワークでアクセスするの躊躇するしでいいことがない。
サーバーから軌跡データを配信して、それをブラウザ側で描画すれば相当マシになる(気がする)のだけど、それをやると、<img>
のloading="lazy"
に頼って手書き一覧画面で1000枚とか表示してるので、負荷がすごいことになる。
あれ
手書き検索の処理をローカルPCで試してるんだけど、1つ書くごとにPCがうなりを投げてる。その割に検索精度が低い。
検索に使う特徴量を事前計算して、さらに索引にすれば処理の負荷が減らせそうなんだけど、現時点では検索精度向上に向けた開発を高速化するために毎回特徴量を計算してる。
手書きの図の類似度判定は、離散コサイン変換してその係数のユークリッド距離を取ってる。いろいろ試したけどこれが一番精度が良い(なお精度が低い)。オートエンコーダーが脳裏をよぎる。ニューラルネットワークやりたくねぇずら。
検索精度向上のために、手書きの軌跡を結合してたらサーバープログラムが落ちた😇
あれ
デジタル機器上を用いた手書きによる個人知識管理を思いついた。
当初、手書きしたデータをデライトに貼り付けて、引き入れによる整理と、文字による検索を考えていたが、そうするよりも手書きした図画を記号として扱って、手書きで図を検索する方がよほど直感的ではないかと考えるようになった。
確か画像の指紋というだったり、特徴量といったものがあったはずで、それらを事前に計算しておき、インデックスのように扱うことで、手書きの図で手書きの図を検索できるはずだ。
手書き画像の高速共有がkakeru.appで実現されていることが発覚し、手書き共有ウェブアプリ TwEgaku(仮)開発のやる気を失っていたが、個人知識管理サービスに昇格することで、より良いものにできる見通しが立ち、再びやる気が出てきた。
あれ
手書き共有ウェブアプリ TwEgaku(仮)で実現しようとしていた「雑な絵や手書きの図をとにかく早く共有したい」のほとんどをkakeruが実現していることが発覚した。というかもうこれでいいんじゃないかと思える。
筆圧が無いのでつけたくなるけど、実はなくてもいい説がある。
デザインをもう少し自分好みに寄せられると良さそう。
kakeruでできること
✓手書き
✓消しゴム
✓拡大縮小
✓ピンチで拡大縮小
✓ペンのみのモード
✓svgで共有
✓pngで共有
✓リアルタイムで複数人で編集
✓画像のアクセス制御
✓書いた画像の管理
kakeruに欲しい機能
○ 筆圧対応
○ hogehoge.svgに直接アクセスしたら広告とか表示
○ 2本指で移動
○ 上のボタンのサイズとかデザインとかいい感じにする
○ ペンのボタン(ダブルタップ)で消しゴムに切り替え
○ PWA対応
○ 背景色設定対応・背景色継承
○ 板の引き入れ
○ 特定ユーザーのみのアクセス権限
GoogleKeepでよくなる
○ 線にリンク付与
○ 文字認識
○ 手書き検索
○ .svgのページに編集画面へのリンク
○ .svgの更新高速化
あれ
iPad mini 6のSafariでevent.touches[0].forceが0になるんですけどぉ……これってぇ……Androidと揃ってなくて困るんですよねぇ……
iPhoneだとタッチの強さが取れるらしいし(未検証)、ウェブアプリで手書きアプリ作るの、沼っぽいな?
というか同じAndroidでも、S22Uだとevent.touches[0].forceが1になって、Pixel 4aだとタッチの強さが取れる(という報告があった・未検証)みたいな差異があるらしくてぇ。
ウェブアプリで手書きアプリ作るの、沼っぽいな?
ゆっくり書くと滑らかに、急いで書くと直線になる
指を動かす速度がゆっくりだと滑らかな曲線が描けますが(画像上の円)、ササッと書こうとすると直線を繋いだような軌跡になります(画像下の図形)(既知かな?)。
実行環境
実行環境を追記しました。
- 実行環境
- Pixel 4a
- Android 13
- Chrome 107.0.5304.105
- 親指で描画
あれ
あれ
iPadとApple Pencil(第二世代)欲しい。
iPad mini 6とApple Pencil(第2世代)買うのが一番安上がりっぽい?
正直なところ、手書き共有ウェブアプリ EGAKU(仮)の検証用機材としてほしいだけなので、中古でいいので、可能な限り安く手に入れたい。
ブラックフライデーで安くならんかな……
iPad miniの中古をmercariで見てみたけど、全然値下がりしてないな。
Amazonの新品で67,740円、mercariの中古最安値で63,000円。
Amazonの新品で67,740円ってこれ、ブラックフライデーで安くなってこの値段なんか。
んー、検証機としてほしいだけだと買うのにGoサインが出ないな。
絵を描く趣味とかあったら即決でGoサイン出たかもなんだけど、残念ながらそうじゃない。
絵を描く人たちにとっては、iPadとApple Pencilは超安価な液タブみたいな扱いと聞く。しかも持ち運べる。
iPad mini 6、ぽちっちゃった
あれ
手書き共有ウェブアプリ EGAKU(仮)の要件を考えている。
成功基準が機能一覧になってんのが気に食わないな。事業としての成功基準を書いた方が良さげ。意識が作る側である下請けに引っ張られてる。下請け根性。
成功基準に欲が出てきた。
邪悪な仕様が生えてきた
画面下部にバナー広告を入れること
手書き時の誤タッチによる収益増加目指す
ちょっと緩和させる。主要な利用者が俺なので、俺が使うときに切れるようだったら下部バナーやめとく。
画面下部にバナー広告を入れること
手書き時の誤タッチによる収益増加目指す
あまりに邪悪な場合は画面上部とする
利用者登録・管理が可能なこと
さらっと書いたけど、一等めんどくさいぞ
利用者登録・管理が可能なこと
利用者が過去に手書きした画像を一覧で表示できること
利用者が過去に手書きした画像を後から追記して手書きできること
作るのがめんどくさい。なんとかしてこういう仕様を迂回したい。
認証の作成を回避する仕様がなくはないけど、使いづらくなるな。あきらめて認証周りを作るか。
認証作るのめんどちっちだから、Amazon Cognito使っちゃおうかしら。
50,000 アクティブユーザー/月が無料
foooへいへーい。
50,000 アクティブユーザー/月って、趣味プロダクトでこれだけいけたら大大大成功の部類では。
TwEgaku
- TwEgaku
- 手楽
- 手書き+描く
- さり気なくt_wさんの名前を入れてみた
あれ
RE:EGAKU所感
iPad上のSafariでApple Pencilを用いて手書こうとすると,筆の動きが「描画欄への入力指令」と「頁の縦方向の移動指令」と重なって捉えられてしまい,描きづらい。これはSafariの問題かもしれない。全画面 (Fullscreen API) にできると良いかもしれない。
筆先をゆっくり動かしたときにギザつくのが気になる。SVGの<line>要素を繋げて筆記線にしているようなので,細微な描画が苦手なのはしかたがないが,丁寧な斜め線を描きたいときなどにかなり汚ない線になってしまう。
iPadとApple Pencilの手持ちがないので試験できないんですよね。実装が進む前に、iPadとApple Pencilを中古でもいいから手に入れるべきか、悩んでいます。
手元のAndroid Chromeだとそれなりに綺麗に動いてます。
斜めに書くとギザ付くのは、特にPCのマウスポインターで確認してます。斜めにゆっくり動かすと、ポインターの移動方向が(1,0),(0,1),(-1,0),(0,-1)に丸まってしまって、それで線がギザギザになってます。プログラム側である程度補正はできる気がしているので、検討中です。
現状の方針としては「きれいな線や絵を書きたい」ではなく、「雑な絵や手書きの図をとにかく早く共有したい」に焦点を当てているので、改善は後回しになりそうです。
拡大すると画面を移動できなくなるが,それで良い。設計図を書くとかそういう複雑な目的に使うわけじゃないだろうし,この方面の多機能化はあまり良くない気がするので。むしろ,二度繰り突く (double click) ことで,共有画面がパッと開くくらいの挙動が良いかもしれない。
拡大・スクロールすらいらないと思っているので、そういう風に設定してあります。手元のAndroid Chromeだとそう動いてますが、やはりiPadのSafariだと挙動が違うみたいですね。
『手書き共有ウェブアプリ EGAKU』と『t_wの輪郭』の同居問題
あれ
手書きできる画像アップローダーみたいなのを考えてるんだけど、考えることが多い。DBどうしようとか、利用者登録管理どうしようとか。
ナウでヤングなやり方を考えるなら、クラウドでマイクロサービスでウェイするのがいいんだけど、それするとお金がドバドバ出ていく。
VultrのVPCでDockerを動かしてマイクロサービスやーってやったら安くつきそうな気がする。
そう考えると、『t_wの輪郭』のシステムもDocker上で動かしたくなる。
やることが……やることが多い……!!
ブログシステムのDocker化、ベンダーに頼むと2人月とか取られるやつじゃんね。規模によるけど。4万ページあるし、ブログ移行としては超大規模案件では?ページ数でみるとやたらデカいけど、システム的にはDBとNode.jsだからそんなにか。
問題は作業者(t_w)にDockerの知識があんまりないってことなんだよな。『t_wの輪郭』のDocker化で知識をためつつ、手書き共有ウェブアプリ(仮) EGAKUの準備を進めるという形が綺麗か。
Docker使うと依存する技術が増えて面倒じゃんというのもある。
追加したい機能
SVGをホスティング
PNGをホスティング
記録して編集しなおし
消しゴム
SVGをJPGかPNGに変換
手書き結果がPNGに10秒ごとぐらいで反映
✓polygonでいい感じに描画
あれ
あれ
Samusung NotesからGyzoに共有して、デライトに貼り付けるの、なめらかで良い
でも、もっとなめらかにできそう
デライトで手書きできたら良い
輪郭法と手書きって相性がいいかもしれない
録画した動画を見てみたけど、gyazoのURLいじるのめんどっちいな
スマホに最適化された画像アップローダーが欲しくなる
というか、手書き共有ウェブアプリとかあれば便利なんだな。