まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

HTML の <textarea> に行番号を付与する jQuery プラグイン jQuery LinedTextArea を使ってみました。

<textarea> フィールドを(コーディング目的などの)テキストエディタとして使いたい場合など、行番号を付与して使いたいケースがあります。CSS と JavaScript でがんばって作る方法もありますが、jQuery のプラグインを使うことで比較的簡単に実現できそうだったので紹介します。

目的のプラグインは jQuery LinedTextArea です。ざっと探した限りで CDN が存在していなさそうだったので、リンク先から git clone するかダウンロードしておきます(最低限必要になるのは jquery-linedtextarea.cssjquery-linedtextarea.js の2つです)。


準備段階として、これらを jQuery 本体の後にロードしておきます:
<script type="text/javascript" src="//code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="./jquery-linedtextarea.js"></script>
<link href="./jquery-linedtextarea.css" rel="stylesheet"/>

  :

そして目的の <textarea> を指定して、以下のようなコードを実行します:
<textarea class="lined">
あいうえお
かきくけこ
さしすせそ
</textarea>

<script>
$(function(){
  $('.lined').linedtextarea({
    selectedLine: 1
  });
});
</script>

目的の <textarea> に "lined" というクラスを指定した上で、jQuery で $('.lined') に対して linedtextarea() を実行します。上記例では { selectedLine: 1 } というパラメータを付けて実行しています。これにより1行目が選択された状態で表示されます:
2020051200


こんな感じ。

このエントリの続きです:
Leaflet.js の UI で画像を表示する(1)


地図操作ライブラリの Leaflet.js の応用で、地図以外のオブジェクトを Leaflet の UI で表示する方法を紹介しています。前回は imageOverlay を使って画像を表示しましたが、今回は canvasOverlay を使ってキャンバス(HTML5 の <canvas>)を操作する方法を紹介します。比較の意味も含めて、表示内容そのものは前回同様に画像としますが、画像を画像のまま表示するのではなく、画像をキャンバスに描画した上で、更にキャンバスに描画を加える、という内容を紹介します。必要に応じて前回の内容も参照しながら見てください。

なお今回も表示対象画像は「いらすとや」「家にいるアマビエ」の画像とします:
amabie_stay_home


また前回紹介した内容は Leaflet.js の標準機能だけで実現しましたが、今回はアドイン機能である L.CanvasLayer を併用して実現します。以下のサイトからあらかじめ L.CanvasLayer.js をダウンロードしておいてください:
https://raw.githubusercontent.com/Sumbera/gLayers.Leaflet/master/L.CanvasLayer.js


ダウンロードできたら以下のような HTML を用意します:
<script src="./L.CanvasLayer.js"></script>

<div id="demoMap"></div>

<script>
//. 空の地図を OpenStreetMap データで表示
map = L.map('demoMap', { dragging: true, zoomControl: true, minZoom: -5, maxZoom: 5, crs: L.CRS.Simple, preferCanvas: true } );

//. 表示する画像のパスとサイズ
var image = {
  url: './3600x3600.png',
  width: 3600,
  height: 3600
};

//. 画像領域を地図に設定
var imageBounds = L.latLngBounds([
  map.unproject( [ 0, image.height ] ),
  map.unproject( [ image.width, 0 ] )
]);
map.fitBounds( imageBounds );
map.setMaxBounds( imageBounds.pad( 0.5 ) );

//. 画像をオーバーレイで設定
L.imageOverlay( image.url, imageBounds ).addTo( map );

//. キャンバスレイヤーを設定
L.canvasLayer().delegate( this ).addTo( map );
      
//. キャンバスの再描画イベントハンドラ
function onDrawLayer( info ) {
  var canvas = info.canvas;
  var ctx = canvas.getContext( '2d' );

  var colors = [
    "rgba(0,0,0,0.2)",
    "rgba(255,0,0,0.2)"
  ];
  var points = [
    [ -1000, 2000 ],
    [ -2000, 2250 ]
  ];

  ctx.clearRect( 0, 0, canvas.width, canvas.height );

  //. ズームレベルに合わせて arc の描画半径を調整
  var zoom = map.getZoom();
  var r = 30 * Math.pow( 2, zoom );

  for( var i = 0; i < points.length; i++ ){
    var point = points[i];
    if( info.bounds.contains( [ point[0], point[1] ] ) ){
      var p = info.layer._map.latLngToContainerPoint( [ point[0], point[1] ] );
      ctx.beginPath();
      ctx.fillStyle = colors[i];
      ctx.arc( p.x, p.y, r, 0, Math.PI * 2 );
      ctx.fill();
      ctx.closePath();
    }
  }
}
</script>



まず L.CanvasLayer.js を読み込みます。そして L.imageOverlay を使って画像(3600x3600.png)をロードするのですが、ここまでは前回紹介したものと同様です。

その後で L.canvasLayer() でキャンバスをレイヤーとして扱います。これでキャンバスの再描画イベントハンドラである onDrawLayer() をカスタマイズすることで画像に更にグラフィックをカスタマイズすることが可能になります。

このコードが実際に動いているワーキングデモページはこちらです:
https://dotnsf.github.io/leaflet_overlay2/


