カテゴリーアーカイブ 言語

村上 著者:村上

【JavaScript】Mapboxの「There is already a source with this ID」エラーの対処法

先日投稿したMapboxのエラーについて、対処法が分かったのでご紹介!
というか、まさにほぼ同じことにお悩みの方がいらっしゃり、そこで対処法が紹介されていたので、それをコピー&ペーストしたら、動きました。
検索が下手だったようです…反省。

なお、以前の記事はこちらから。

【JavaScript】Mapboxで「There is already a source with this ID」エラーが発生【未解決】
https://cpoint-lab.co.jp/article/201808/【javascript】mapboxで「there-is-already-a-source-with-this-id」エラーが発生【未解決】

ざっくりと状況を説明すると、Mapboxで追加できるナビゲーション機能を追加してから一旦削除し、もう一度追加しようとすると、「There is already a source with this ID」という IDの重複エラーが発生し、ナビゲーション機能を追加できない状態でした。

 

さて解決策ですが、ナビ機能を削除する、removeControl() を実行したタイミングで下記の項目も削除するだけでした。

map.removeLayer('directions-route-line');
map.removeLayer('directions-route-line-alt');
map.removeLayer('directions-hover-point-casing');
map.removeLayer('directions-hover-point');
map.removeLayer('directions-waypoint-point-casing');
map.removeLayer('directions-waypoint-point');
map.removeLayer('directions-origin-point');
map.removeLayer('directions-origin-label');
map.removeLayer('directions-destination-point');
map.removeLayer('directions-destination-label');
if (map.getSource('directions')) map.removeSource('directions');

なお、この解決策が紹介されていた投稿はこちらから。

Error when adding controls dynamically #5089・mapbox/mapbox-gl-js・GitHub
https://github.com/mapbox/mapbox-gl-js/issues/5089

実際に、ソースコードに追加するとこのような感じ。

var directions;
function navi() {
    if(['条件:ナビ機能が追加済みだったら']) {
        map.removeControl(directions);

        /* ここから */
        map.removeLayer('directions-route-line');
        map.removeLayer('directions-route-line-alt');
        map.removeLayer('directions-hover-point-casing');
        map.removeLayer('directions-hover-point');
        map.removeLayer('directions-waypoint-point-casing');
        map.removeLayer('directions-waypoint-point');
        map.removeLayer('directions-origin-point');
        map.removeLayer('directions-origin-label');
        map.removeLayer('directions-destination-point');
        map.removeLayer('directions-destination-label');
        if (map.getSource('directions')) map.removeSource('directions');
        /* ここまで */

        directions = null;
    } else {
        directions = new MapboxDirections({
                        accessToken: mapboxgl.accessToken
                    });
        map.addControl(directions, 'top-left');
    }
}

どれか一つがなくてもダメなようで、試しに2行ほど削除してみたのですが、当然ながらその行でエラーが発生し、実行できませんでした。

作業は以上で完了です。
画面をリロードして動作確認をしたところ、問題なく動作しました!

 

以上、Mapboxのエラーの対処法でした。
前回の記事でも書いたのですが、Mapboxのナビ機能ってそこそこサイズが大きいので、特にスマートフォンでは表示/非表示を行いたかったんですよね。
最初はCSSを操作して、ナビゲーションウィンドウを消すことも考えたのですが、ウィンドウが見えないだけでナビ機能は有効だったので、どうしても機能自体のON/OFFを切り替えたかったんです。

あとは…ラベルとか、ナビの道順のところを日本語化できないかな…と考えています。
こちらもとっかかりが見つかったら、改めてご紹介したいと思います。

  • この記事いいね! (0)
著者:杉浦

文字コードを利用して文字をforで回す

 文字コードは文字を数字で扱う仕組みです。各数字と各文字が一対一の関係で対応しています。この記事では文字コードの一つであるASCIIを利用します。ASCIIの対応の大きな分類は次の表のとおりです。ASCII – Wikipediaより引用

