20190226のJavaScriptに関する記事は29件です。

Nuxtでグーグルアドセンスの導入でハマったこと

こんにちは、とくめいチャットサービス「ネコチャ」運営者のアカネヤ(@ToshioAkaneya)です。

Nuxtに置いて、グーグルアドセンスの導入でハマったので記録しておきます。

Nuxtでグーグルアドセンスの導入でハマったこと

結論としては、Nuxtのグーグルアドセンスモジュールを使えば問題ありません。

これを使わないと、画面遷移やDOMの書き換えがおきた時に、アドセンスが正しく読み込まれないという不具合がおきてしまします。

はてなブックマーク・Pocketはこちらから

はてなブックマークに追加
Pocketに追加

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue Cli 3で作ったコンポーネントライブラリをnpmで公開する

自己紹介


@coppieee
https://coppieee.com
フリーランスプログラマ
Vue.js、TypeScript、Serverless、Cordovaとかやってます。


Vue.js コンポーネントライブラリを作成しました

Vue.jsでMaterial DesignしたくてVuetifyやVue Materialとかライブラリを触ってみたけど、
CSSなどいろいろカスタマイズし辛い。
なのでMaterial Designの勉強も兼ねて、Material Designの自作ライブラリを作りnpmに公開しました。
npm公開作業は結構簡単にできたのでnpm publishの方法を共有します。


npmで公開したもの

Vuterial

Material Designするための Vue.js コンポーネントライブラリ。
Materail Conponents for Webを使って実装してる。

https://github.com/coppieee/vuterial
https://coppieee.github.io/vuterial/


サンプル(ドキュメントページ)


コンポーネントをnpm publish して公開する手順

  • Vue CLI 3でプロジェクトを作成
  • build設定
  • package.json設定
  • npmjsにサインアップ
  • npm publish

Vue CLI 3でプロジェクトを作成

ライブラリを作成する場合もWebアプリと作るのと同様にVue CLIから作成します。

$ npm i -g @vue/cli
$ vue create your-library-name

特にライブラリ用に特殊な設定は必要ないので自分の好きなように設定しよう。
ライブラリ名は名前が被ってないかnpmjs.comでチェックしておきましょう。


Build設定

ライブラリのビルドはvue-cli-serviceにライブラリ生成用のビルドオプションがあるのでそれを使う。

$ vue-cli-service build --target lib --name your-library-name ./lib-main.js

それをpackage.jsonscriptsbuild-bundleなど適当な名前で設定しておくといいでしょう。

package.json
{
  "scripts":[
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "build-bundle": "vue-cli-service build --target lib --name your-library-name ./src/lib-main.js",
    ...
  ]
}

Build結果

$ npm run build-bundle

./distフォルダに以下のファイルが出力される

./dist
your-library-name.common.js
your-library-name.common.js.map
your-library-name.css
your-library-name.umd.js
your-library-name.umd.js.map
your-library-name.umd.min.js
your-library-name.umd.min.js.map

jsとcssを生成してくれる。
WebPackなどで使う場合はcommon.js、ブラウザで直接読み込む場合はumd.jsを使うことになる。
ライブラリの生成まで一つのコマンドでしてくれるVue CLI 3ってすげー。


ライブラリの実装例

今回はVue プラグインとして使う設定をしている。
ライブラリ使用者はVue.use(libraryName)の形式で使うことになる。以下一例。

lib-main.js
import { mdcChip } from './components/mdc-chip.vue'
import { mdcCard } from './components/mdc-card.vue'
import { mdcButton } from './components/mdc-button.vue'
// ...
export default const YourLibraryName = {
  install(Vue, options){
    const components = {
      mdcButton, // <mdc-button/> として使える
      mdcCard, // <mdc-card/> として使える
      // ...
    }
    for(const [name,c] of Object.entries(components)){
        Vue.component(name,c)
    }
  },
} 

package.jsonの設定

package.json
{
  "name": "your-library-name",
  "version": "0.1.0",
  "main":"dist/your-library-name.common.js", // エントリーポイント
  "unpkg": "./dist/your-library-name.umd.min.js", // CDN用(オプション)
  "jsdelivr": "./dist/your-library-name.umd.min.js", //CDN用(オプション)
  "typings":"dist/types/index.d.ts", //typescript用型ファイル(オプション)
  "license": "MIT",
  "author": "your name",
  "files": [
    "dist" // npm publish 対象のフォルダ
  ],
  "dependencies": {}, // distのみ公開の場合はdependenciesの中は空でOK
  "peerDependencies": { // 依存しているライブラリ(オプション)
    "vue": "^2.6.6",
    "vue-router": "^3.0.2"
  },
  "private": false,
  ...
}

npm publishに必要な設定はmainにエントリーポイントのパス設定と、filesでnpm にアップする対象を設定する。
privateをfalseに。
dependenciesにはdistだけを公開する場合は何も書かなくていい。
必要最低限の設定はそれだけであとはオプション。

ちなみに以下のファイルは、filesに指定しなくても自動的にアップされる。

  • package.json
  • README
  • CHANGELOG
  • LICENSE / LICENCE

unpkgとjsdelivrはCDN配布用で、設定するとそれぞれ
https://unpkg.com/your-library-name@latest
https://cdn.jsdelivr.net/npm/your-library-name@latest
というURLでjsファイルにアクセスできるようになる。
htmlのscriptタグのsrcで直接読み込む方式だ。

他にもいろいろ設定があるけど、githubに公開されてるvueとかvuetifyとかのpackage.jsonを見てみると参考になる。


npm login

ビルドの設定が終わったら次はいよいよnpmに公開する作業だ。
npm用のアカウントを作成してから、コンソールでログインする。

npm サインアップ

https://www.npmjs.com/signup

npm login

$ npm login

npm publish

$ npm run build-bundle
$ npm publish

npm 公開完了

https://www.npmjs.com/package/your-package-nameのようなURLで公開確認できる。

https://www.npmjs.com/package/vuterial


npm install example

npm に公開できたらプロジェクトを作成してnpm installしてみよう。

$ vue create my-project
$ cd vmy-project
$ npm i your-library-name

ライブラリをimport

ライブラリをimportしてVue.use()で設定する。
また、cssも使う場合は別途import。

main.js
import Vue from 'vue'
import YourLibraryName from 'your-library-name'
import 'your-library-name/dist/your-library-name.css'
Vue.use(YourLibraryName)

 まとめ

Vue コンポーネントをnpmに公開する場合もVue CLI 3を使うと簡単。


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】連想配列の値(value)で並び替え

連想配列の値で並び替えをしてみた。

以下のような連想配列を値が大きい順にソートしたかったので、挑戦してみました。

let obj = {
  "Apple" : 10,
  "Orange" : 5,
  "Banana" : 12,
  "Mango" : 2,
  "Melon" : 7,
}

キーと値にそれぞれキーをつけた連想配列を格納した配列の作成

let arr = let arr = Object.keys(obj).map((e)=>({ key: e, value: obj[e] }));
console.log(arr);

// [ { key: 'Apple', value: 10 },
//   { key: 'Orange', value: 5 },
//   { key: 'Banana', value: 12 },
//   { key: 'Mango', value: 2 },
//   { key: 'Melon', value: 7 } ]

※mapに訂正しました。

キー[value]でソート

上記で作成した連想配列を格納した配列をキー[value]でソートします。

arr.sort(function(a,b){
  if(a.value < b.value) return 1;
  if(a.value > b.value) return -1;
  return 0;
});
console.log(arr);

// [ { key: 'Banana', value: 12 },
//   { key: 'Apple', value: 10 },
//   { key: 'Melon', value: 7 },
//   { key: 'Orange', value: 5 },
//   { key: 'Mango', value: 2 } ]

いぇーい(^^)
すごく回りくどいけどソートすることができました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Garoonに登録した予定情報をkintoneにPOSTしてみた

はじめに

前回の記事
kintoneに登録した予定情報をGaroonにPOSTしてみた

の逆バージョン、

Garoon → kintone

になります。こっちの方が需要がありそうな気がします。

動作イメージ

イメージはつきやすいとは思いますが、こんな感じです。
grkin.png

kintoneへ登録することで、
「来訪」の割合を出したり「勉強会」の開催回数を出したり
が簡単にできる!kintoneのグラフ集計機能も使えるので便利!

事前知識

今回はGaroon側でカスタマイズするわけですが、Garoonのカスタマイズはkintoneと比べるとちょっとつらかったです (単に慣れてないだけかもですが ^^;)。

  • カスタマイズファイルのアップロード先がわかりくい
  • Garoon JavaScript API はそこまで充実しているわけではない

ファイルのアップロード先

Garoonはアプリケーションごとに管理が別れています。
スケジュールの場合は、
『Garoonシステム管理 > 各アプリケーションの管理(タブ) > スケジュール > JS/CSSによるカスタマイズ』
の順にいきます。うん。覚えられない。

で、カスタマイズグループを作成してJSファイルをアップロードします。