上記 URL をブラウザで開くと、前回同様「家にいるアマビエ」の画像が Leaflet の UI で表示されます:
2020050401


左上のズームコントローラーやスマホのピンチイン/アウト操作で画像が拡大縮小されます。実は前回と少しだけ違う点があることに気付く方はいらっしゃるでしょうか?:
2020050402


よく見ると窓とアマビエの右目尻に丸いオブジェクトが描画されています。これはゴミではなく、画像が表示されている Canvas の上にグラフィックコンテキストを使って(JavaScript で)描画されたものです:
2020050403


画面を更に拡大/縮小しても、ズームレベルに合わせて表示されます:
2020050404


この部分は上記コードの OnDrawLayer 関数内で処理されています。キャンバスが再描画されるタイミングで呼び出されますが、パラメータ(info)の info.canvas で表示されている <canvas> 要素を取得することができます。なので後は info.canvas.getContext( '2d' ) でグラフィックコンテキストを取得した後にここなどを参照して描画すると上述のように元の画像の上に更にグラフィックを追加した上で Leaflet の UI で表示できるようになる、というものです。


<canvas> をある程度使ったことがあると、この方法が使えるのは本当に便利です。自由に描画したキャンバスを Leaflet.js の UI で表示できるようになるため、使いみちが広がります。

オープンソースの地図ライブラリである Leaflet.js を使って(正確には「 Leaflet.js の UI 」を使って)、地図以外の情報を表示することができます。今回は「画像」を表示する方法を紹介します。

例えば Leaflet.js を使って OSM(OpenStreetMap) の地図を表示するには以下のような JavaScript コードをブラウザで実行します:
<div id="demoMap"></div>

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"></script>


<script>
var map = L.map('demoMap', { dragging: false, zoomControl: false, minZoom: 5, maxZoom: 5 }).setView( [ 35.695, 139.983 ], 5 );
L.tileLayer(
  'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: 'Map data © <a href="http://openstreetmap.org/">OpenStreetMap</a>',
    maxZoom: 5
  }
).addTo( map );
</script>

20200506


詳しくは紹介しませんが、青字の行でマップの定義を行って、赤字部分で OSM を指定して地図を表示する、という処理を実行しています。 この赤字部分ではタイルレイヤー(tileLayer)を使って OSM のタイルを指定しているのですが、Leaflet ではここを変えることで地図以外のオブジェクトを扱うことも可能です。今回はその中の1つである「画像」を扱う方法を紹介します。

まず Leaflet.js 利用時に限りませんが、地図アプリの UI というのはなかなか便利です。目的のオブジェクト(普通は地図)をマウスやスワイプでスクロールしたり、拡大・縮小したりして見たり、クリック・ダブルクリックによって特定位置を指定したりすることができます。これ自体が非常に便利な UI となっていて、地図以外でもこのようなインターフェースを使いたくなることがあります。今回は「(比較的大きな)画像ファイル」を対象に Leaflet.js でスクロール・拡大・縮小といったインターフェースが使えるように表示させてみます。

今回の表示対象画像は「いらすとや」「家にいるアマビエ」の画像とします:
amabie_stay_home


オリジナルは横 400 x 縦 373 ピクセルの画像だったのですが、これを 3600 x 3600 に拡大した画像(3600x3600.png)を用意しました。このファイルを使って以下のようなコードを用意します:
<div id="demoMap"></div>

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"></script>

<script>
//. 空の地図を OpenStreetMap データで表示
var map = L.map('demoMap', { dragging: true, zoomControl: true, minZoom: -5, maxZoom: 5, crs: L.CRS.Simple, preferCanvas: true } );

//. 表示する画像のパスとサイズ
var image = {
  url: './3600x3600.png',
  width: 3600,
  height: 3600
};

//. 画像領域を地図に設定
var imageBounds = L.latLngBounds([
  map.unproject( [ 0, image.height ] ),
  map.unproject( [ image.width, 0 ] )
]);
map.fitBounds( imageBounds );
map.setMaxBounds( imageBounds.pad( 0.5 ) );

//. 画像をオーバーレイで設定
L.imageOverlay( image.url, imageBounds ).addTo( map );
</script>

青字部分と赤字部分がそれぞれ元のコードに対応しています。ただ今回は赤字部分の前に画像を用意した後に、画像オーバーレイ(L.imageOverlay)を実行するための準備コードが間に含まれています。


実際にこのコードを使って動くページを用意しました。ワーキングデモはこちらを参照してください:
https://dotnsf.github.io/leaflet_overlay/


上記サイトに PC ブラウザかスマホブラウザでアクセスすると、画面中央に上述の画像が表示されます。ただ単に画像が表示されているわけではなく、画面左上に Leaflet.js のズームコントローラーが、右下には Leaflet ロゴが表示されています:
2020050201


ズームコントローラーを使うか、あるいはスマホなどでピンチイン・アウト操作を行うことで画像が拡大・縮小して表示できます:
2020050202


またマウスやスワイプ処理で画像をスクロール表示することも可能です:
2020050203


こういったユーザーインターフェースが簡単に作れてしまうという点で Leaflet.js は本当に便利です。


(このページの続きはこちらです)
http://dotnsf.blog.jp/archives/1077424924.html


このページのトップヘ