JUGEMテーマ:JavaScript
JUGEMテーマ:プログラミング言語
バーコードリーダーを作ることになったのでその時メモです。
今回はJavascriptのQuaggaJSを使用することにしました。
今回のフォルダ構成は以下の通りです。
/js
/css
index.html
js・・・javascriptを保存するディレクトリ
css ・・・スタイルシートを保存するディレクトリ
カメラアクセス機能を使用するにはhttpsが必要なので証明証が入ったサーバーなりを用意。
https://serratus.github.io/quaggaJS/
npmでインストールできますが、今回はzipファイルをダウンロードしてquagga.min.jsを/jsフォルダに保存します。
とりあえず、最低限のhtmlファイルを作成します。
photo-areaで指定した部分がバーコードの読み取り部分です。
バーコード
javascriptファイル(test.js)に下記内容を記述します。
バーコード
バーコード
今回はi2of5バーコードリーダーです。
バーコードの種類は下記に対応してます。
EAN, CODE 128, CODE 39, EAN 8, UPC-A, UPC-C, I2of5, 2of5, CODE 93 and CODABAR
const startScanner = () => { Quagga.init({ inputStream: { name: "Live", type: "LiveStream", target: document.querySelector('#photo-area'), constraints: { decodeBarCodeRate: 3, successTimeout: 500, codeRepetition: true, tryVertical: true, frameRate: 15, width: 320, height: 240, facingMode: "environment" }, }, decoder: { readers: [ "i2of5_reader" ] }, }, function (err) { if (err) { console.log(err); return } console.log("Initialization finished. Ready to start"); Quagga.start(); // Set flag to is running _scannerIsRunning = true; }); Quagga.onProcessed(function (result) { var drawingCtx = Quagga.canvas.ctx.overlay, drawingCanvas = Quagga.canvas.dom.overlay; if (result) { if (result.boxes) { drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height"))); result.boxes.filter(function (box) { return box !== result.box; }).forEach(function (box) { Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 }); }); } if (result.box) { Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 }); } if (result.codeResult && result.codeResult.code) { Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 }); } } }); //barcode read call back Quagga.onDetected(function (result) { console.log(result.codeResult.code); }); }
Quagga.onProcessed部分は、バーコードに枠を表示する部分です。
このままだと枠が正しい位置に表示されないのでスタイルシート(test.css)で調整します。
#photo-area.viewport { height: 240px; } #photo-area.viewport canvas, video { float: left; height: 240px; } #photo-area.viewport canvas.drawingBuffer, video.drawingBuffer { margin-left: -320px; }
注意点は以下の2つです。
このままでiphoneなどで実際にバーコードを読もうとすると中々認識してくれません。
おそらくスマフォのカメラのサイズが1600×1200だとすると、videoのサイズを320x240にしているので画像を縮小した際に画像が劣化して読めないんじゃないかと。
そこで思いついたのが、video自体は640x480のサイズにして、表示は320x240の中央のみを表示すれば感度が上がるのではないかと。
先ず、javascriptファイル(test.js)のQuaggaの設定を640x480に変更します。
const startScanner = () => { Quagga.init({ inputStream: { name: "Live", type: "LiveStream", target: document.querySelector('#photo-area'), constraints: { decodeBarCodeRate: 3, successTimeout: 500, codeRepetition: true, tryVertical: true, frameRate: 15, width: 640, height: 480, facingMode: "environment" }, }, }
続いてvideoの中央部分を320x240で表示するようにobject-fit: noneをcssに設定します。
#photo-area.viewport { height: 240px; width:320px; } #photo-area.viewport canvas, video { float: left; width:320px; height: 240px; } #photo-area.viewport canvas.drawingBuffer, video.drawingBuffer { margin-left: -320px; }
なお、object-fitはIE/Edgeが対応していないので対応させる場合はfitie.jsなんかで。
このバージョンで確認してみるとサクサクっとバーコードを認識してくれます👍
]]>
こんにちは。
ごんちゃんです。
TRPG用の多面ダイスをさっさと振れるツールを置いているサイトを作っています。→http://gonchan.pupu.jp/
私は家の中でははじっこの部屋で生活しているので、そこが一階のwifiルータからも二階のwifiルータからも離れており、通信環境が劣悪です。
それに打ち克つために作りました。
よろしければご利用ください。
また、作成に際し、数々のサイトを参考にさせていただいておりますm(_ _)m
さて…
「忙しい人のための…」TRPGツールを名乗るためには、機能の簡略化が必要なわけですが、その結果を記録する機能も必要ですよね。
そして今の時代、気軽に記録が残せるといえばやはりツイッター!!
クトゥルフ神話TRPGのキャラシート用のダイスを作成していますが、やはりあの覚えづらい数字にツイート機能は不可欠だと思います。
その実装を目指して調べに調べ、色々試しているのですが、なかなかうまくいかず…。
やはり公開するからにはそれをつけてから!と考えているので、まだまだ先になりそうです。
どなたか知恵をお貸しいただけると助かります!
それではこの辺で
]]>D3で「つまづきの石」になりがちなのが、地図の描画とフォースレイアウトです。そこで今回は、そんなD3の難関のひとつである地図を作成してみます。
大まかな手順は以下の通りです。
Step.1 GeoJSON 又は TopoJSON 形式の地図データを準備する
Step.2 d3.json メソッドで、準備したJSONデータを読み込む
Step.3 d3.geoPath メソッドで、SVGのPath要素として地図を描画する
いろいろな本やサイトを見ていると、インターネットで公開されている地図データを GeoJSON/TopoJSON に変換する方法が紹介されていたりします。でも今回は、まずはD3で地図を作成する基本的な手順を知ってもらうために、既に GeoJSON ファイルが準備できているものとして、Step.2 から進めます。
下記のサンプルコードは、公開されている GeoJSON ファイルをインターネット上から読み込んで、メルカトール図法の世界地図を作成するものです。JavaScriptソースコードの23行名以降が Step.2に、また13~17行目と25行目が Step.3 に、それぞれ対応しています。
ちなみに D3 v3からv4へのバージョンアップに伴い、関連するメソッドが以下のように変化しているので、これまでv3を使っていたかたは注意が必要です。
過去の関連記事
JUGEMテーマ:JavaScript
]]>
d3.jsonで読み込んだデータの確認方法
CSVファイルや外部のURLからデータを読み込むときには、d3.json や d3.csv メソッドを使います。でも、プログラムの作成中には、これらのファイルがちゃんと読み込めているかどうか確認したくなるものです。
すぐに思いつくのは、 d3.json メソッドの内部で console.log を使って読み込んだ変数をコンソールに表示するという方法です。ただ、これだと読み込めたかどうかは確認できるのですが、変数として出力しているわけではないので、たとえば「読み込んだデータ配列の100番目にD3のxxメソッドをどう適用すればいいのかコンソールで試したい」と思ってもできません。
そんなときには d3.json や d3.csv の関数の外でデータ変数を定義をしておけば、読み込んだデータをグローバル変数として扱うことができます。例えば前回のプログラムでは、下記のように変数 dataSet をグローバル変数として定義しておけば、d3.json でデータを読み込んだ後、dataSet に対してコンソールでいろいろテストすることができます。
var dataSet = new Array();
d3.json(jsonFile, function(error, data){ for(var kk=0;kk<numData;kk++){ .... }); |
連想配列の特定のキーに対するmin/maxを取得する方法
D3 には、d3.min, d3.max という配列の最小値や最大値を返してくれる関数が用意されています。でも場合によっては、連想配列のなかの特定のキーに対する最小値や最大値を求めたい場合があります。そんなときには、d3.min, d3.max の後ろにキーを指定するための関数を追加することで、これらを求めることができます。
言葉ではなかなか分かりにくいので、下記に簡単な例を示します。
var data = [ {key1: 1, key2: 5}, {key1: 3, key2: 2}, {key1: 7, key2: 1}];
d3.min(data, function(d){return d.key1;}) // key1 の最小値 1 を出力
d3.max(data, function(d){return d.key2;}) // key2 の最大値 5 を出力 |
ちなみに D3 で用意されている配列操作のための関数については、以下のサイトが参考になります。
出力する文字数を制限する方法
データによっては、ときどき極端に長い文字列が出てくることがあります。たとえば前回プログラムを作成しているときには、地震の名称が極端に長いものが見つかって、一覧表をきれいに表示するために文字列を制限する必要がありました。そんなときには、ストリング型変数 str の substr メソッドを使って文字数を制限することができます。構文は str.substr(start[, length]) です。以下に簡単な例を示します。
var str = "abcdefghijklmn";
str.substr(5) // 最初の5文字が削除されて、残る fghijklmn を出力
str.substr(0,5) // 0番目から5文字、abcde を出力 |
JUGEMテーマ:JavaScript
これまでD3を使ってSVGを操作してきましたが、D3を使って操作できるのはSVGだけではありません。同じように select() メソッドを使って、他のDOM要素を JavaScript 側から操作することも可能です。そこで今回は、米国地質調査所 (USGS: United States Geological Survey) が公開している過去4.5ヶ月分の地震データをもとに、<div>~</div> 要素を操作して一覧表を作成するプログラムを作成しました。
2行目で、まずUSGSが JSON 形式で公開している、過去4.5ヶ月分の世界の地震データ最新版のURLを設定しています。これにより、この JavaScript プログラムが呼び出されるたびに、表示されるテーブルの内容は自動的に最新版の地震データになるというわけです。7~24行目では、テーブルのヘッダー行を作成しています。ヘッダー行の背景色や文字のスタイルは CSS 側で自由に設定できるように、<div> 要素にはそれぞれクラス名を与えています。
26行目以下は、いよいよ USGS のサーバーから JSON 形式の公開データを取得して、必要な情報を整理してテーブルで表示する部分です。この例では受領したデータから、個別の地震の情報のうち ?マグニチュード、?発生場所の名称、?発生日時、?USGSの詳細情報ページのURL、の4つの情報を抽出して表示することにしています。USGSが公開しているデータにはこれ以外にも、震源地の緯度・経度や震源の深さ、発生した国の名称など多くの情報が記録されています。詳細については、USGSによる説明を参照してください。
42~48行目では、データに含まれるマグニチュードの最大値と最小値を求めて、マグニチュードの数値によりテーブルの行の色が変わるようにカラーグラデーションを設定しています (関連記事:D3 v4でオリジナルのカラーマップを作成する方法)。
今回は JavaScript だけでなく、CSS側でも色々な設定をしています。それぞれの内容は、下記のタブを切り替えることで確認することができます。
過去の関連記事
JUGEMテーマ:JavaScript
]]>以前、このブログでD3.jsを使ったVoronoi図の作成方法を紹介しました (【D3.js】ボロノイ図の作成)。ところが、v4へのバージョンアップに伴い、Voronoi図を作成するための関数も d3.geom.voronoi() から d3.voronoi() に変更されたため、以前作成したプログラムのままでは D3 v4 でVoronoi図を作成できなくなってしまいました。
そこで、改めて D3 v4 を使って Voronoi図の作成方法について紹介します (Voronoi図そのものの説明については割愛します。Wikipediaの説明などを参照して下さい)。
それでは、下記のサンプルプログラムを使って説明を進めます。1~10行目はもう大丈夫ですね。これまで何度も出てきた、SVGを描画するための領域を定義している部分です。14~16行目では、前回紹介した方法でオリジナルのカラーグラデーションを定義しています。ここでは、0~1の数値を入力引数として与えると、LightGreenからLightCyanになめらかに変化する色を返す関数として定義しました。19~22行目では、乱数を使ってx-y平面上にVoronoi図の母点40個を設定しています。
いよいよ25~28行目が今回のポイントです。そもそも d3.voronoi() というメソッドは何を返しているのでしょうか?答えは、Voronoi図を作成するための「関数」を返しています。具体的には、母点のx-y座標の配列を入力引数として与えると、Voronoi図の領域などを自動的に計算して出力する関数です。d3.voronoi() メソッドに対して、データ配列のどの値をx,y座標の数値として渡すかを、26, 27行目の .x(), .y() メソッドで定義しています。最後の .extent() メソッドは、Voronoi図を描画する範囲を指定するためのものです (JavaScriptやCSSの内容は、下記のタブを選択すると表示されます)。
こうして定義した関数を使って、いよいよ31~41行目でVoronoi図を描画しています。ここで、SVGのPath要素にバインドするデータとして、voronoi.polygons(data) を与えています。これは、25行目で定義した voronoi という関数に data を与えて、それぞれの母点に対するVoronoi領域をSVGのPath要素として描画するためのものです。36~38行目の部分は、上記の関数が返したポリゴンの頂点を結んでSVGのPath要素を生成するためのものです。これらの部分については、後で詳細に見ることにします。最後に40, 41行目では、各ポリゴン要素にマウスオーバー/マウスアウトのイベントが発生した場合に、クラス要素を書き換えています。これは、CSS側でクラス名に従って色を変えるように指定しているためです。つまり、JavaScriptによるSVG要素のクラス名変更処理と、CSSによる色の設定が協調することで、マウスオーバー/マウスアウトされたポリゴン要素だけの色が変化するようにしているというわけです。
さて、これだけだとなかなか分かりにくいので、32行目に出てきた voronoi.polygons(data) の動きもう少し詳細に見てみることにしましょう。例えばChromeなどのブラウザの開発者モードを使って、JavaScriptコンソールで voronoi.polygons(data) を呼び出すと、以下のような配列を生成していることが分かります。Voronoi図との対応が分かるように、1枚の画像の左側にブラウザ表示、右下に voronoi.polygons(data) の出力、右上に生成されたSVG要素を、それぞれ示しています。
まず、右下と右上を比較すると、voronoi.polygons(data) の出力は、ぞれぞれのVoronoi領域を表現するためのPathの頂点のx-y座標の集合であることが分かります。ただ、x-y座標の数値のままではSVGのPath要素として生成できないので、36~38行目の関数でPath要素を指定するフォーマットに整形しているというわけです。
JUGEMテーマ:JavaScript
]]>以前、d3-scale-chromatic.v1.min.js を使ってグラデーションを作成する方法を紹介しました (D3.js v4で利用可能なカラーマップ一覧)。今回は、d3-scale-chromatic.v1.min.js を読み込まずに、任意のカラーマップを作成する方法を紹介します。
このブログで D3.js v4 で折れ線グラフを作成する方法について紹介したときに、scaleLinear() というメソッドが出てきました。そのときは、データの値の範囲をSVG画像の座標軸にマッピングするために、このメソッドを使っていました。ところがこのメソッド、使い方によっては、数値の範囲をRBGの色の範囲にマッピングすることも可能です。試しに 0~1 の範囲の数値を、0 => cyan, 0.5 => yellow, 1 => orange となるようなオリジナルのカラーマップを作ってみました。
ポイントは、14~16行目の部分です。この部分で、0~1の数値を入力引数として、cyan~yellow~orange の範囲で連続的に変化するRGB値を出力する関数を作成しています。色の指定は、この例のように既に定義されているカラーネームを使うこともできますし、RGB値を直接入力することもできます (せっかくなので、サンプルコードにアニメーションも加えてみました)。
JUGEMテーマ:JavaScript
]]>前回は、d3.arc() メソッドを使ったパイチャートの作成方法について説明しました (D3.js v4 によるパイチャートの描画 (1)) 。ただ、前回は簡単のためにアークの開始角度を固定していました。そこで今回は、アークの開始角度と終了角度の両方をデータにあわせて設定できるようにして、より現実的なパイチャートにしてみましょう。
せっかくなので、前回と同様にパイチャートと数字が変化するようにしてみました。ただ、今回はアークの数が複数になっているので、変化前の状態を保持しておくために each() メソッドを使ってデータを保持しておくようにしています (55行目など) 。
JavaScriptのソースコードを確認するには、下記の "JavaScript" タブをクリックして下さい。
過去の関連記事
JUGEMテーマ:JavaScript
]]>以前、このブログで「D3.jsによるパイチャートの描画」という記事を書きました。ところが D3 の v4 へのバージョンアップに伴って、d3.svg.arc() が d3.arc() に変更されたため、以前のコードのままでは v4 でパイチャートを描画できなくなってしまいました。そこで、あらためて D3 v4 を使ってパイチャートを描画してみます。
ただ、前回と同じものを作っても面白くないので、ちょっとだけインタラクティブに動くグラフを作ってみました。
今回のポイントは以下の 3つです。
それでは順番に見ていきます (下記のJavaScriptタグやHTMLタグをクリックすると、それぞれの中身が表示されます)。
1. d3.arc() によるアークの設定
d3.arc() は、円弧の形のPath要素を生成するための関数を生成します。そこに outerRadius(), innerRadius() メソッドによって、それぞれ円弧の外側の半径と内側の半径を指定します。さらに、今回は円弧の開始角度を常に 0度 (時計の12時の位置) に設定するため、startAngle() メソッドで開始角度を指定しています。ウェブブラウザの JavaScriptコンソール上で toString.call(arc) として変数 arc の型を確認すると、関数型になっていることが分かると思います。
2. attrTween() によるアークの連続的な変化
これまで作成したアニメーションは、円の半径のようなSVG要素の基本的な属性を変更するもので、transition(), duration() などのメソッドで簡単にアニメーションとして表示することができました。ところが今回は円弧のPath要素を連続的に変化させる必要があります。そんなときに使うのが attrTween() メソッドです。
55行目以降で定義しているgrapUpdate関数が最初に呼び出されたとき、66行目の attrTween() の第1引数 "d" は、31行目でバインドした変数 {endAngle: 2*Math.PI} です。このため、67行目の interpolate() の第1引数は d.endAngle、つまり 2*Math.PI になっています。ちなみに interpolate() メソッドは第1引数と第2引数の間を内挿 (interpolate) するための関数です。
69行目では、この interpolate() を使って、更新前の角度と更新後の角度の間を連続的にスイープさせて d.endAngle に設定しています。つまり、68行目から71行目全体で、角度を連続的に変更させたPath要素が次々と生成されているわけです。
3. tween() によるテキスト表示内容の変化
これはパイチャートのアニメーション化に必要というわけではありませんが、せっかくなので使ってみました。
インタラクティブなデータの可視化をする際、しばしばテキストの表示内容も連続的に変更させたくなることがあります。そのような場合には tween() メソッドが役に立ちます。やっていることは基本的には attrTween() でやったことと同じです。まず interpolate() メソッドで、ある値と別の値を内挿するための関数を作成して (58行目)、それを使って連続的に変化するテキストを生成している (69~61行目) というわけです。
JUGEMテーマ:JavaScript
]]>今回はちょっと応用編です。
インターネットで公開されているデータセットをいろいろ見ていると、文豪ヴィクトル・ユゴーの名作『レ・ミゼラブル』の人間関係というデータがありました。JSON形式で公開されているこのデータ、内容がどこまで正しいのかは良く分かりませんが、D3.js でJSON形式のファイルを読み込んで可視化する練習にちょうど良い手ごろなサイズなので、SVGのrect要素とtext要素だけを使って可視化してみました。
JUGEMテーマ:JavaScript
]]>