コード範囲(16進) 内容
00-1F 制御文字
20 空白
21-7E 図形文字
7F 制御文字(DEL)

 図形文字はいくつかの記号とa-zA-Z0-9、おおざっぱにはキーボードのローマ字入力で直接打てる文字です。キーボードに詳しくないのでまあ多分そんなものぐらいの気持ちで。Ascii Table – ASCII character codes and html, octal, hex and decimal chart conversion
 知る限りのプログラミング言語にはこのASCIIと数字を変換する機能が備わっています。これを利用すると文字列をforで回せます。Excelシートと関係のあるプログラムを書いたりする時、特に便利です。最近よく使用している言語であるphp,javascriptでの例が次です。
 phpならばchr関数を利用して次の様な感じです。PHP: chr – Manual

<?php
for($i = 97;$i <= 122;$i++){
    echo chr($i);
}
for($i = 65;$i <= 90;$i++){
    echo chr($i);
}


javascriptならばString.fromCodePoint()関数を利用して次の様な感じです。String.fromCodePoint() – JavaScript | MDN

String.fromCodePoint.apply(null,Array.from({ length: 26 }, (_, i) => i+65));
String.fromCodePoint.apply(null,Array.from({ length: 26 }, (_, i) => i+97));

  • この記事いいね! (0)
村上 著者:村上

【JavaScript】Mapboxで「There is already a source with this ID」エラーが発生【未解決】

タイトルにも書いてありますが、未解決です。

先日からMapboxを触っているのですが、その中でナビゲーション機能を追加・削除したいと考えています。
で、追加して削除までは成功したのですが、その後もう一度追加しようとすると、「There is already a source with this ID」というエラーが発生している状況です。
Google翻訳に掛けたところ「このIDを持つソースが既に存在します。」とのことだったので、削除したコントローラのデータが一部残っているのではと思っております。

ちなみにエラーが発生しているソースコードはこちら。

var directions;
function navi() {
    if(['条件:ナビ機能が追加済みだったら']) {
        map.removeControl(directions);
        directions = null;
    } else {
        directions = new MapboxDirections({
                        accessToken: mapboxgl.accessToken
                    });
        map.addControl(directions, 'top-left');
    }
}

このコードを実行すると、1回目の追加と削除が成功した後、10行でエラーになります。

まだしっかりと読めてはいないのですが、下記の記事が同じ原因で発生しているように見えるので、時間をとってしっかり確認したいと思います。

layers don’t show up after removing them and adding them again・issue #5440・mapbox/mapbox-gl-js
https://github.com/mapbox/mapbox-gl-js/issues/5440

 

CSSでの単なる表示・非表示の切り替えも考えたのですが、検索窓が見えないだけで実行されてしまうので、結局この方法がベストかな、と考えています。
解決策が分かったら、また改めてご紹介したいと思います!

  • この記事いいね! (0)
著者:杉浦

変数名等の命名サービスcodic

 codicはコーディング中の命名を楽にしてくれるサービスです。
プログラマーのためのネーミング辞書 | codic”

使い方は簡単。左側に日本語を入れると対応する英語が出てきます。各行が1対1で対応しており、余計な操作なく多数の語を変換できます。左上の記法ボタンからスネーク記法、キャメル記法、ハイフン区切りなど記法を切り替えることができます。

 codicはgoogle翻訳の様な一般の翻訳ツールと異なり命名用と目的が狭く、明確です。そのためちょっとした記法で、出力を限定できる機能が備わっています。
 ”~する”と動詞で結ぶことで、メソッド名になります。

 ”~か”と結ぶことで、真偽値を返すメソッド名になります。

 ”辞書s”のように名詞の後にsをつけることで複数形に変換されます。

 コーディングにおける命名用の翻訳のため通常の翻訳と異なるコーディング用の翻訳をしてくれます。

 英単語をクリックすると他の候補と簡単な英和辞書へのリンクが出現します。

  • この記事いいね! (0)
村上 著者:村上

【JavaScript】Mapboxを使って場所の検索機能を実装する方法

