FileMakerでサムネイル画像のタイルビューを作った その1

FileMakerで作るメディア管理システムに、サムネイル画像をタイル状に配置するビューを作ります。段階を追って少しずつ進めますがここは第一回、最初の基本、タイル状にサムネイルを並べることだけを目指します。

(2023年11月 改訂)

FileMaker でタイルビューを実現すること

FileMakerではレコードをタイル状に並べることができないので、一般的な画像管理アプリのようなビューを作れません。ナンチャッテでは作れますが、機能としてありません。かつてポータル機能ができたとき「いつかポータルを横方向やタイル状に並べられるようになるに違いない」と期待しましたが無駄でした。

Aperture tile view
こんな感じのタイルビューを誰もが欲します。

FileMaker Pro 19 のアドオン、写真ギャラリー

FileMaker Pro 19 から、アドオンでいろいろ機能を追加することができるようになったそうです。そうした新機能紹介の中で一際目を引くのが写真ギャラリー。

FileMaker のアドオン使ってみた – 写真ギャラリー編 <前編>  ←こういうページが用意されていました。

この機能が使えるv19ですが、OSの最低条件に満たない筆者はインストールすることもできませんでした。そこで「どうせこんなのナンチャッテ表示だし、使うための手続きも面倒そうだ。きっと酸っぱいんだろうな。あー酸っぱい。あー酸っぱい」と負け惜しみます。

Penguin icon その後 v19で写真ギャラリーのアドオンを使ってみましたが、「こういうことも出来ますよ」的なデモのようなものでした。

最初のタイルビュー – v19にしなくてもできるもん

悔しがってないでナンチャッテタイルビューを作ってみようと奮起し、Webビューアを使ったタイルビューに挑戦し、出来上がりました。

この投稿には出来上がったファイルとその作り方が書かれました。

一旦は満足しましたが実践的に実用することが困難だと思い知ります。いくつかの問題があり、上手い解決法も見つからないまま試みを一旦中断して、そのまま放置しました。

—- ここで数年経過 —

別件のメディア管理も育ってきたことだし、そろそろタイルビューに再挑戦しようと思い立ちます。それで、この投稿を全面的に書き換えることにしました。

徐々に育てるシリーズを開始

改めて仕切り直し、タイルビューに挑んでいきます。

メディア管理と同じように、基本の簡単なファイルから始めて、徐々に育てていくことにします。こうすることで、機能と仕組みを把握し理解することの手助けになります。

ということで再スタート。ナンチャッテタイルビューの最も基本のところから始めようと思います。投稿の書き換え前はもう少し機能がありましたが一旦なしにします。

 

ではその1行きます。

メディア管理との関係

その前にテストファイルの構成について補足があります。

タイルビューはあくまで表示の仕組みであり、それだけで独立したデータベースではありません。画像管理・メディア管理なしには成り立ちません、というかタイルビューのテストファイルはメディア管理DBそのものです。

にもかかわらず、タイルビューだけ切り離して作っていこうとしています。他のFMファイルへの組み込みやコピペ転用のし易さ、実用を目指すからです。

ということは、どうするかというと、どうしましょう。

メディア管理の部分をできるだけ単純化し、タイルビューと関係あるところだけを作る以外にないような気がします。それでいきましょう。

メディア管理部分を次のように定義して、フィールドやスクリプトをバッサリそぎ落とします。

メディア管理の代替品、仮の簡易版と想定する

他に存在しているちゃんとしたFMメディア管理があり、暫定的にそれを模した簡易版という想定にします。タイルビューを作るための土台としてのみ存在する仮のメディア管理で、後にちゃんとしたメディア管理に組み込むときにどのフィールドが必要かの目安にする役割です。

どのフィールドがタイルビューに必要ですか。それは次の通り。

プレビューイメージ(previewImage)

通常、メディア管理にはメインとなるオブジェクトフィールドがあります。ファイルタイプが多岐に渡るため、あるいは巨大サイズであるために、閲覧用のプレビューイメージを作ったりすることでしょう。圧縮したりサイズを調整したりした画像(jpegまたはpng)です。

テストファイルでは previewImage という名のフィールドとします。

このプレビューイメージをスタート地点とします。本来あるべきオブジェクトフィールドを設置しません。よってメインオブジェクトに関わるメディア管理の機能も一切搭載しません。

プレビューイメージのサムネイルサイズ(preview256)

もうひとつ、プレビューイメージを縮小した画像のフィールドが必須になります。これがタイルビューでビューするサイズの画像です。

テストファイルでは preview256 という名前のフィールドとします。

それ以外は、データベースとして必須の ID だとかファイル名だとか拡張子とか、いくつかの基本的なフィールドを作っておきます。

タイルビューのテストファイルには以上の想定でメディア管理のメインテーブルを作成しました。

FileMaker で画像管理のタイルビュー 〜 その1

さて改めましてタイルビューを作って実用化まで持っていくチャレンジその1、最初は超基本「タイル状に並べるビュー」を作ります。

作りました。

タイルビューテスト: 準備段階
タイルビュー(tile view レイアウト)

