Open32

センサーマップダッシュボード開発

shusukeshusuke

leaflet上にマーカーを置くときは緯度経度を指定するのだが、この際はGoogle Mapでマーカーを置く場所を決め右クリックをして緯度経度をコピーしてプログラムに持ってくると良い。

shusukeshusuke

'getComputedStyle' of null
よく出るエラー。
基本的に指定したid要素がなかったときとかに出る。

shusukeshusuke

Leaflet|マップのポップアップ

L.marker(sensorPopupObjs[i].location)
    .addTo(mymap)
    .bindPopup(`<div id="${sensorPopupObjs[i].name}"></div>`, {
      autoClose: false,
      closeButton: false,
      className: "popup",
    })
    .on("popupopen", () => {
      sensorPopupObjs[i].setActive(true);
      sensorPopupObjs[i].createGaugePopup();
    })
    .on("popupclose", () => {
      sensorPopupObjs[i].setActive(false);
    })

    .openPopup();

popupopen, popupcloseとかのイベントごとに処理を登録しておくと良い。
clickイベントでやる必要はない。popupopenが結局呼ばれるので。

https://kita-note.com/leaflet-list-map-popupevents

shusukeshusuke

セルシウス温度を色温度likeなもの(青から赤にグラデーションする)に変換するコード書いた。
p5jsのmap function的な処理をしている。

const maxTemperature = 40;
const minTemperature = -5;
const p5LikeMapFunc = (n, start1, stop1, start2, stop2) => {
  return ((n - start1) / (stop1 - start1)) * (stop2 - start2) + start2;
};
const temperatureBase = p5LikeMapFunc(
      ここに温度,
      minTemperature,
      maxTemperature,
      0,
      255
    );
config.circleColor ="rgb(" + [temperatureBase, 128, 255 - temperatureBase].join(",") + ")";

ケルビン温度を本物の色温度に変換するコードはいっぱい転がっている。セルシウス温度→ケルビン温度にして、無理やり使うのもあり。
https://www.google.com/search?sxsrf=ALeKk02BTk2RJDfFOjSx-aRBZ-o6B4XfyA:1613395606127&q=Convert+color+temperature+in+Celsius+to+a+color+in+RGB+color&spell=1&sa=X&ved=2ahUKEwi-yPD__uvuAhWD-mEKHZ0qBYcQBSgAegQICxA1&biw=1280&bih=976

でも自分には色温度がわかりやすいと思えないので、色温度likeなグラデーションを採用。

追記です。
いい感じに外部モジュール化した。

function bToRColorTemperatureDefaultSettings() {
  return {
    maxTemperature: 40,
    minTemperature: -5,
  };
}

function getBToRColorTemperature(temperature, config) {
  if (config == null) config = bToRColorTemperatureDefaultSettings();
  const temperatureBase = Math.round(
    ((temperature - config.minTemperature) /
      (config.maxTemperature - config.minTemperature)) *
      255
  );
  return "rgb(" + [temperatureBase, 128, 255 - temperatureBase].join(",") + ")";
}

// how to use
// const config = bToRColorTemperatureDefaultSettings();
// config.maxTemperature = 50;
// alert(getBToRColorTemperature(40, config));
//or just use like this
// alert(getbToRColorTemperature(40));

オープンソースのリソースとして公開する練習につかいたい。

shusukeshusuke

"Magnific Popup"を使う。
いい感じのモーダルポップアップを簡単につくれる。レスポンシブ対応らしい。
ポップアップのスライド対応までしているのが良い。
https://dimsemenov.com/plugins/magnific-popup/

簡単に使ってみることには成功したので、inlineコンテントを作ってギャラリーに表示する手法でやってみようと思う。

参考サイト
https://github.com/dimsemenov/Magnific-Popup
https://dimsemenov.com/plugins/magnific-popup/documentation.html#gallery
https://gimmicklog.com/jquery/180/#i-4

shusukeshusuke

Magnific Popup難しかった。なんとかinlineのギャラリーを作れた。

まずはhtmlのどっかにモーダルで表示する要素を準備しておく。これは後から動的に生成してもよい。このために#modal-itemsで要素をまとめて管理している。

index.html
<div id="modal-items">
    <div id="modal-1" class="mfp-hide white-popup">
        item-1
    </div>
    <div id="modal-2" class="mfp-hide white-popup">
        item-2
    </div>
    <div id="modal-3" class="mfp-hide white-popup">
        item-3
    </div>
