LoginSignup
4
0

More than 1 year has passed since last update.

Mac対応の画像ビューア(comic master)をつくった React+Electron(Vite, TailwindCSS)

Last updated at Posted at 2022-08-28

成果物

comic master
※署名とかしていないので開発元を検証できません、と出る野良です。
Macの人はシステム環境設定→セキュリティとプライバシーの一番下から開いてもらえたら開けると思います。

つくった理由

mac対応のまともな漫画ビューアが無料でなかったからです。windowsだと古くはmangameeya、いまはhoney viewなどあります。macの場合はComicViewerというソフトがありますが、いまいち使用感が好きではなかったので自分でつくりました。

操作方法

  1. 画像ファイルの入ったフォルダか、zipをドラッグする
  2. 左キー、右キーでページめくり
  3. zキーで1ページ表示、右見開き表示を切り替え
  4. aキーで1ページだけ送る、qキーで1ページだけ戻す

以上です。

マウスホイール、クリックでのページめくり、それからキーバインドの変更などはおいおいつくる予定です。

今後の更新予定

  • 最後に開いたファイルを起動時に開く
  • 見開きモード、1枚表示モードを記憶する機能
  • 自動でページをめくる機能
  • 5ページ飛ばし、10ページ飛ばし
  • 3/12など全体のうちどこまで読んだのかを把握する機能
  • 最後まで読んだらループせず、そこで止まる機能(オプション)
  • マウスホイール、マウスクリックでページを送る機能

など。気が向いたときにつくっていきます。

ソースコードも置いておくので、お好みで調整してもらえれば良いかと思います。

つくっていて詰まった点

そもそも画像をアスペクト比を維持したまま中央表示にするのが難しい

これはtailwindcssを駆使して下記コードで解決しています。

<div className="mx-auto bg-slate-800 text-white overflow-hidden">
  <img src={`${pageUrlList[page]}`} alt="" className="object-contain h-screen w-screen" />
</div>

wrapperのdivにoverflow-hiddenをつけて、中の画像にobject-contain, h-screen, w-screenをつけるといい感じに画面を小さくすれば比率を維持したまま画面をはみ出さずに小さくなってくれます。

2枚表示のときはこんな感じ……。

<div className="flex justify-center">
  <div>
    <img src={`${pageUrlList[page + 1]}`} alt="" className="object-contain h-screen w-full" />
  </div>
  <div>
    <img src={`${pageUrlList[page]}`} alt="" className="object-contain h-screen w-full" />
  </div>
</div>

開発中にローカルの画像ファイルを読み込めない

electronで開発をしていると、ローカルの画像ファイルを読み込むことができません。正確にはbuildしたあとのexeでは読み込めるけれども、devでつくっているときには読み込みません。
対応策としてwebSecurityをfalseにすると動きます……ということで最初はそうしていたのですが、結局zipを解凍して読み込む部分をつくるときに、ローカルの画像パスを読み込むのではなく、readFileで読み込んだ画像をそのままURIにエンコードしています。

そのうちリファクタリングするぞ……と思いつつ書いてしまったコードがこちら。

export const getDirectoryImageFiles = async (path: string): Promise<[string[], string[]]> => {
  /* ディレクトリのファイルを読み込む */
  const files = await readDirSync(path);

  /* jpgなどでfilterする */
  const filteredFiles = files
    .map((fileName) => `${path}\\${fileName}`)
    .filter(async (filePath) => {
      const extName = await nodeExtnum(filePath);
      return enableExtnames.includes(extName);
    });

  let urls: string[] = [];

  for (const path of filteredFiles) {
    const base64 = await nodeReadFileSync64(path);
    const url = `data:image/png;base64,${base64}`;
    urls = [...urls, url];
  }
  return [urls, filteredFiles];
};

そんな感じで自分用につくったソフトですが、転職活動も兼ねて一般公開することにしました。要望があれば気が向いたときに開発してみます。

4
0
5

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
4
0