このファイルをダウンロードできます。

Download tileview_test_1.fmp12.zip

面倒を省くため最初からいくつか画像が入っていますが、全部消したりフォルダを指定してインポートもできます。

機能: イメージをWebビューアでタイルビューする

テストファイルでは tile view という名のレイアウトがタイルビューです。

機能は、サムネイル画像をタイルビューします。ただビューするだけです。クリックしても何も起きません。何の仕掛けもありません。

仕組み: WebビューアにHTMLを表示する

仕組みは、Webビューアを配置してHTMLを表示します。

タイルビュー レイアウト編集画面

レイアウトに配置する Webビューアの「Web アドレス」にこう書きました。

"data:text/html," & mainData::HTMLc

mainData が今回のメインテーブル名です。

HTMLc というフィールドが最終形のHTMLフィールドです。HTMLcの内容がビューアに表示されます。

解説: HTMLができるまで

開発用のレイアウト

HTMLがどう作られるかは、開発用のレイアウトにまとめました。テンプレートや必要フィールドを確認、編集できます。

Details HTML layout
開発用の詳細レイアウト。テンプレートなどの確認や編集ができます

HTMLが生成される道筋

HTMLはテキストですから、最終のHTMLcフィールドには完成した最終形態のHTMLテキストがだーっと書かれます。

最終的なHTMLは計算で作られますが、そこに至るまでにはいくつかの段階を経ています。大雑把に次の3工程です。

  1. レコード単位のHTML(content)を作ります
  2. 対象レコード分の content を全部集めて contents を作ります
  3. contents を含めた全体のHTMLを作ります

1のレコードのHTMLはタイル一個分の完成形HTMLです。サムネイル画像がセットされた時点で計算により作られます。

2の対象レコード分のかき集めはスクリプトで行います。contents フィールドに 対象レコード分の content を全部集めます。

3の最終形HTMLは計算により自動で作られます。contents の他、CSSも入ります。

この三つの工程をもう少し分解すると以下になります。

  1. レコードのHTML(content)
    1. レコードのサムネイル画像をbase64テキストに変換
        →  
    2. <img>タグの構造をテンプレートに作っておき、
       <img src="data:image/<!-- type -->;base64,<!-- base64 -->">
    3. basr64テキストを置換して含む base64ImageTag フィールドを作成(実際はbase64変換も含めた計算式になっています)
      Let([
        // サムネ画像からimgタグを作る計算
        pType = If ( mainData::ext = "png"; "png" ; "jpeg" );
        base = Base64EncodeRFC ( "" ; mainData::preview256 );
        imagetag = Substitute ( mainData::base64ImageTag_template ;
       [ "<!-- ID -->" ; mainData::ID ] ;
       [ "<!-- base64 -->" ; base ];
       [ "<!-- type -->" ; pType ] ) 
      ]; imagetag )

    4. レコード一個分(=タイル一個分)の構造を singleContent_template に作っておき
      <article id="ID-<!-- ID -->">
       <div class="thumbnail">
        <!-- imgTag -->
       </div>
       <p class="title">
        <!-- fileName -->
       </p>
      </article>
    5. 内容に応じた置換で HTML(content)を完成させる
      // content 置換の計算式
      Substitute ( mainData::singleContent_template ;
        ["<!-- ID -->" ; mainData::ID ] ;
        ["<!-- imgTag -->" ; base64ImageTag ] ;
        ["<!-- fileName -->" ; mainData::fileName ]
       )
      

  2. 対象レコード分の contents を作成
        1. 対象レコード分すべての content を & で繋げて contents フィールドに網羅します。スクリプトが担当します。対象レコードを変更する度にスクリプトを走らせ網羅し直すことで「ビューの更新」となります。
  3. 全体のHTML
    1. 全体のHTMLの構造を HTML_template に作っておき
      <!DOCTYPE html>
      <html lang="ja">
       <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style><!-- css --></style>
       </head>
      <body>
       <div class="contents">
        <!-- contents -->
       </div>
       <script>
        <!-- script -->
       </script>
      </body>
      </html>
    2. contents(とCSS)を置換して最終形HTMLを作成
      // HTMLc の計算式
      Substitute ( HTML_template ;
      ["<!-- css -->" ; css_min ];
      ["<!-- script -->" ; script ];
      ["<!-- contents -->" ; contents ]
      )

※ テンプレートでは、置き換える部分をコメントの形で書いておき、Substitute関数によって実際の値やフィールド内容で置換するのが基本処理です。

※ 構造をテンプレートに書くことで表示する内容を決定します。要となるレコード単位の完成形HTML … content_template は次のようになってます。

<article>
 <div class="thumbnail">
  <!-- imgTag -->
 </div>
 <p class="title">
  <!-- fileName -->
 </p>
</article>

全体を<article>で囲んで、サムネイルとファイル名があるだけです。見てのとおり、<button>や<input>や<a>すらありません。タイルビューその1が「見るだけで何も操作できない」ことが読み取れると思います。

フィールド定義のスクショを一応挙げておきます。