</div>

次に選択されるとモーダルを発火させる要素を準備しておく。ここは単純に.modal-linkで囲ってやるだけで大丈夫。さらにそれぞれの子要素はaタグで囲い、hrefで先程定義したモーダルで表示する要素を指定する。選択するときの数字部分を動的にすれば、要素も増やせる。

index.html
<div iclass="modal-link">
    <a href="#modal-1">モーダル1を開く<a/>
    <a href="#modal-2">モーダル2を開く<a/>
    <a href="#modal-3">モーダル3を開く<a/>
</div>

最後にjsスクリプト。モーダルを発火させる親要素である.modal-linkを指定して、それぞれのモーダルの指定はその子要素のaタグにしている。galleryのenableをtrueにすることでギャラリー表示できる。その他、モーダル開閉時や生成時のコールバックも指定できる。

main.js
$(".modal-link").magnificPopup({
      delegate: "a",
      type: "inline",
      gallery: {
        enabled: true,
      },
      callbacks: {
        open: function () {},
        close: function () {},
      },
    });
shusukeshusuke

モーダルにチャート用のcanvasを埋め込むと、チラつきが気になる。これはもとからcanvas分の領域をcssで確保してあげると解決。

.white-popup {
  position: relative;
  background: #fff;
  padding: 40px;
  width: auto;
  min-height: 300px;
  max-width: 50%;
  margin: 20px auto;
  text-align: center;
  user-select: none;
}

min-height: 300px;の記述が大事。

shusukeshusuke

ギャラリー表示のモダールに合わせて、地図も動かすのに成功した。

やり方はモーダル要素に情報を埋め込んで、それをmagnificPopupのchangeコールバックで取得する。今回はhiddenのinputに緯度経度のデータを埋め込んでおいた。

change: function () {
          //モダールのスライドに合わせてマップの中心の移動
          map.setView([
            this.content.find(".longitude").val(),
            this.content.find(".latitude").val(),
          ]);
        },
shusukeshusuke

chartライブラリ探し

三軸以上の複合チャートが描けるものを探してます。マウスカーソルを重ねたら、そのグラフの単位が表示されるみたいのが好ましい。縦軸は自動でスケールしてほしい。

なかなか良さそうなのが見つからない...。

shusukeshusuke

d3.jsがバージョン間で互換性がなさすぎるかつ、複数バージョンの共存は難しそうなので、d3jsベースのグラフライブラリc3jsは断念。特にver3から4は大きい違いらしい。他も違うかもだけど。

代わりに最も検索に引っかかったchartjsを採用。こっちはcanvasベース。c3はsvg。

shusukeshusuke

jsのthisではまった〜

なかなか体で理解できん。
関数呼び出しパターンは一回selfでthisを受けてから使うと。

var myObject = {
  value: 1,
  show: function() {
    var self = this;
    console.log(self.value); // 1

    function show() {
      console.log(self.value); // 1
    }
    show();
  }
};
myObject.show();

https://qiita.com/takeharu/items/9935ce476a17d6258e27

shusukeshusuke

日本語配列のmacをus配列として使うとグレイヴ・アクセントが使えないので、苦肉の策として日本語入力の辞書に'をグレイヴ・アクセント追加した。

もっと良い方法はあるのだろうか...

shusukeshusuke

ある程度長い時間動かしていると重くなる原因がたぶんわかった。
D3 Liquid Fill Gaugeライブラリのこの部分。GaugeUpdaterってのをクリエイトのたびにnewしているからだ。

普通のアップデートの際にはこれをつかってupdateすればよいのだが、configに含まれるゲージの色もアップデートしたいので毎回createする必要がある。

結論として、今回はこの関数とreturnをまとめてコメントアウトすることで重さを改善。

  function GaugeUpdater() {
    // ゲージのアップデートをしてくれる関数
    this.update = function (value) {
    };
  }

  // return new GaugeUpdater();
shusukeshusuke

メモリリーク問題

  • chromeでconsole.logを出し続けると重くなるくさいのでそれをコメントアウト
  • chartjsの表示データをずっとpushし続けるのはよくないので、表示可能最大数に達したらshift()をするようにした。shiftが重そうで怖い。ここは実際に動かして試さないと。