ここ数日空き時間はずっとこれ作ろうとしてる。さすがにボタン押すのでは素朴すぎるし、塗りつぶしになってて欲しいなと思っていろいろ試している。 Range とか試してたのもそのせい。
使い方の理想イメージはこういう感じで、範囲選択したら黒く塗りつぶされる(■とかで文字列置換もしてフィードリーダー対策もする)
奇しくも Range.compareBoundaryPoints の解説ページを参考にさせてもらった人が似た発想の Chrome 拡張を作ってた。でも惜しいけど欲しい物とは違うんだ。この記事っぽい見た目だけど、塗りつぶし部分のベールをはがせるようにしたい。
うまくいってない部分
DOM 要素をまたぐ場合の処理
<p>00he</p> <p>llo w</p> <p>orld11</p>
みたいな DOM 構造に対して hello
や hello world
などの文字列を選択した場合のこと。 compareBoundaryPoints を調べ始めたのもこれ対応を考えたからだが、これは難しいので「要素をまたいだ場合は処理しない」というふうに除外することにした。要素をまたいで選択しているかの判定は簡単なので。
すでに塗りつぶし済みの部分と重複する範囲を塗りつぶす場合の処理
<p>hello world</p>
という DOM 構造に対して、
- まず
llo wor
を範囲選択して塗りつぶす - 次に
world
を範囲選択して塗りつぶす
ということをする場合、塗りつぶしのたびに選択範囲を <span>
で囲う単純なやり方だと
<p>he<span>llo wor</span>ld</p> ↓ <p>he<span>llo </span><span>world</span></p>
のような DOM 構造になるが、こうなってて欲しい(<span>
要素に背景を黒にするとか文字を■で置き換えるなどの処理を施す想定)
<p>he<span>llo world</span></p>
そんなに難しくないはずだしできそうなんだがプログラミング能力が低すぎてうまくいかない。
塗りつぶしからネタバレ本文を表出させる方法
ボタンなら押せばいいだけだが、塗りつぶしだとどうするのがいいのか。ベストなのは塗りつぶし部分を範囲選択すると選択中の部分だけ■が本来の文字列に置換されてネタバレが読める、というユーザー体験だが、これも難しそうで、どういうふうにやるといいかまだ考えられていない。
次点は塗りつぶしエリアをクリック(タップ)したらオリジナルの文字列に戻る、というボタンを模した感じだが、自分用ならそれで全然構わないけど、塗りつぶし部分をマウスでクリックはともかくスマホで読んでてタップするって直感的な UI とは思えないので、あまり気がすすまない。
ともあれネタバレ感想文を書けないままだと観た映画のことをブログにかけずにストックばかり溜まってしまって精神衛生上悪いので、妥協してボタンでいいか、とも思う。想像以上に難しくて飽きてきたのと、練習用に React コンポーネントとか割と少し手に馴染むくらいに書けたのでまあいいかという気にもなっている。