フィールド定義

 

簡易なメディア管理

メディア管理の部分についてもちょっと触れておきましょう。今回タイルビューその1に関係するフィールドは preview256 と fileName と ext です。

  • mainData … テーブル名
    • ID … 必須のレコード固有ID
    • fileName … ファイル名
    • previewImage … メディアを元に作られた想定のプレビューイメージ
    • ext … プレビューイメージの拡張子(jpegまたはpng, カスタム関数で取得)
    • preview256 … サムネイル画像(previewImage を縮小したもの)
    • importPath … インポート元パス(インポート機能で使用する)

※ preview256 は previewImage から計算で生成しています。

GetThumbnail( previewImage ; 256 ; 256 )

※ ext(拡張子)を取得するカスタム関数 GetExtention() が仕込まれています。

メディア管理のメインレイアウトがあります( list view という名前です)

tileview list view layout
画像管理の画面

ソートしたり絞り込んだり通常の作業を行う想定のメディア管理メイン部分。

フォルダからインポートもできます。フォルダを指定して、その中のjpegまたはpngファイルのみインポートできます。

サムネイルをダブルクリックするとプレビュー(single view)に切り替わります。戻るときもダブルクリックでOK。

それ以外の機能はほぼありません。

その他、小ネタのいくつか

オマケです。テストファイルその1で登場した小ネタの紹介しておきます。

ダブルクリックスクリプト

FileMakerでダブルクリックを実現するアイデアは先人の賢人さまが伝授してくださっています。タイマーを使うやりかたとグローバル変数を使うやり方がありますが、後者がいいですよ。タイマー使うやり方は通常の使用でクリック間隔が近い時に誤動作連発してしまいます。

アイデア丸パクリの受け売りですが、汎用性を高めるために僅かに工夫を施してます。

FileMaker ダブルクリックスクリプト
ダブルクリックスクリプト

最初は変数を二つ、スクリプト引数から受け取ります。一つはダブルクリックで実行するスクリプト名です。2行目はクリックで実行するスクリプト名を用意します。2個目はなくてもOK。でも1個は必ず必要です。

一時停止している隙にクリックした場合に割り込みで入ってこれるというのが何故なのか実は理解しておりませんが💦

jpg と png だけインポート

インポートのスクリプトくらいは欲しかったので、複雑な「メインオブジェクトからプレビュー画像を作成するよ」の代わりに、簡単な「jpegかpngをインポートするよ」を用意しました。jpegとpngだけをどうやってインポートしたか。こうやりました。

フォルダを取得したあとはFMパスを作ってフォルダからインポートを行います。この時、ファイル名とファイルパスだけをインポートします。これが1回目のインポート。

ファイルパスから拡張子を取得してjpgかpng以外のレコードを捨てます。

次は2回目のインポート。1回目と同じくフォルダからインポートしますが、この時ファイル名とファイルパスを照合フィールドに指定して「イメージ」を「更新」します。

CSS – flex でタイルを綺麗に並べる秘訣

CSSの話です。flex でタイルを並べるわけですが、綺麗に並べるために justify-content を設定すると、最後の余り部分が非常に気にくわない結果になります。space-betweenではこんな感じ。

<div style="display:flex; flex-wrap:wrap; justify-content:space-between;">
   <div style="width: 40px; height: 40px; margin: 3px;"></div>
   <div style="width: 40px; height: 40px; margin: 3px;"></div>
...(繰り返し)
</div>

最後の行だけ左に寄ってほしいんだけど・・・。こういうときどうしましょう。こうします。

同じ幅のダミーを最後に繰り返し置きます😀

<div style="display:flex; flex-wrap:wrap; justify-content:space-between;">
   <div style="width: 40px; height: 40px; margin: 3px;"></div>
   <div style="width: 40px; height: 40px; margin: 3px;"></div>
...(繰り返し)
   <div style="width: 40px; margin: 3px;"></div>
   <div style="width: 40px; margin: 3px;"></div>
   <div style="width: 40px; margin: 3px;"></div>
   <div style="width: 40px; margin: 3px;"></div>
   <div style="width: 40px; margin: 3px;"></div>
</div>

(ここで示しているHTMLは参考用に雑に書いたものなのでご留意を)

タイルビューでもこの処理を入れています。content を束ねて contents を作るスクリプトの中で、全部繋げ終わった最後に、幅があって高さがない中身空のダミーdivを繰り返し配置しています。

次への課題

今回タイルビューテストその1では、サムネイルをタイルビューすることができました。ただそれだけで、何の操作もできません。今回は「わーい。表示できた」と喜ぶためだけにあります。

次はもうちょっと進めて、せめて何か操作できるようにしましょう。クリックしたらプレビューを表示する。これですね。次のテストファイルで実現します。

Penguin icon 続きの投稿はこちらです。

FileMakerでサムネイル画像のタイルビューを作った その2

FileMakerでサムネイル画像のタイルビューを作った その3


尚、タイルビューはメディア管理で使ってこそ意味あります。別件のメディア管理を育てるシリーズはこちら。

コメント

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください