Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

HGマップについて

最近フロントエンドの学習をゆっくり進めています。Vue を理解した後、TypeScript の学習を始めました。新しいことを学ぶたびに、自分が興味のあるものを作りたくなり、こうするのがとても Coooooooooooool だと思っています!👊

以前、偶然に吉珠の地図を見かけて、非常に優れていると感じました。たまたま私たちの学校には関連する製品がなく、ただ描かれた画像の地図しかありませんでした。少し考えた結果、

  • 携帯性を考慮して、モバイル端末で使用することに決めました。
  • 学校の施設の場所を示す必要があります。
  • シャトルバスのルートと乗降場所。
  • 製品の紹介と学校の紹介が必要です。
  • 学校の実景が見えると良いです。

以前に Vue を学んだこともあり、Vue を使って書くことに決めました。やると決めたらすぐに行動!✈️

そして、初日はプロジェクトの作成でつまずきました。

最初にインストールした Vue のバージョンは 2.x で、新しいプロジェクトの webpack バージョンは 3.6 でした。TypeScript を使用する際に webpack を 4.x バージョンにアップグレードする必要があると表示されました。最初はあまり考えず、表示された問題を Google で検索して解決策を探しました(検索エンジンに頼るプログラミング)。ざっと見たところ、古い依存関係をアンインストールして新しい依存関係をインストールし、設定を変更するという内容が多かったですが、彼らのチュートリアルは基本的に異なり、唯一共通していたのはどれも非常に複雑で、どう選べばいいのかわからず、見た目が良さそうなものを選んで書き始めた結果、失敗しました…… その後、Vue3.x バージョンからは TypeScript に対応し始めており、プロジェクト作成時に TypeScript を使用するかどうかを選択でき、自動的に設定されることがわかりました…… ああ、これ。

古いバージョンの Vue をアンインストール!

npm uninstall vue-cli -g

最新バージョンの Vue をインストール!

npm install -g @vue/cli

もう一度やってみて、出発!✈️

プロジェクトのアドレス:HgMap
地図のリンク:華広地図

環境依存#

  • vue/cli 4.4.6
  • typescript
  • element-ui:UI コンポーネント
  • vue-class-component:クラスデコレーター
  • vue-property-decorator:vue-class-component を基にした拡張
  • vue2-svg-icon:SVG アイコンコンポーネント
  • 地図リソースは高徳地図 API から取得

注:vue-cli 4 バージョンには vue.config.js が自動で付属しないため、ルートディレクトリに自分で作成して設定する必要があります。そうしないと、プロジェクトのパッケージング時に静的リソースが見つからなくなります。

Vue と TypeScript の使用#

前提#

script タグに : lang=“ts” を追加

<script lang="ts">
   ···
</script>

コンポーネントの作成#

import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

@Component
export default class Test extends Vue {

}

コンポーネントのインポート#

import Mapmenu from '@/components/Mapmenu.vue'

@Component({
 components: {
   Mapmenu
 }
})

data オブジェクト#

boolean や string などの単純な型は TypeScript が自動で認識するため、型を明示する必要はありません。そうしないと、実行時にエラーが出ます……

import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

export default class Map extends Vue {
 map: any = null
 dialog = false
 name = "MAGREN"
}

method メソッド#

カンマで区切る必要はなく、export default 内に直接書き、戻り値の型を明示する必要があります。

<script lang="ts">
import { Component,Vue,Prop,Emit } from 'vue-property-decorator';
import markers from '@/config/markers.ts'

@Component
export default class Mapmenu extends Vue {
 
 show = true
 // メソッド
 // 学校紹介
 toPageSchoolInfo(): void{
   this.$router.push({
     path:'/schoolinfo'
  })
}
 
 ………………
}

Prop および Emit を使用した親子コンポーネント間のパラメータ伝達#

親コンポーネント

= 'map’は親コンポーネントの map パラメータを子コンポーネントに渡し、map という名前を付けます。
@show-dialog=“handleChildValue” は子コンポーネントから送られた値を handleChildValue メソッドで処理します。