最近、Mapboxを業務で使っているので、今回もMapboxで実装できる機能の紹介を。
できることが多すぎて、いっそ何ができるのかわかりにくいので、個人的に使えそうだと思った機能をピックアップしていこうと思います。
前回はナビゲーション機能でしたが、今回は場所の検索機能について。

公式サイトのサンプルはこちらから。

Add a geocoder|Mapbox
https://www.mapbox.com/mapbox-gl-js/example/mapbox-gl-geocoder/

 

まず、実装できる画面はこちら。

画面左上に検索窓が表示されるので、こちらに検索したいキーワードを入力します。
試しに「浜松駅」と入力しましたが、問題なく機能しました。

実装方法ですが、まず下記のJSファイルとCSSファイルを読み込みます

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D'https%3A%2F%2Fapi.mapbox.com%2Fmapbox-gl-js%2Fplugins%2Fmapbox-gl-geocoder%2Fv2.3.0%2Fmapbox-gl-geocoder.min.js'%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.css' type='text/css' />

次に、下記のコードを追加します。

map.addControl(new MapboxGeocoder({
    accessToken: mapboxgl.accessToken
}),"top-left");

何と実装は以上で完了です!
とても簡単ですね!
また、第2引数の「top-left」を変更することで、表示位置も調節できます。
例えば、右下に配置したい場合は「bottom-right」と指定します。

 

以上、Mapboxのマップに検索窓を追加する方法でした。
ただ、検索後、その場所に移動はしますが、マップピンが立つなどの機能はないので、そこは自分で実装する必要がありますね。
が、簡単な検索ならこれで十分すぎるくらいの機能だと思います。

  • この記事いいね! (0)
著者:杉浦

PHPを例にした正規表現の再帰

 正規表現によって多重括弧のような入れ子構造を表現することは難しいです。正規表現の難題、入れ子構造
 入れ子構造が正しいことを示すにはスタックのデータ構造を表現することが望ましいですが、通常の正規表現ではスタックを用いることはできません。一部の正規表現エンジンにのみ備わっている再帰機能によってスタック構造を表現できます。再帰機能を備えた正規表現を使用可能な環境にはPHP、python、ruby、一部テキストエディタなどがあたります。正規表現のみに頼らないで文字列操作コードを書くことが可能なプログラミング言語では実装されていない場合が少なくないです。次の正規表現はPHPで動作する正規表現です。PHP: 再帰的パターン – Manual

/\((?:[^\(\)]+|(?R))*\)/

 (?R)が再帰の記号です。この時点で再度正規表現全体を呼び出します。これは最大の大きさで成立している括弧を抜き出す目的の正規表現です。動作結果は下図の通りです。
 
 詳しい動作の過程は次の通りです。この過程の説明はPHP Recursive Patterns – Stan Angeloff’s blogの説明の仕方を大きく参考にしています。


/
  \(          # 開き括弧 '(' を見つける.
    (?:       # 新しいグループの開始。これをしないと最初と最後の'('と')'が|に巻き込まれる。
      [^\(\)]+# '('でも')'でもない文字をどん欲に消費する。
      |       # or
      (?R)    # '('か')'を読んだら、また最初から。再帰処理。
    )
    *         # 可能な限り深いのネストを探索する.
  \)          # '('に対応する閉じ括弧 ')' を見つける.
/
  • この記事いいね! (0)
takahashi 著者:takahashi

PHPからSlack/Discordに、Webhookで簡単に通知を送る。

SlackやDiscordを使っていると何かと便利なのがWebhook通知。

専用のチャンネルを用意し、何かイベントが発生したときの通知などに、メールの代わりにこのWebhookで通知を飛ばしてやることで取りこぼしなく通知を確認できます。

このWebhook、既存のサービスやシステム以外で通知を飛ばしたいときに”どうやってやればいいんだろう?”と思ってしまう方もいらっしゃるかと思います。
調べるとcurlとかめんどくさいパラメータアレコレとか指定するものが多く出てくるのでつい面倒な印象を持ってしまいがちですが、いろいろ調べていたところ、PHPで超簡単にできる方法を見つけました!