:pencil2: 豆知識
このカスタマイズグループでカスタマイズの適用ユーザーを指定することができる!
(Garoonは影響範囲が広いのでぜひ確認を)

Garoon JavaScript API

devnetの このページ に一覧があるのですが、そこまで多くはないのがわかると思います。
特にイベントは 表示系 しかないです。困った。

やりたいこと

やりたいことをシンプルに1行で表すと、
Garoonで予定を登録すると、その内容がkintoneの特定アプリにレコードとして保存される

です。もう少し技術的に表すと、

「Garoonの予定登録で保存ボタンが押されたら」
「Garoon側で記述した内容(日時、タイトル、参加者 等)を取得して」
「kintoneの適切なフィールドに値が入るようにレコードを新規追加する」

てな感じです。うん。わかりやすい

ポイント

今回も前回同様、なかなかスムーズにはいかなかったです(´;ω;`)
ざっと洗い出すと、以下がポイントかなと。

  • Garoonのイベント
  • ユーザー情報
  • 施設情報
  • 予定の公開方法

イベント

先ほども触れましたが、Garoon側には 表示イベント しか用意されていません。
kintoneでいうsubmitイベントがないんですよね・・・

まぁ、ないものをねだっても仕方がないので、
今回は addEventListener()で保存ボタンにイベントを追加することにしました

そのため非推奨のDOM操作です つД`)グスン

ユーザー情報

これは前回もありましたが、Garoonとkintoneではユーザー情報の内容が異なるので、kintone用に合せる必要があります。詳しくは前回の記事を!

施設情報

Garoonではユーザー情報と似た感じで施設(会議室など)の情報を保持しています。
が、kintone側にはそんなものないので、うまいこと保存できるようにする必要があります。

予定の公開方法

これはコードを作り終わって動作確認しているときに 「はっ!やべっ!」 と思った部分でした^^;
Garoon側で「非公開」としても、kintone側で公開されたらたまったもんじゃないです

ってことで、Garoon同様、参加者しか見れないようにします

kintoneアプリ

保存先のkintone側のアプリは以下のように作りました

フィールド

フィールドタイプ フィールドコード 用途
日時 start 開始日時
日時 end 終了日時
文字列 (1行) eventMenu メニュー
文字列 (1行) subject タイトル
ユーザー選択 attendees 参加者
文字列 (1行) facilities 施設
文字列 (複数行) notes メモ
ラジオボタン visibilityType 公開方法

↓ 配置するとこんなかんじ
スクリーンショット 2019-02-26 21.35.19.png

アクセス権

レコードの公開・非公開をラジオボタンで設定しています
スクリーンショット 2019-02-26 21.55.03.png

これで非公開のデート予定 飲み会 がバレずに済みますw

コード

全体は GitHub で公開しています。

イベント処理

Garoonのイベントと保存ボタンのonclickイベント
addEventListener('click', handler(), true) この最後に true を指定することで、ボタンを押したら最初に動くようになりました。