<template>
<Mapmenu :map='map' @show-dialog="handleChildValue"></Mapmenu>
</template>

<script lang="ts">
// @は/srcへのエイリアスです
import AMap from '@/config/amap.ts'
import Mapmenu from '@/components/Mapmenu.vue'
import { Component,Vue } from 'vue-property-decorator';

@Component({
 components: {
   Mapmenu
 }
})

export default class Map extends Vue {
  dialog = false 
  ……
   
  private handleChildValue(val: boolean) {
       // val: 子コンポーネントから送られた値
     this.dialog = val;
    }
}
子コンポーネント

親コンポーネントから渡されたパラメータは this.xxx で直接使用します。
親コンポーネントにパラメータを渡すには、@Emit デコレーター内のメソッドを呼び出します。

<script lang="ts">
// PropとEmitをインポート
import { Component,Vue,Prop,Emit } from 'vue-property-decorator'; 
import markers from '@/config/markers.ts'

@Component
export default class Mapmenu extends Vue {
 
 show = true

 // 親コンポーネントから送られた値を受け取る
 @Prop()
 private map: any

 // 親コンポーネントに値を送る
 @Emit()
 private showDialog(){
   return this.show
}
}

高徳地図の読み込みと使用#

高徳地図の読み込み#

地図をラップし、Promise を通じて非同期で読み込みます。TypeScript はコンパイル時に window 型をチェックし、直接 window.xx を呼び出すことを許可しません。any 型に変更すれば使用できます。読み込む前に、すでに存在するかどうかを確認します。

export default function MapLoader(): Promise<void>{
 return new Promise((resolve, reject) => {
   const win: any = window  
   if (win.AMap) {
     resolve(win.AMap)
  } else {
     const url='高徳地図api'
     const script: HTMLScriptElement = document.createElement('script')
     script.charset = 'utf-8'
     script.src = url
     script.onerror = reject
     document.head.appendChild(script)
  }
   win.onLoad = () => {
     resolve(win.AMap)
  }
})
}

必要な場所で呼び出します。

<template>
 <div id="map">
   <div id="container">
    
   </div>
 </div>
</template>

<script lang="ts">
import AMap from '@/config/amap.ts'
import { Component,Vue } from 'vue-property-decorator';

export default class Map extends Vue {
 map: any = null

 // 地図を初期化
 async initAMap(): Promise<void> {
  try {
   const res: any = await AMap();
   this.map = new res.Map("container", {  // idがcontainerのdivに装載
     viewMode:'3D', // 地図モード、モバイルでは2D効果のみ
     resizeEnable: true, // 地図コンテナのサイズ変化を監視するか
     zoom: 17, // 地図の初期レベル
     center: [113.172847,23.43399], // 地図の初期中心点
     pitch:40, // 地図の俯瞰角度、有効範囲は0度-83度
     buildingAnimation:true, // 3D地図表示アニメーション
    });
    this.personOptions(this.map,true)
  }catch (err) {
     console.error(err);
  } 
}

 mounted() {
    this.initAMap();
}
}
</script>

地図にマーカーを追加#

const win: any = window
const marker = new win.AMap.Marker({
         position: new win.AMap.LngLat(113.171688,23.433279),  // マーカーの座標 
})

マーカーの上にテキストを追加:

marker.setLabel({ // labelはデフォルトで青い枠と白い背景で左上に表示される
         offset: new win.AMap.Pixel(0, -3),  // テキストラベルのオフセットを設定
         content:"商業街", // テキストラベルの内容を設定
         direction: 'top' // テキストラベルの方向を設定
}); 

スタイルを変更:
この時、css タグに scoped を付けてはいけません。そうしないと効果がありません。この問題は css のスコープに関わります。

.amap-marker-label{ 
 padding: 5px;
 border-radius: 3px;
 border-color: ##54B7E7;
 border-width: 0px;
 color:##54B7E7;
}

最後に add メソッドを呼び出して追加します:

this.map.add(marker)
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。