PHP から Slack の Incoming webHooks を叩く – Qiita

<?php

//処理内容を定義
function send_to_slack($message) {
  $webhook_url = 'Webhook受付URL';
  $options = array(
    'http' => array(
      'method' => 'POST',
      'header' => 'Content-Type: application/json',
      'content' => json_encode($message),
    )
  );
  $response = file_get_contents($webhook_url, false, stream_context_create($options)); //要求を$webhook_urlのURLに投げて結果を受け取る
  return $response === 'ok'; //$responseの値がokならtrueを返す
}

//メッセージの内容を定義
$message = array(
  'username' => '送付元として表示するユーザー名', 
  'text' => 'メッセージ内容', //Slackの場合
  //'content' => 'メッセージ内容', //Discordの場合
);

send_to_slack($message); //処理を実行
?>

これだけで行けちゃうそうです。
要するに、送付先とデータ形式とメソッド(POST・GETなど)さえ合っていれば、どんな方法でも大丈夫なようです。

ちなみにコードをそのままDiscordに転用する場合は、$messageに入れている要素名’text’を’content’に書き換える必要があります。
‘text’のまま実行してしまうと400エラーが返ってきてしまい、Webhookの内容が送信されません。

上記の内容をテキストエディタなどで書き、
hoge.php
のような適当なファイル名で保存してください

あとはコマンドライン上で

php ./hoge.php

のようにしてやればWebhookが実行され、入力した内容がSlack/Discordに届くはずです。

内容さえ書き換えてやればいくらでも応用ができるので、例えばリモートでサーバーを再起動したときの起動通知とか、システムで障害が発生したときのエラー通知なんかにも使うことができます。

メール通知の場合だと、メールサーバーが落ちて送付できなかったり、通知メールが遅延してしまうことがあったりもするので、Webhook経由でも通知が送れると便利ですね。

  • この記事いいね! (0)
村上 著者:村上

【JavaScript】Mapboxを使ってルート検索を行う方法

Mapboxでルート検索を行いたかったので調べてみたところ、プラグインがあったので試してみました。
導入もとても簡単で、しかも無料とのこと!

なお、今回参考にさせていただいたサイトはこちらから。

Mapbox でルート検索を試してみた – マルティスープ株式会社
https://maps.multisoup.co.jp/blog/2818/

なお、GitHubはこちらから。

GitHub – mapbox/mapbox-gl-directions: Directions plugin for mapbox-gl-js using Mapbox Directions API.
https://github.com/mapbox/mapbox-gl-directions

 

さて、ルート検索プラグインの導入方法ですが、まずMapboxのアカウントを作成し、画面上に地図を表示させるところから行ってください。
こちらの方法については、下記の公式サイトをご確認ください。

Welcome to Mapbox | Mapbox
https://www.mapbox.com/install/

上記の方法で地図が表示出来たら、下記のコードを追加します。

まずは、プラグインを使用するためのJavaScriptファイル及びCSSファイルの読み込みです。

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D'https%3A%2F%2Fapi.mapbox.com%2Fmapbox-gl-js%2Fplugins%2Fmapbox-gl-directions%2Fv3.1.1%2Fmapbox-gl-directions.js'%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-directions/v3.1.1/mapbox-gl-directions.css' type='text/css' />

次に下記のJavaScriptコードを追加します。

// アクセストークン設定
mapboxgl.accessToken='xxxxxxxxxxxxxxxxxxxxx';
// 地図生成
var map = new mapboxgl.Map({
    container: 'map',
    center: [地図の中心座標],
    zoom: 10,
    styles: 'mapbox://styles/mapbox/streets-v10'
});

// ここから下のコードを追加
map.addControl(
    new MapboxDirections({
        accessToken: mapboxgl.accessToken
    }), 'top-left');

なお、地図生成のコードは既に追加されているはずなので、12行目以降のコードを追加してください。

そうすれば、下記のようにルート検索用のメニューが表示されるはずです。