が、詳しくは知りません。キャプチャとバブリングがどうたらとネットに書いてありましたw

  // Garoonのイベント
  garoon.events.on('schedule.event.create.show', () => {
    // 保存ボタンの取得 (※DOM操作)
    const submit = document.getElementById('schedule_submit_button');
    if (!submit) {
      return;
    }
    // 保存ボタンのクリックイベントに下記処理を追加
    submit.addEventListener('click', () => {

処理

kintoneに合わせてごにょごにょします

      // ユーザーのidとtypeを削除 (kintoneでは必要ないため)
      e.attendees.forEach((ele, i) => {
        delete e.attendees[i].id;
        delete e.attendees[i].type;
      });

      // スケジュールの公開方法
      const visibilityType = e.visibilityType === 'PUBLIC' ? '公開' : '非公開';

      // 施設情報 (テキスト1行で表現)
      let facilities = e.facilities.map(ele => {
        return ele.name;
      });
      facilities = facilities.join(', ');

レコード登録

GaroonにはjQueryがもともと入ってるので (グローバル?)、ajaxでPOSTします。

Garoonイベントで受け取れるオブジェクトはなかなか複雑なので頑張りましょう

注意点 :warning:

addEventListener('click', handler(), true) でイベントを登録すると、
Garoonのエラーチェックの前に レコードを登録してしまいます。
-> 施設が重複でエラーとなっても、kintone側には登録されてしまいます

でも他に良い方法が思いつかず今回は断念・・・
-> submitイベントさえつけば、、、(どうせなら submit.success もつくと良いな〜)

おわりに

なかなか思い通りにはいかないガルキン連携です。
Garoon側がエラーでもkintoneへ保存されるのはどうにかしたい。。Promise対応できないかね〜

ただ、前回よりは今回のほうが需要があると信じてます!!
それでは!≧(+・` ཀ・´)≦

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AnimateCCで生成したファイルの画像をbase64化する方法

概要

ゲームの広告だがそのゲームの一部を疑似体験できる、プレイアブルアドという代物を実装することになった。
アプリ上のwebviewで表示されるので、ターゲットブラウザはsafariとchrome。
通常のhtml,css,jsでイケるのだが、複雑なことになると工数かかりそうだなーと思っていたがAdobe AnimateCCという持て余しまくっているツールのことを思い出したので、それで作ってみた。快適快適。
が、とある広告プラットフォームの入稿のフォーマットは単一htmlのみ。
画像のパスをbase64にすれば良いだけの話がいたくハマったので、解決策をここに記す。

間違い

animteCCから書き出されたjsにこんな記載があります。

lib.properties = {
    id: 'CBE7D0B014C34055B50EB7B1A2F1A211',
    width: 640,
    height: 1136,
    fps: 24,
    color: "#FFFFFF",
    opacity: 1.00,
    manifest: [
        {src:"images/test_atlas_.png?1551178733007", id:"test_atlas_"}
    ],
    preloads: []
  };

これだけ見ると、srcの中身をbase64化したものに変えるだけで良いと思うが、全然動きません。
理由は、裏でPreloadJSが動いているから。
animateCCは基本的にCreateJSにおんぶにだっこなので、マニフェスト内の画像はPreloadJSによって事前ロードされます。
なので、base64をhtml内のimgタグに書き、jsでそいつを読み込んであげてanimate内の画像管理部分に紐づけてあげる、までを自前でやる必要があります。

htmlに追記する

html内にimgタグでbase64を書いちゃいましょう。

<img id="test_atlas_" style="display:none" width="2048" height="2048" title="" alt="" src="data:image/png;base64,iVBORw0K...">

canvasの下あたりにimgタグを追加します。display:noneにしておくことを忘れず。
idは、上で紹介したmanifestのidと同じ名前にしましょう。

jsを改造する

animateでエクスポートしたjsに変数を追記

最後のほうで、グローバル変数を定義している部分があるので、createjs, AdobeAn,に続き、「images」を追加します。

})(createjs = createjs||{}, AdobeAn = AdobeAn||{});
var createjs, AdobeAn, images;

htmlのインラインjsでpreloadの記載を修正

init()の上からすぐに見つかると思うので、この5行をコメントアウトします。

// var loader = new createjs.LoadQueue(false);
// loader.addEventListener("fileload", function(evt){handleFileLoad(evt,comp)});
// loader.addEventListener("complete", function(evt){handleComplete(evt,comp)});
// var lib=comp.getLibrary();
// loader.loadManifest(lib.properties.manifest);

そして、下記を追加します。
images変数を初期化し、htmlにべた書きしたbase64の画像と、manifestのidを紐づけています。

images = images||{};
var manifest = lib.properties.manifest;
for (var i=0, l=manifest.length; i<l; i++) {
    var id = manifest[i].id;
    var img = document.getElementById(id);
    if (img != null) {
        images[id] = img;
    }
}
handleComplete(comp);

もうちょい修正

loaderの記述のすぐ下のほうに、handleCompleteという関数があります。
修正前はloaderのcompleteイベントも一緒に渡していたのですが、loader使わないので引数を修正します。

//function handleComplete(evt, comp) {
function handleComplete(comp) {

さらにすぐ下のほう、この一文もいらないのでコメントアウト。

// var queue = evt.target;

最後です。さらにすぐ下のほう。for文でloaderから画像の本体を引っ張ってくる部分を、loaderではなく自前で用意したimagesに置き換えてあげます。

for(i=0; i<ssMetadata.length; i++) {
    // ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [queue.getResult(ssMetadata[i].name)], "frames": ssMetadata[i].frames} )
    ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [images[ssMetadata[i].name]], "frames": ssMetadata[i].frames} )
}

終わり

これで画像をソース内に入れ込むことができました!
cdnから読んでるcreateJSもインラインに含めてしまえば、立派な入稿用単一htmlが完成しました!
プレイアブルアドの実装を考えている方の参考になれば幸いです。ニッチすぎる!!!!
現場からは以上です。

参考(これしかなかった)
https://www.reddit.com/r/createjs/comments/4dfldb/how_do_i_use_base24_instead_of_external_library/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

styled-componentとreact-transition-groupでお手軽にtransitionやanimationをかける

Reactでアニメーションをさせたい時、react-posereact-springなどのライブラリがある。これらライブラリはすごくリッチなのだがちょちょっとCSSのtransitionを使うぐらいの時には若干オーバーになる。

一方で過去公式だった(今はコミュニティ運用) react-transition-groupもある。こちらは非常にシンプルだ。

styled-componetsでさくっとアニメーションさせたい時、react-transition-group<Transition>を使うと割とさくっとできることに気付いたのでまとめたい。

例示

まずTransitionを利用する側を書く。
この例ではReact Hooksを使っているが別にそこは本筋ではないのでclass componentsでも問題無い。

import { Transition } from "react-transition-group"
import { Animation } from "./Animation"

export const AnimateItem = () => {
  // animationの状態を持つのにstateが必要。ここだけは面倒だけどしょうがない
  const [animate, setAnimate] = useState(false)

  // ボタンを押したらtrueになって3000ms後にfalseになるように仕組む
  const doAnimate = useCallback(() => {
    setAnimate(true)
    setTimeout(() => {
      setAnimate(false)
    }, 3000)
  }, [])

  return (
    <div>
      {/* Transition は `in` に渡した値で変化する */}
      <Transition in={animate} timeout={500}>
        {(state) => (
          // stateは下記の順序で変遷する
          // exited -> entering -> entered -> exiting -> exited
          <Animation state={state}>Hello</Animation>
        )}
      </Transition>
      <button onClick={doAnimate}>Animate</button>
    </div>
  )
}

次にanimationを設定するstyled-components側を作る。
propsのcallbackを受け取れるのでこれに応じて値を変えるだけだ。

// Animation.js
import styled from "styled-components"

export const Animation = styled.div`
  transition: 0.5s;
  width: 300px;
  height: 200px;
  /* 要素を動かす */
  transform: translateX(
    ${({ state }) => (state === "entering" || state === "entered" ? 400 : 0)}px
  );
  /* 色を変える */
  background: ${({ state }) => {
    switch (state) {
      case "entering":
        return "red"
      case "entered":
        return "blue"
      case "exiting":
        return "green"
      case "exited":
        return "yellow"
    }
  }};
`

Animationの部分がちょっと分厚くなったり汚くなりがちなので、例えば基礎となる要素とanimation部分を分けて書くのもよいだろう

const BaseItem = styled.div`
  width: 300px;
  height: 200px;
`

export const Animation = styled(BaseItem)`
  transition: 0.5s;
  transform: translateX(
    ${({ state }) => (state === "entering" || state === "entered" ? 400 : 0)}px
  );
`

結果

a.gif

例えばfadeIn / fadeOutするなら

この理屈で例えばアニメーションの前後で要素を消したいfadeInのようなものを作るならこんな感じだろう

export const Fade = styled.div`
  transition: 0.5s;
  opacity: ${({ state }) => (state === "entered" ? 1 : 0)};
  display: ${({ state }) => (state === "exited" ? "none" : "block")};
`

もしくは若干開始タイミングの制御が雑でもよければunmountOnExitmountOnEnterを利用して下記のような方法もある

export const Fade2 = styled.div`
  transition: 5s;
  opacity: ${({ state }) => (state === "entered" ? 1 : 0)};
`

const Item = () => {
  // ...
  return <Transition in={animate} timeout={500} unmountOnExit mountOnEnter>
    {(state) => <Fade2 state={state}>Fade In</Fade2>}
  </Transition>
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

複数のフォームデータを、javascriptを使って1つのボタンで送信する方法

複数フォームの内容をワンクリックで送信する方法を書きます。

結論
submitボタンのフォームにhiddenでフォームの数だけinputを作り、
ボタンを押した時にjavascriptを呼び出して、
入力されているフォームの内容を、json形式にして、
hiddenのinputのvalueにセットする。

そうすることで、複数フォームの内容をワンクリックで送信することができる。

例えば、

<select id="select">
  <option value="0" >0</option>
  <option value="1" >1</option>
  <option value="2" >2</option>
  <option value="3" >3</option>
  <option value="4" >4</option>
</select>

<textarea id="textarea"></textarea>

<form method="POST" action="/worktimes/edit/" id="post_form">
    <input type="hidden" name="form1" value="" />
    <input type="hidden" name="form2" value="" />
    <button type="submit" >送信</button>
</form>

という2つのフォームがあったら、
呼び出したjsファイル内で下記の処理を書く

// 送信ボタンが押された時に呼び出されるjsファイル内の関数
$('#post_form').submit(function () {
        var selectJsonData = get_select_data_by_json(); // selectの内容をjsonで取得
        $("input[name='form1']").val(selectJsonData); // form1のvalueにselectの内容をセット
        var textareaJsonData = get_textarea_data_by_json(); // textareaの内容をjsonで取得
        $("input[name='form2']").val(textareaJsonData); // form2のvalueにtextareaの内容をセット
        return true;
});

function get_select_data_by_json() {
    var select = $( '#select' + i ).val(); // idを元にselectのvalueの内容を取得
    return JSON.stringify(select); // JSON形式でリターン
}

function get_textarea_data_by_json() {
    var element = document.getElementById( 'textarea' ); // idを元にselectの内容を取得 
    var textarea = element.value; // selectのvlueを取得
    return JSON.stringify(textarea); // JSON形式でリターン
}

保存ボタンクリック→js関数実行→フォームのvalueに値セット→アクション実行
という処理の流れなので、
コントローラ側に値が渡される。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

jQuery UI Datepickerでちょっと引っかかった話

過去ブログのQiitaへの移転シリーズ第4弾、今回はこの記事を移転してみました。

今回はDatepickerというjQueryの機能を紹介したいと思います(Datepicker自体はjQuery以外の実装もあるんですが、自分が使ったことがあるのがjQueryのものだけなので、あくまで今回はjQueryに限った話です)。

Datepickerとは、テキストボックスをクリックするとカレンダーが出てくるやつで、皆さんも入力フォームとかでよく見るかと思います。
201708161617_datepicker1.png
これが・・・
201708161610_datepicker2.png
こんな感じになるやつです。

使い方についてはこちらを見ていただければわかるかと思いますが、結構簡単です。 ちなみに、リンク先ではid="datepicker"としていますが、クラスでやることもできます。クラスだと該当するクラス名の箇所では全てDatepickerが使えるようになります。 クラスの場合だと、functionの中は

$("".datepicker).datepicker();

となります。

なぜこの記事でDatepickerを紹介しようと思ったかと言いますと、その当時Datepickerでちょっとやらかして、うまく使えていないことがありまして、その備忘録も兼ねてということです。 ちなみに何があったかと言いますと、テキストボックスをクリックしてもカレンダーが出てこず、しかもページの下の方を見ると本来カレンダーの中に含まれるはずの内容が延々と表示されていました。(注意、画像は結構長いです)
201708161620_datepicker_err1.png
201708161629_datepicker_err2.png

最初一瞬何事かと思いましたが、右クリックで検証ツールを開いてコードをよく見てみると、datepickerのcssが当たっていないことがわかりました。 何でcssが当たっていないのか調べるためにblade(Laravelなので)を見てみると、ちゃんと機能しているページではJavaScriptを読み込んでいるところとCSSを読み込んでいるところの順番の対応がうまく取れていたようなのですが、今回の現象が起きた箇所ではその順番の対応に問題があったようで(詳しく書くと長くなるので詳細は略します)、読み込む順番を機能しているページと同じ順番にすると、ちゃんとうまくいきました。

今回の教訓としては、便利なツールもちゃんと読み込めるよう正しく使ってこそ、ということですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング学習記録10〜10日続けてよかった〜

今日やったこと

  • Progate JavaScript4,5,6リセット復習

昨日やったところを復習しました。

インポートとエクスポートがこんがらがってよくわからなかったのですが、今日復習してみて理解しました。

どれが親クラスでどれが子クラスなのかを把握してれば、こんがらないということがわかりました。

親クラス・子クラスを把握すると、ファイルを分割しても、どこからインポートすればいいかがわかります。

Progate JavaScriptは卒業

今日でProgateは、

  • HTML&CSS
  • JavaScript
  • Ruby
  • Python
  • Command Line
  • Git

が一通り終わりました。

まだ、Gitは1周しかしていないので、理解が浅く、もう2、3周はする必要がありますが、他の言語に関してはもう十分な気がします。

なので、明日からは前からやろうと思っていたUdemyの「Web開発入門完全攻略コース - プログラミングをはじめて学び創れる人へ!未経験から現場で使える開発スキルを習得!」を進めていきたいと思います。

レッスンを進めていく中でわからない部分、忘れた部分があればProgateのスライドを検索して復習しながら進めていこうと思います。

10日連続でQiitaに学習過程を記録して思ったこと

結論からいうと、Qiitaに学習過程を記録し始めてよかったです。

Qiitaに書くことを意識しながら学習することで、より質の高い学習ができてる気がします。

あと、一目に触れるのを意識することで多少めんどくさくても「やらなきゃな」という気持ちになれます。

Qiitaはなんとなく敷居が高そうに見えて、投稿をためらってしまいがちだと思うのですが、間違ったら訂正すればいいし、自分でクソだと思ったら投稿を消せばいいだけです。

投稿することで批判されることのデメリットよりも、投稿することで質のいいインプットができるメリットの方が大きいので、やっていない方は一度やってみることをオススメします。

ということで、明日からも引き続きプログラミング学習を頑張っていきたいと思います。

おわり

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メモ:jsファイルのキャッシュがクリアされない

CakePHP2系でjsファイルを触ってた時
編集しても編集してもエラーが消えないからなんでかなー思ってたらキャッシュがずっと残ってた。

Chromeのキャッシュクリアもしたけど全然更新されないから
jsのファイル名変えたらいけた。
jsファイル、この名前が使っちゃダメだよみたいなのあるの...?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

canvasのサイズ指定に気をつけろ

はじめに

canvasのサイズを変更するときに挙動がおかしくなってしまう人のための記事です。

検証してみた

- 良い例 -

  • cssで指定せずに幅、高さを設定する

canvas.width = 500;
canvas.height = 500;

yes.png

- 悪い例 -

  • cssで幅、高さを設定

canvas.style.width = 500 + "px";
canvas.style.height = 500 + "px";

no.png

canvasを使ってみた

test.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>hand spinner</title>
    <style> 
        body {
            margin: 0;
            background-color: #000;
        }
    </style>
</head>
<body>
    <div id="main"></div>
    <script>
        const hand_spinner = (leftX, topY, hand_spinner_count) => {
            let main = document.getElementById('main');
            main.style.position = "relative";
            let canvas = document.createElement('canvas');
            canvas.width = 200;
            canvas.height = 200;
            canvas.style.left = leftX + "px";
            canvas.style.top = topY + "px";
            canvas.style.position = "absolute";
            main.appendChild(canvas);
            let rgb = {
                    r: Math.floor(Math.random() * 256),
                    g: Math.floor(Math.random() * 256),
                    b: Math.floor(Math.random() * 256) 
                };
            const draw_circle = (x_center, y_center, radius) => {
                let context = canvas.getContext('2d');
                context.strokeStyle = `rgb(${rgb.r},${rgb.g},${rgb.b})`; 
                context.beginPath();
                context.arc(x_center, y_center, radius, 0, Math.PI * 2, false);
                context.closePath();
                context.stroke();
            }
            draw_circle(100, 100, 20);
            draw_circle(100, 49, 30);
            draw_circle(100, 151, 30);
            draw_circle(49, 100, 30);
            draw_circle(151, 100, 30);
            draw_circle(100, 100, 10);
            draw_circle(100, 49, 20);
            draw_circle(100, 151, 20);
            draw_circle(49, 100, 20);
            draw_circle(151, 100, 20);

            let transform_t_clockwise = 0;
            let transform_t_counterclockwise = 360;
            let speed = Math.floor(Math.random() * 6) + 2; 
            let magic_interval;
            if(hand_spinner_count % 2 === 0) {
                magic_interval = setInterval(() => {
                    canvas.style.transform = `rotateZ(${transform_t_clockwise}deg)`;        
                    transform_t_clockwise += speed;
                    if(transform_t_clockwise >= 360) {
                        transform_t_clockwise = 0;
                    }
                }, 1);
            } else {
                magic_interval = setInterval(() => {
                    canvas.style.transform = `rotateZ(${transform_t_counterclockwise}deg)`;
                    transform_t_counterclockwise -= speed;
                    if(transform_t_counterclockwise <= 0) {
                        transform_t_counterclockwise = 360;
                    }
                }, 1);
            }
            setTimeout(() => {
                clearInterval(magic_interval);
                main.removeChild(canvas);
            }, 1000);  
        }
        const call_hand_spinner = () => {
            let hand_spinner_count = 0;
            let main_magic_interval = setInterval(() => {
                hand_spinner(
                    Math.floor(Math.random() * 1601),
                    Math.floor(Math.random() * 701), 
                    hand_spinner_count
                );
                hand_spinner_count++;    
            }, 15);
            addEventListener('keydown', (event) => {
                switch(event.keyCode) {
                    case 81: //81 == q
                        clearInterval(main_magic_interval);
                        break;
                    case 82: //82 == r
                        location.reload();
                        break;
                }
            });
        }
        call_hand_spinner();
    </script>
</body>
</html>

test.html結果

  • 一番スムーズに動いたブラウザはchromeです(画面size: 1920*1080)。

thank you!!!

@altさん編集リクエストありがとうございます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

bitcoinjs-lib v4を使ったhdwalletスニペット

bitcoinjs-lib hdwallet

  • 階層的決定性ウォレット
  • この記事はbitcoinjs-lib@4系です
  • バージョン3系と後方互換性がなくなっています

v3との簡単な違い

  • モジュールの名前空間変更 HDNode -> bip32
  • address取得方法の変更
  • bip32周りのメソッド名の変更

install

npm i bip39 bitcoinjs-lib

mnemonic generate

12 word

const mnemonic = bip39.generateMnemonic();

24 word

const mnemonic = bip39.generateMnemonic(256);

mnemonic to masternode

const mnemonicToM = (mnemonic, password, network) => {
    const seed = bip39.mnemonicToSeed(mnemonic, password || "")
    const m = bitcoin.bip32.fromSeed(seed, bitcoin.networks[network || "bitcoin"])
    return m
}

master extended private key

m.toBase58()

extended private key

m.deriveHardened(44).deriveHardened(0).deriveHardened(0).toBase58()
m.derivePath("m/44'/0'/0'").toBase58()

extended public key

m.deriveHardened(44).deriveHardened(0).deriveHardened(0).neutered().toBase58()
m.derivePath("m/44'/0'/0'").neutered().toBase58()

bitcoin address

address

  • address生成用のラッパーを作ったほうが楽です
const getAddress = (node) => {
    return bitcoin.payments.p2pkh({ pubkey: node.publicKey }).address
}
getAddress(m.derivePath("m/44'/0'/0'/0/0"))

private key

m.derivePath("m/44'/0'/0'/0/0").toWIF()

とりあえず実行してみる

const bitcoin = require("bitcoinjs-lib")
const bip39 = require("bip39")

const mnemonicToM = (mnemonic, password, network) => {
    const seed = bip39.mnemonicToSeed(mnemonic, password || "")
    const m = bitcoin.bip32.fromSeed(seed, bitcoin.networks[network || "bitcoin"])
    return m
}

const getAddress = (node) => {
    return bitcoin.payments.p2pkh({ pubkey: node.publicKey }).address
}

const mnemonic = bip39.generateMnemonic();
const m = mnemonicToM(mnemonic, '', 'bitcoin')
console.log(mnemonic)
console.log(m.derivePath("m/44'/0'/0'").toBase58())
console.log(m.derivePath("m/44'/0'/0'").neutered().toBase58())
console.log(getAddress(m.derivePath("m/44'/0'/0'/0/0")))
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js のカスタムディレクティブの使い方とフック関数のタイミングを理解する

はじめに

Vue.js(2.6.7)のカスタムディレクティブに関しての備忘録です。

そもそもディレクティブとは?

テンプレートに記述できるv-から始まる属性のこと。

様々なディレクティブが存在し、属性値に応じた DOM 操作ができる。

以下は DOM 操作の例。

  • 要素の表示制御
  • データバインディング
  • イベントリスナのアタッチ

ディレクティブの利用例

以下はv-show(値に応じて要素のstyle.displayプロパティを変更するディレクティブ)の利用例。

<div id="app">
  <h1 v-show="ok">Hello!</h1>
</div>
const vm = new Vue({
  el: '#app',
  data: {
    ok: true
  }
});
// `ok`を`false`にすれば、`<h1 v-show="ok">Hello!</h1>`は非表示になる。
// vm.$data.ok = false;

See the Pen Vue.js v-show by soarflat (@soarflat) on CodePen.

dataoktrueの場合、<h1>Hello!</h1>は表示され、falseの場合、<h1 style="display:none;">Hello!</h1>となり表示されない。

この他にも様々なディレクティブが存在する。詳細は公式ドキュメントを参照。

ディレクティブ

カスタムディレクティブとは?

自作したディレクティブ、もしくは自作したディレクティブを登録できる機能(仕組み)のこと。

カスタムディレクティブを利用することで、属性の付与もしくは属性値の変化に伴う DOM 操作を定義できる。

なぜカスタムディレクティブを利用するのか(カスタムディレクティブの使い所)

前述の通り、v-showは値に応じてstyle.displayプロパティを変更しているだけなので、この DOM 操作は自前でも定義できる。

しかし、ディレクティブという仕組みを利用することで、それぞれのコンポーネント(Vue インスタンス)に「値に応じてstyle.displayプロパティを変更する DOM 操作」を定義せずとも、共通の DOM 操作が可能になる。

そのため、複数のコンポーネント(Vue インスタンス)で独自の DOM 操作を共通化したい場合、カスタムディレクティブを定義する。

カスタムディレクティブの利用例

以下は、v-focusというカスタムディレクティブを定義する例。

ページを読み込む(Vue インスタンスをマウントする)とinput要素に自動でフォーカスが当たるようにする。

Vue.directive('focus', {
  inserted(el) {
    el.focus();
  }
});

insertedはカスタムディレクティブと紐付いた要素が親 Node に挿入された時に呼ばれるフック関数。引数elには親 Node に挿入された要素が渡される。

カスタムディレクティブと要素を紐付けるためには、以下のように定義したv-focusを付与する。

<input v-focus>

今回の場合、このinput要素が親 Node(今回の場合はbody要素)に挿入された時にinsertedが呼び出され、引数elに挿入されたinput要素が渡される。

実際に動作するコードは以下の通り。

<input id="input" v-focus>
Vue.directive('focus', {
  // `el`に`input`要素が渡されるので、それにフォーカスを当てる
  inserted(el) {
    el.focus();
  }
});

new Vue({
  el: '#input'
});

See the Pen Vue.js CustomDirective example by soarflat (@soarflat) on CodePen.

ローカルディレクティブに登録する

directivesオプションを利用すれば、コンポーネント毎にカスタムディレクティブを登録できる。

<input id="input" v-focus>
new Vue({
  el: '#input',
  directives: {
    focus: {
      inserted(el) {
        el.focus();
      }
    }
  }
});

フック関数

前述のinsertedを含め、カスタムディレクティブでは以下のフック関数を利用できる。

  • bind: カスタムディレクティブが初めて対象の要素に紐付いた時に1度だけ呼ばれる。
  • inserted: カスタムディレクティブと紐付いた要素が親 Node に挿入された時に呼ばれる。
  • update: 紐付いた要素を抱合しているコンポーネントの VNode が更新される度に呼ばれる(子コンポーネントが更新される前に呼ばれる)。
  • componentUpdated: 紐付いた要素を抱合しているコンポーネントの VNode と子コンポーネントの VNode が更新された時に呼ばれる。
  • unbind: 紐付いた要素からディレクティブが取り除かれた時に呼ばれる。

それぞれのフック関数が呼ばれるタイミングを理解する

以下は全てのフック関数が呼ばれるサンプル。

<div id="app">
  <h1 v-message v-if="message">{{ message }}</h1>
  <button @click="update">update</button>
  <button @click="remove">remove</button>
  <button @click="init">init</button>
</div>
Vue.directive('message', {
  bind(el) {
    console.log('bind');
    console.log('el.parentNode(bind)', el.parentNode);
  },
  inserted(el) {
    console.log('inserted');
    console.log('el.parentNode(inserted)', el.parentNode);
  },
  update(el) {
    console.log('update');
    console.log('el.innerHTML(update)', el.innerHTML);
  },
  componentUpdated(el) {
    console.log('componentUpdated');
    console.log('el.innerHTML(componentUpdated)', el.innerHTML);
  },
  unbind(el) {
    console.log('unbind');
  }
});

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  methods: {
    update() {
      this.message = 'Hello React!';
    },
    remove() {
      this.message = '';
    },
    init() {
      this.message = 'Hello Vue!';
    }
  }
});

See the Pen Vue.js Hook Functions(Custom Directives) by soarflat (@soarflat) on CodePen.

それぞれのフック関数がどのタイミングで呼ばれるのかは、以下の通り。

  • ページロード時(Vue インスタンスを生成時): bindinserted
  • 「update」ボタンをクリック時: updatecomponentUpdated
  • 「remove」ボタンをクリック時: unbind
  • 「init」ボタンをクリック時(「remove」ボタンをクリックした後): bindinserted

ページロード時(Vue インスタンスを生成時)

bindinsertedが呼ばれて以下がコンソール出力される。

// bind
// el.parentNode(bind) null
// inserted
// el.parentNode(inserted) <div id=​"app">​…​</div>​

insertedは親 Node に挿入された時に呼ばれるため、parentNode<div id=​"app">​…​</div>​)が存在する。

「update」ボタンをクリック時

this.message"Hello React!"になる。

updatecomponentUpdatedが呼ばれて以下がコンソール出力される。

// update
// el.innerHTML(update) Hello Vue!
// componentUpdated
// el.innerHTML(componentUpdated) Hello React!

updateが呼ばれた時点では、子コンポーネントの VNode({{ message }})は更新されていないため、el.innerHTMLの結果は"Hello Vue!"

componentUpdatedが呼ばれた時は、子コンポーネントの VNode も更新された後のため、el.innerHTMLの結果は"Hello React!"

「remove」ボタンをクリック時

this.message""になる。

今回紐付けをした要素はv-if="message"を付与しており、このタイミングで<h1 v-message v-if="message">{{ message }}</h1>が破棄されunbindが呼ばれる。

// unbind

「init」ボタンをクリック時(「remove」ボタンをクリックした後)

this.message"Hello Vue!"になる。

<h1 v-message v-if="message">{{ message }}</h1>が再生成され、bindinsertedが呼ばれて以下がコンソール出力される。

// bind
// el.parentNode(bind) null
// inserted
// el.parentNode(inserted) <div id=​"app">​…​</div>​

フック関数に渡される引数

el以外にも複数の引数が渡される。詳細は公式ドキュメントを参照。

ディレクティブフック引数

終わり

間違いがあれば、ご指摘いただけると幸いでございます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GASで文字列の前方一致、後方一致判定をする

tl;dr

  • GASに startsWith, endsWith なんてものは今のところない(2019/02/26)
  • なので自作してまとめておく

メソッドにしておく

何度も同じ判定処理を書くのもアレなのでメソッドにしておく。(メソッド名はそのままとしたが、必要に応じて修正してください)

なお、意図した挙動をしているように見えるが、あんまりテストしてない。

なので、テストコードとかもうちょいまとめたら GitHub にリポジトリ作っておくかも。

前方一致

function startsWith(target, pattern) {
  return target.indexOf(pattern) === 0; 
}

後方一致

function endsWith(target, pattern) {
  return ((target.lastIndexOf(pattern) + pattern.length) === target.length)
         && (pattern.length <= target.length);
}

参考にしたサイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【最新サービス試用④】Gitの差分を視覚的に楽しめて、イメージの手助けとなる、「Git History」を試用

  • 日々輩出される素晴らしき最新サービスを素早く試して、不鮮明な先見性を堂々と誇示する記事第四弾。
  • あるドラマでの、「真似事でも、必死で見習えば、それは本物だから」という刺激的名言を、「山盛り解釈・少々捏造」の行為で、大量模倣の許可を得たと被害妄想。
  • 今回は、GitHubの差分が、視覚的に楽しく把握できる「GitHistory」を試用することにしよう。

試用サービス名

Git History

概要

  • 把握しづらい差分を、視覚的に動きをつけて表示してくれる。
  • コミッターやメッセージも非常に見やすい。
  • インストール不要で、GitHub上でURLを変えるだけでよい。
  • 初学者がイメージをつかむのに適している

結果

  • 下記の例は、GitHub上の「Vue.js」のpackage.jsonファイル
  • バージョンの変化が把握できる。

tes.gif

基本手順

1. GitHubへ行く。

2. 差分を表示したいファイルを開く。

※GitHubアカウントを持っていない場合は、気になるオープンソースプロジェクトのファイルでも良い。

GitHubのスター数(評価数)ランキングはこちら

3. ファイルのURLを下記のように変更

※例では、「Vue.js」のpackage.jsonを使用。

<変更前> : https://github.com/vuejs/vue/blob/dev/package.json

<変更後> : https://github.githistory.xyz/vuejs/vue/blob/dev/package.json
  • 例のように、URLの「github.com」の部分を、「github.githistory.xyz」へ変更

4. 表示確認。

image.png

5. 左右矢印キーで、差分確認

※だいぶ奥深くでの変更等はわかりづらい。

6. 差分を詳細に見たい場合は、コミッター欄のリンクで、確認。

※各コミットファイルへアクセスできる。

image.png

image.png

7. 完了

試用感

  • 差分を視覚的なアニメーションで楽しめる。
  • 奥深くの差分や多くの量等の、一発では把握しにくいものもある。
  • しかし、各個別の差分ファイルへのリンクがあるので良い。
  • Git環境がなくても、簡単にできる。
  • 初学者がGitの概念やイメージを把握しやすい。

まとめ

  • 今回は、差分表示の視覚的把握ということで、「将来、散髪や化粧・体重変化等が、鮮やかに把握できる視覚機器が出ないかな。」という、高等級男性の特徴的行動までも自己解決しない、底辺等級人の私。
  • 「今回もJavaScript製とはね」という、この言語の多様性・可能性を身に染みて再認識。
  • 試用後の恒例行事の「開発者への礼拝作業」に、今回は「全開発者への魅力サービス開発祈願」という、本来の意味を大きく逸れた礼拝を追加することにしよう。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

prototypeの継承

prototypeの継承って。

  • ptototypeで継承すると参照するかたちになってメモリの無駄な消費をさけることができる
  • 複数のprototypeを継承できる
// Animal関数を定義
function Animal(name,weight){
   this.name = name;
   this.weight = weight;

   this.getName = function(){
     return this.name;
   }
   this.getWeight = function(){
     return this.weight;
   }
}

// Animal関数のプロトタイプに isHeavy 関数を定義
Animal.prototype.isHeavy = function(){
    if(this.weight > 100){
      return 'heavy';
    }else{
      return 'right';
    }
}

// golira インスタンスを作成
var golira = new Animal('golira',120);

console.log(golira.getName()); // golira
console.log(golira.getWeight()); // 120
console.log(golira.isHeavy()); // heavy

console.log(golira); // __proto__の中に isHeavy() 関数がある
/*
Animal {name: "golira", weight: 120, getName: ƒ, getWeight: ƒ}
getName: ƒ ()
getWeight: ƒ ()
name: "golira"
weight: 120
__proto__:
isHeavy: ƒ ()
constructor: ƒ Animal(name, weight)
__proto__: Object
*/

console.log(Animal.prototype);  // {isHeavy: ƒ, constructor: ƒ}

prototypeに登録した関数も呼び出し方は .(ドット)関数名でOK。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webサイト『 Map API 』の高い学習コストを超低くするライブラリ~BmapQuery.js~ (解説本ダウンロード)

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webサイト『 Map API 』の高い学習コストを低くするライブラリ~BmapQuery.js~

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Web『 Map API 』の学習コスト「100 →10」にするライブラリ~BmapQuery.js~ を公開

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Web『 Map API 』の学習コスト「High→Low」にするライブラリ~BmapQuery.js~ を公開

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

 

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

 

◇3.ライブラリを使って「経路検索」

【処理内容】
・経路検索

経路検索:経由地あり(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地あり
const array = ["新宿", "恵比寿"];                     //Waypoints...
map.direction("#direction", "walking", "御茶ノ水", "表参道", array);  //walking or driving

SnapCrab_NoName_2019-2-26_8-57-33_No-00.png

 

経路検索:経由地なし(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地なし
const array = [];
map.direction("#direction", "walking", "御茶ノ水", "表参道, array ); //walking or driving

SnapCrab_NoName_2019-2-26_9-2-54_No-00.png

 
  

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Web『 Map API 』の学習コスト100→10にするライブラリ~BmapQuery.js~ 公開

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

 

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

 

◇3.ライブラリを使って「経路検索」

【処理内容】
・経路検索
ライブラリ使用: 3~4行
ライブラリ不使用:60~80行

経路検索:経由地あり(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地あり
const array = ["新宿", "恵比寿"];                     //Waypoints...
map.direction("#direction", "walking", "御茶ノ水", "表参道", array);  //walking or driving

SnapCrab_NoName_2019-2-26_8-57-33_No-00.png

 

経路検索:経由地なし(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地なし
const array = [];
map.direction("#direction", "walking", "御茶ノ水", "表参道, array ); //walking or driving

SnapCrab_NoName_2019-2-26_9-2-54_No-00.png

 
  

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Web『 Map API 』の学習コスト100→10にするライブラリ「BmapQuery.js」

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

 

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

 

◇3.ライブラリを使って「経路検索」

【処理内容】
・経路検索
ライブラリ使用: 3~4行
ライブラリ不使用:60~80行

経路検索:経由地あり(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地あり
const array = ["新宿", "恵比寿"];                     //Waypoints...
map.direction("#direction", "walking", "御茶ノ水", "表参道", array);  //walking or driving

SnapCrab_NoName_2019-2-26_8-57-33_No-00.png

 

経路検索:経由地なし(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地なし
const array = [];
map.direction("#direction", "walking", "御茶ノ水", "表参道, array ); //walking or driving

SnapCrab_NoName_2019-2-26_9-2-54_No-00.png

 
  

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。

本を(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『 Map API 』学習コスト100→10にするライブラリ化

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

 

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

 

◇3.ライブラリを使って「経路検索」

【処理内容】
・経路検索
ライブラリ使用: 3~4行
ライブラリ不使用:60~80行

経路検索:経由地あり(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地あり
const array = ["新宿", "恵比寿"];                     //Waypoints...
map.direction("#direction", "walking", "御茶ノ水", "表参道", array);  //walking or driving

SnapCrab_NoName_2019-2-26_8-57-33_No-00.png

 

経路検索:経由地なし(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地なし
const array = [];
map.direction("#direction", "walking", "御茶ノ水", "表参道, array ); //walking or driving

SnapCrab_NoName_2019-2-26_9-2-54_No-00.png

 
  

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。

本を(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『 Map API 』学習コスト100→10にするライブラリを作った

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

 

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

 

◇3.ライブラリを使って「経路検索」

【処理内容】
・経路検索
ライブラリ使用: 3~4行
ライブラリ不使用:60~80行

経路検索:経由地あり(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地あり
const array = ["新宿", "恵比寿"];                     //Waypoints...
map.direction("#direction", "walking", "御茶ノ水", "表参道", array);  //walking or driving

SnapCrab_NoName_2019-2-26_8-57-33_No-00.png

 

経路検索:経由地なし(最短で3~4行)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);

//経由地なし
const array = [];
map.direction("#direction", "walking", "御茶ノ水", "表参道, array ); //walking or driving

SnapCrab_NoName_2019-2-26_9-2-54_No-00.png

 
  

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。

本を(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『MapAPI』学習コストを減らすライブラリを作ってみた!

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

再度以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『MapAPI』の学習コストを超低くするライブラリ作成(解説本ダウンロードあり)

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webサイト『Map API』学習コストを超低くするライブラリBmapQuery.js (解説本ダウンロード付き)

MapAPI の選択

Note記事: Google一択「WebサイトのMap」に一石を投じる!

こちらは、先日「 Note 」に書きましたので、良ければ見てください。
以下につながる話でもあります。

学習コストを減らしたライブラリと通常コードの比較

今回作成した「BmapQuery.js」はサンプルサイトでの動作確認や、Githubでのライブラリダウンロードが可能です。

  • サンプルサイト: BmapQuery.js
    ※沢山のサンプルコードがあるので是非試してください。

  • ライブラリダウンロード: Github
    ※Readmeにも基本サンプルコードを載せています。

◇1.シンプルな処理で比較

【処理内容】
・MAP表示
・MAPにPINを立てる
・MAPにINFOBOXを立てる

「ライブラリ無し」MapAPIを利用して書いたコード
    //Map表示
    const map = new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(47.6149, -122.1941),
        zoom: 15
    });
    //Get MAP Infomation
    let center = map.getCenter();

    //PushPin
    let pin = new Microsoft.Maps.Pushpin(center);
    pin.metadata = {
         color: "#ff0000"
    };
    map.entities.push(pin); //Add Pushpin to Map

    //infobox
    let infobox = new Microsoft.Maps.Infobox(center, {
        title: 'title',
        description: 'description'
    });
    infobox.setMap(map); //Add infobox to Map

「ライブラリ有り」MapAPIを利用して書いたコード
//0. Map初期化
const map = new Bmap("#myMap");

//1. Map表示
map.startMap(47.6149, -122.1941, "load", 10);

//2.PushPinを立てる
let pin = map.pin(47.6149, -122.1941, "#ff0000");

//3.テキストボックスをMapに立てる
map.infobox(47.6149, -122.1941, "Title", "Description");

どちらも、このような結果で表示されます。
picture_pc_a2a87a921cfda8759fdda566f8412670.png

◇2.範囲円を作成するコードで比較

【処理内容】
・範囲円を描く

「ライブラリ無し」MapAPIを利用して書いたコード(1つ作成のコード)
//Map表示
map = new Microsoft.Maps.Map('#myMap', {
    center: new Microsoft.Maps.Location(47.6149, -122.1941),
    zoom: 12
});
//Circle設定
const style = {
    pinColor:"#0000ff",
    fillColor:"rgba(0,0,100,0.4)",
    strokeWidth:10
};
//Circle表示
const lat =47.6149;
const lon = -122.1941;
const meter = 3000;
//Load the spatial math module
Microsoft.Maps.loadModule("Microsoft.Maps.SpatialMath", function () {
    //Request the user's location
    const loc = new Microsoft.Maps.Location(lat, lon);
    //Create an accuracy circle
    const path = Microsoft.Maps.SpatialMath.getRegularPolygon(loc, meter, 36, Microsoft.Maps.SpatialMath.Meters);
    const poly = new Microsoft.Maps.Polygon(path,{
        fillColor: style.fillColor,
        strokeThickness: style.strokeWidth
    });
    map.entities.push(poly);
    //Event:add [click,mousedown,mouseout,mouseover,mouseup]
    if((event==="click" || event==="mousedown" || event==="mouseout" || event==="mouseover" || event==="mouseup") && typeof callback==="function"){
        Microsoft.Maps.Events.addHandler(poly, event, callback);
    }
    //Add a pushpin at the user's location.
    const pin = new Microsoft.Maps.Pushpin(loc,{
        color: style.pinColor
    });
    map.entities.push(pin);
});

※3つ作成のサンプルは少し長くなるので省略(下部のライブラリでは3つ作成しています)

「ライブラリ有り」MapAPIを利用して書いたコード(3つ作成)
//Map初期化
const map = new Bmap("#myMap");
map.startMap(47.6149, -122.1941, "load", 13);
//MapCircle設定
const style = {
      pinColor:"#0000ff",
      fillColor:"rgba(0,0,100,0.4)",
      strokeWidth:10
};
//以下3つのCircleを作成
map.circleSet(47.6200, -122.1100, 2000, style); //2000=2Km
map.circleSet(47.6000, -122.1599, 3000, style); //3000=3km
map.circleSet(47.6149, -122.1941, 1000, style); //1000=1km

ライブラリでは「3つ作成」ではこのような結果で表示されます。
SnapCrab_NoName_2019-2-26_4-31-26_No-00.png

再掲、以下サイトから動作確認&ライブラリダウンロード可能です

  • サンプルサイト: BmapQuery.js

  • ライブラリダウンロード: Github
    沢山のサンプルコードがあるので是非試してください。
    DyvstEWUwAEHbZn.jpg

今回はドキュメント(PDF)を作成しました。

無料でダウンロードできるので、よければどうぞ!

本のダウンロード : BmapQuery.js

※注意)infobox_iframe.htmlの箇所だけGithubのコード&Readmeが最新です。

今後は、

Mapはピンポイントで使われるケースが多いと思いますので、ニッチに必須のライブラリになるよう使われればと思います。

最後に

こんなにニッチな事によく頑張ったな~と思っていただけたら、
今後も応援していただければ嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『Google Apps Script 完全入門』を買って基礎入門①

今回はタイトル通り、
GASの記述ルールやお作法、変数、定数、型、配列や演算子など様々な基本を複数回に分けて書いていきます!

以下様々なGASの記事を紹介してます!
https://bzbot.work/

紹介記事

今回紹介している記事は以下です!
https://bzbot.work/2019/02/25/gas-superbeginner/

1.GASの超基本

GASを利用するにあたり、最低限覚えておいたほうがいい使用上のルールがあります。

スクリプト実行時間

無料のGoogleアカウントの実行時間は6分 / 実行で、スクリプトの実行の際にこの制限を越えると、スクリプトはエラーとなって終了しちゃいます。
なので扱うデータ量が多かったり、処理速度を意識しないといけません!(笑)

ただ、6分の壁を越える処理を記述する方法もあるようなので、今後やってみたいなぁーと思ってます。

記述のルール

1.英数字、記号は全て半角で入力
2.アルファベットの大文字と小文字は区別される
3.初めて実行するスクリプトは都度『承認』が必要
4.ステートメント *1 の末尾にはセミコロン(;)を付ける
5.識別子 *2 は先頭文字は数字、一部アンダースコア、ドル記号($)をのぞいて記号は使えない
6.予約語 *3 は使えない
7.変数と関数名にはキャメル記法 *4、定数名にはスネーク記法 *5を使用

*1 ステートメント…処理の最小単位の事
セミコロンがなくても自動でステートメントを判断して処理されるけど、絶対ではないので非推奨です!
*2 識別子…変数、定数、関数などの事
*3 予約語…すでに特別な意味を持つ単語として定められているものの事(var や function など)
*4 キャメル記法…単語を連結した時に、2つ目以降の単語の頭文字を大文字にする記法(maxRow など)
*5 スネーク記法…単語をアンダースコア(_)で連結しつつ全てを大文字にする記法(TAX_RATE など)

2.記述準備

エディタ表示方法

『ツール』の中にある『スクリプト エディタ』を選択します。
image.png

コードの記述場所

image.png

3.変数と定数

変数

スクリプト上で実行する為に必要な数値、文字列、オブジェクトなどのデータを格納する『データの箱』のことです。変数を使うことで、データを一時的に保管したり、データをわかりやすい名称で取り扱うことができます。

例えば以下が変数です。

GAS
function myFunction() {
/*
*変数の値は基本上書きが可能
*/

//numという変数に『12345』という数値が入ってます
var num = 12345;
Logger.log(num);

//strという変数に『Hello ビジボット』という文字が入ってます
var str = 'Hello ビジボット';
Logger.log(str);

//numに1という値を上書きする
num = 1;
Logger.log(num);
}

ログ結果はこんな感じ。

[19-02-25 01:47:46:598 JST] 12345.0
[19-02-25 01:47:46:598 JST] Hello ビジボット
[19-02-25 01:47:46:599 JST] 1.0

定数

変数は上書きが可能でしたが、上書きによる変更をさせたくない時があります。(例えば消費税とか)
そのような場合には『定数』を使います。定数は変数同様、名前を付けられる『データの箱』として使用できますが、一度値を格納したら値の上書きをすることができません。

例えば以下が定数です。

GAS
function myFunction() {
/*
*定数の値は上書きが不可能
*/

//TAXという定数に『1.08』という数値が入ってます
const TAX = 1.08;
Logger.log(TAX);

//SITE_NAMEという定数に『ビジボット』という文字が入ってます
const SITE_NAME = 'ビジボット';
Logger.log(SITE_NAME);

//TAXに1.10という値を上書きする記述をしてみる...
TAX = 1.10;
Logger.log(TAX);
}

ログはこんな感じ。

[19-02-25 01:54:22:985 JST] 1.08
[19-02-25 01:54:22:986 JST] ビジボット
[19-02-25 01:54:22:986 JST] 1.08

他にも結果は以下サイトで載せてます!
https://bzbot.work

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

僕の考えた最強のService Workerキャッシュ戦略で爆速サービスを作った

はじめに

聖地の写真を共有するサービス「Holy Place Photo」にService Workerによるキャッシュを実装しました。

そのためネットワークがオフラインでも下記のようにサクサク動きます!!!!

また、LighthouseのPWAのスコアは100を取れました。

スクリーンショット 2019-02-25 22.10.58.png

この記事ではService Workerを利用したキャッシュの設計、Laravel + Vue.jsのWebアプリケーションでの実装を解説していきたいと思います。

注意書き

  • 僕の考えた最強のService Workerのキャッシュの設計のため唯一の正解ではありません
  • キャッシュの設計はサービスによって違うと思うのでこの記事は一つの参考にしてください

Service Worker

まずService Workerについて簡単に解説します。

※今回はスコープについてはあまり説明しません

Service Workerとは

Service WorkerはWebページのバックグラウンドで動くスクリプトです。

オフライン対応・バックグラウンド同期・プッシュ通知などの機能を持ちます。

Progressive Web Appとセットでよく聞くと思います。

ここで注意してほしいのはService WorkerはリクエストにaddEventListenerを貼ることができるだけで、キャッシュする機能はService Workerには含まれていないという点です(キャッシュについてはCache Apiの項目で詳しく説明します)

詳しくはこちら。

Service Worker の紹介 | Web Fundamentals | Google Developers

Service Worlerのライフサイクル

Service Workerはウェブページとは異なるライフサイクルで動作します。

スクリーンショット 2019-02-25 22.40.49.png

Service Workerの登録(Install)

Serivce Workerを登録するためにはnavigator.serviceWorker.registerを利用します。

app.js
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js').then(() => {
      console.log('登録成功');
    },() => {
      console.log('登録失敗');
    });
  });
}
sw.js
self.addEventListener('install', (event) => {
  console.log('インストール');
});

登録が成功するとinstallが実行されます。

このinstallは一度だけ発生します。

installは静的なアセットをキャシュするのによく使われます。

Service Workerによる制御(Activate)

installが成功、またはすでにinstallが成功しているページを表示するとactivateが実行されます。

installが成功 = 初回のアクセス時
installが成功しているページを表示する = 2回目以降のアクセス時

activateは古いキャッシュを削除したりするのによく使われます。

activateが完了するとService Worker はそのスコープ内のすべてのページを制御します。

た だ し !

Service Workerを登録時点では(初回のアクセス時)制御されず、次に読み込まれた際に制御されるようになります。

初回にService Workerの制御が始まらない理由は「Service Worker 登録」に記載されています。

新しい Service Worker スレッドを開始してリソースのダウンロードとキャッシュをバックグラウンドで実行すると、ユーザーがはじめてサイトにアクセスしたときに迅速なインタラクティブ エクスペリエンスを提供するという目標に逆行することになります。

初回のアクセスの際はブラウザはバックグラウンドでスクリプトを実行している場合ではないぞ、と書かれています(個人的解釈)

初回アクセス時にService Workerの制御を開始させる

実はactivate時にclients.claim()を実行すると、強制的にService Workerの制御を開始できます。

sw.js
self.addEventListener('activate', (event) => {
  event.waitUntil(self.clients.claim());
});

Service Workerの更新

Service Workerが更新されていると判断される条件は、1ByteでもService Workerのスクリプトに変化があった際です。

更新を検知すると新しいService Workerは待機状態になります。

待機状態から新しいService Workerの制御を開始するためには、すべてのタブを閉じるか、現在開いているページから別のページに移動する必要があります(ページの更新・リロードするだけでは制御は開始されません)

そのため、新しいService Workerの制御を開始させるためには1step必要になります。

Service Workerの更新時に即座に制御を開始させる

install時にskipWaiting()を実行すると、新しいService Workerの制御を即座に開始させられます。

sw.js
self.addEventListener('install', (event) => {
   event.waitUntil(self.skipWaiting());
});

Service Workerによるオフライン対応

なぜ、Service Workerを導入するとオフライン対応が可能になるのでしょうか?

それはService Workerはネットワークへのアクセスを捕まえることができるためです。

Service Workerが制御している状態で、ネットワークへのアクセス(ページ遷移、リソースの取得など)が発生すると、fetchイベントが発火します。

sw.js
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then((response) => {
      if (response) {
        return response;
      }
      return fetch(event.request);
    })
  );
});

Service Workerはこのfetchイベントに対してaddEventListenerを貼ることができます。

上記例ではキャッシュにあったらキャッシュから返して、なかったらfetchを実行してネットワークへアクセスし取得します。

このようにfetch内でキャッシュから返すことができるため、あらかじめ全てのリソース(HTML,CSS,JS,IMGなど)をキャッシュしていれば、オフライン状態でもWebページが見れるようになります。

Cache API

次にCache APIについて解説します。

2度目になりますが、Cache APIはService Workerの機能ではありません。

キャッシュは削除されない限り有効期限切れにはなりません。

キャッシュはcaches.open(CACHE_NAME)を実行しキャッシュオブジェクトを取得して利用します。

詳しくはこちら。

https://developer.mozilla.org/ja/docs/Web/API/Cache

キャッシュの登録

キャッシュへの登録はadd,addAll,putがあります。

const CACHE_NAME = 'v1';

caches.open(CACHE_NAME).then((cache) => {
  return cache.add('/hoge.png');
});

caches.open(CACHE_NAME).then((cache) => {
  return cache.addAll([
    '/fuga.png',
    '/piyo.png'
  ]);
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.open(CACHE_NAME).then((cache) => {
      return cache.match(event.request).then((response) => {
        return response || fetch(event.request).then((response) => {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

addはURLを受け取り、ネットワークへアクセスして取得後、レスポンスオブジェクトをキャッシュに追加します。

addAllは配列を受け取り、ネットワークへアクセスして取得後、レスポンスオブジェクトをキャッシュに追加します。

putは取得済みのレスポンスオブジェクトをキャッシュに格納します。

addfetch + putのイメージです。

上記例ではService Workerのfetch内で、キャッシュから取得できなかった場合、fetchして、
レスポンスオブジェクトをputを利用しキャッシュに追加しています。

キャッシュの削除

削除はdeleteを利用します。

caches.open(cacheName).then((cache) => {
  cache.delete('hoge.png');
});

キャッシュの利用

追加のところで出ていますがmatchを利用します。

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.open(CACHE_NAME).then((cache) => {
      return cache.match(event.request).then((response) => {
        return response || fetch(event.request).then((response) => {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

matchdeleteにはオプションが利用できます。

  • ignoreSearch: trueを指定するとクエリストリングを無視するようになります
  • ignoreMethod: trueを指定するとGET,HEAD以外のMETHODが利用できます

僕の考えた最強のService Workerキャッシュ戦略

ということで僕の考えた最強のService Workerキャッシュ戦略を解説していきたいと思います。

今回のキャッシュ戦略のポイントは下記になります。

  • 次のページに遷移する際に必要なリソースは全てキャッシュから返す
    • HTMLの有効期限は1日にする
    • アセット(CSS,JS)は無期限
    • ただしサードパーティのリソースは除く
  • 初回のユーザーもService Workerの制御下に置く

1つずつ解説していきたいと思います。

次のページに遷移する際に必要なリソースは全てキャッシュから返す

次のページで必要なリソースは主に動的なHTMLと、静的なアセット(CSS,JS)とサードパーティのリソースに分類されます。

動的なHTMLは有効期限を1日にして、静的なアセット(CSS,JS)は無期限キャッシュするようにします。

より頻繁に更新されるようなサイトでは、HTMLの有効期限はより短くていいかもしれません。

動的なHTMLのキャッシュ

document.querySelectorAll('.js-sw-fetch').forEach((e) => {
  const url = e.getAttribute('href')
  caches.open(cacheName).then((cache) => {
    cache.match(url).then((response) => {
      if (!response) {
        cache.add(url);
        localStorage.setItem(url, Date.now());
      } else {
        const time = localStorage.getItem(url);
        if (!time || Date.now() - time > 60 * 60 * 24 * 1000) {
          cache.delete(url).then(() => {
            cache.add(url);
            localStorage.setItem(url, Date.now());
          });
        }
      }
    });
  });
});

画面内にあるリンクをDOMから引っこ抜いて、Cache APIを使ってキャッシュに登録します。

キャッシュにない場合はaddを利用して保存し、ローカルストレージに遷移するURLをkeyにしてタイムスタンプを保存します。

キャッシュにある場合は、有効期限が切れていたらdeleteを利用してキャッシュを削除して、addを利用しキャッシュに保存します。

静的なアセット(CSS,JS)

今回FWにLaravelを採用しており、フロントのビルドにLaravel Mixを利用しています。

アセットのバージョン管理にはLaravel Mixのmix.version()を利用しています。

そのためビルドされるファイルにはid=12345といったクエリパラメーターが付与されます。

これはmix-manifest.jsonで管理されており、bladeで利用するmix()はこのmix-manifest.jsonを見ています。

{
    "/js/app.js": "/js/app.js?id=27081b345ad90ec7716a",
    "/css/app.css": "/css/app.css?id=ebe23bcc66ba35ecfe6c"
}

画面表示時に必要なアセットをコントローラーからviewに埋め込み、JSで引っこ抜いてキャッシュに登録させます。

<?php

namespace App\Http\Controllers;

class Controller extends Controller
{

    /**
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function index()
    {
        $manifests = json_decode(file_get_contents(public_path('/mix-manifest.json')), true);
        // swもビルドされているため、除外
        $files = array_filter($manifests, function($key) {
            return $key !== '/sw.js';
        }, ARRAY_FILTER_USE_KEY);
        $swCacheList = json_encode(array_values($files));
        return view('index', compact('swCacheList');
    }
}
<div id="sw" data-sw-cache-list="{{$swCacheList}}"></div>
JSON.parse(document.getElementById('wrapper').dataset.swCacheList).forEach((url) => {
  caches.open(cacheName).then((cache) => {
    cache.match(url).then((response) => {
      if (!response) {
        cache.delete(url.split('?')[0], {ignoreSearch: true}).then(() => {
          cache.add(url);
        });
      }
    });
  });
});

cache.delete(url.split('?')[0], {ignoreSearch: true})により、URLパラメーターが違う同じファイルのキャッシュを削除することで、無期限にキャッシュしているファイルをキャッシュから削除しています。

管理しきれる間は上記方法でいいと思いますが、管理しきれなくなってきた場合は、HTMLをキャッシュする際に、HTMLをパースしてJSとCSSのURLを取得してキャッシュするという動的な方法が良いかもしれません。

初回のユーザーもService Workerの制御下に置く

上記の解説の通りService Workerは通常初回アクセスのユーザーは制御下におきません。

今回は初回のユーザーも制御下に置くために、activate時にclients.claim()を実行します。

また、Service Workerの更新時も初回から更新したService Workerの制御下に置くために、install時にskipWaiting()を実行します。

Service Workerの制御の開始を検知する

install後の制御の開始や、更新後の制御の開始はcontrollerchangeイベントが発火します。

そのため、Service Workerの制御中に何か処理をしたい場合は下記のように書くことで実現できます。

  const controllerChange = new Promise((resolve) => {
    navigator.serviceWorker.addEventListener('controllerchange', resolve);
  });
  navigator.serviceWorker.register('/sw.js').then(() => {
    return navigator.serviceWorker.ready;
  }).then(() => {
    if (navigator.serviceWorker.controller) {
      // 更新時
      return navigator.serviceWorker.controller;
    }
    // 初回
    return controllerChange;
  }).then(() => {
    // Service Workerの制御下
  });

おわりに

サクサクなのは本当に気持ちよく、やってやった感が高かったです。

作った後に、quicklinkという、Intersection ObserverrequestIdleCallbacknavigator.connection.effectiveTypeprefetch使って、リンクを高速に先読みするライブラリを知りました・・・。

最強のService Workerキャッシュ戦略は最強(改)にできそうです・ω・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む