ルート検索を行いたい場合は、地図上で出発地点と到着地点をクリックすればOKです。
ルート検索後は、車や徒歩、自転車から移動手段を選択できます。
また、ルートも3候補くらい出してくれます。

ただ、Googleマップのように建物名や住所では検索できないのが少し難点ですね。

 

以上、Mapboxでルート検索をする方法でした。
検索機能は少し限定的ですが、導入は簡単だし、何よりも無料なので、簡単なルート検索機能の導入でしたら是非お試しになってはいかがでしょうか。

  • この記事いいね! (0)
著者:杉浦

javascriptにおける型変換による計算のさわり

 javascriptは型変換を行うことによって記述から予想される実行結果と実際の実行結果が異なることが起きやすい語です。それぐらい大きく変化の起きる型変換を用いた小ネタです。

+[]

 これの実行結果が
 
 です。javascriptは正負の様な数式符号がついた対象を数字として扱う動作があります。大体、空っぽい対象は0、trueっぽい対象は1として評価されます。そのためこの様な結果になります。これを利用すると次の様なこともできます。

 この手の型変換をこれでもかと利用した方法に記号プログラミングというものがあります。例えば、Aを表すコードは次になります。

(([][($+[])[-~-~-~[]]+(({})+[])[-~[]]+([][![]]+[])[-~[]]+(![]+[])[-~-~-~[]]+(!![]+[])[+[]]+(!![]+[])[-~[]]+($+[])[-~[]]+($+[])[-~-~-~[]]+(!![]+[])[+[]]+(({})+[])[-~[]]+(!![]+[])[-~[]]])+[])[-~-~-~[]*-~-~-~[]]
  • この記事いいね! (0)
村上 著者:村上

【JavaScript】部分一致のある複数のキーワードをそれぞれ置換する方法

JavaScriptで複数の文字列を置換するとき、置換したいキーワードの一部が他のキーワードと重複しているため、置換後の文字列が意図しない結果になるという状況に陥りました。
例えば、「#○○○」などのハッシュタグをタグで囲もうとしたとき、ハッシュタグに「#浜松」と「#浜松市中区」というキーワードが一部重複している箇所があるため、「#浜松」の部分が意図せずに2回も置換されてしまうという感じです。

今回は、それの対処法です。
もしかしたらもっといい方法があるのかもしれませんが…個人的に一番しっくり来たのでこの方法を採用しました。

 

対処法ですが、まず置換したい文字列(ここではハッシュタグ)をいったん別の文字に置き換えます。
この時、他のキーワードと一致しないように特殊な文字列にするようにしましょう。
例えば、%をキーワードの頭と末尾に2つずつつけてみるとか。
サンプルコードは下記のとおりです。

var text = '[ハッシュタグを含む置換したい文字列]';
var result = str.replace(/(#\S+)/g, '%%$1%%');

上記のコードを実行すると、ハッシュタグが2つの%で囲まれた特殊な文字列に置き換えられます。
なお、正規表現でグループ化を使うと、$1 に一致した文字列が代入されるので、これを利用して文字列を置換していきます。

あとは、この文字列を最終的に置き換えたい文字列の形になるように置換します。
ここでは、タグでハッシュタグを囲んでいます。
サンプルは下記に。

result = result.replace(/%%(#\S+)%%/g, '<a href="[リンク先]">$1</a>');

全部通しで書くと下記のようになります。

var text = '[ハッシュタグを含む置換したい文字列]';

// %%[ハッシュタグ]%% となるように置換
var result = str.replace(/(#\S+)/g, '%%$1%%');

// %%[ハッシュタグ]%% を <a href="[リンク先]">[ハッシュタグ]</a> に置換
result = result.replace(/%%(#\S+)%%/g, '<a href="[リンク先]">$1</a>');

作業は以上で完了です。

 

以上、部分一致のある複数のキーワードをそれぞれ置換する方法でした。
今回はJavaScriptで紹介しましたが、もちろんPHPなどでも使うことができます。
是非、ご活用ください。

  • この記事いいね! (0)