TSM - Aplicații mobile folosind Vue și Capacitorjs

Ovidiu Mățan - Fondator @ Today Software Magazine


Tuturor ne plac website-urile care își adaptează elementele în funcție de dimensiunea ecranului device-ul pe care rulează. Un pas înainte pentru eficientizarea acestora poate consta în a oferi utilizatorilor o aplicație mobile. Aceasta are avantajul de a fi la un click distanță pe telefon vs. adresa URL a website-ului. De asemenea, prin intermediul ei se oferă accesul la senzorii telefonului cum ar fi poziția GPS, camera photo, accelerometrul sau notificările. Rezultă, prin urmare, posibilitatea publicării unor aplicații mai complexe și mai bine integrate în viața utilizatorilor noștri.

Fie că ești la început de drum sau un developer front-end cu experiență, articolul de față îți va arăta în câțiva pași simpli cum se pot dezvolta aplicații mobile folosind JavaScript. Vom dezvolta pas cu pas o aplicație Vue.js care va rula atât în browser ca un SPA (Single Page Application) dar și pe device-urile Android. Același cod va putea rula și pe device-urile iOS, dar aceasta într-un articol viitor.

Aplicația demo va afișa pe hartă poziția noastră și un cerc al ariei din jurul nostru. Se vor putea modifica atât poziția de pe hartă cât și dimensiunea ariei.

Un click pe markerul poziției selectate va afișa coordonatele acestuia.

Configurarea proiectului

Componenta Web

Începem prin instalarea Vue Cli folosind toolul npm

npm install -g @vue/cli @vue/cli-service-global

B. Generăm un proiect simplu

vue create map_demo

Vom fi întrebați în legătură cu versiunea Vue folosită, pe care o alegem ultima: 3

Rulăm proiectul generat:

cd map_demo
npm run serve

Componenta mobile

Vom folosi soluția CapacitorJS pentru Vue

Începem prin instalarea librăriei

npm install @capacitor/core @capacitor/cli

Integrăm librăria în proiectul nostru Vue astfel:

npx cap init --web-dir=dist

Vom fi întrebați care este numele aplicației (map_demo) și package ID-ul (org.map_demo)

Pasul următor este să instalăm Android Studio. Vom seta următoarele proprietăți pentru sistem (Windows):

ANDROID_SDK_ROOT = AppDataLocalAndroidSdk)
JAVA_HOME = AndroidAndroid Studiojre

Instalăm suportul nativ pentru Android:

npm i @capacitor/android
npx cap add android

Continuăm prin instalarea unui device virtual în Android Studio: Tools -> AVD Manager.

Acum vom putea rula aplicația noastră în emulatorul Android:

npm run build
npx cap sync
npx cap run

În cazul în care emulatorul nu este găsit va trebui să rulați prima oară aplicația din Android Studio.

npx cap open

urmat de Run -> Run 'app'

Codul sursă

<template>
  <div >
    <p>Set the area size</p>
    <vue-slider
        v-model=”circleSize”
        :min=”10000”
        :max=”100000”
        :interval=”10000”
    >

    </vue-slider>
    <p>{{error}}</p>
    <div style=”width: 100%; height: 300px; 
                text-align: center”>
      <div style=”margin: 0 auto”>
      <GMapMap
          :center=”center”
          :zoom=”7”
          map-type-id=”terrain”
          style=”width: 100vw; height: 900px”
          ref=”myMapRef”
          :click=”true”
          @click=”updateCoord”
      >
        <GMapCircle
            :radius=”circleSize”
            :center=”{ lat: lat, lng: long}”
            :options=”circleOptions”
        />
        <GMapCluster>
          <GMapMarker
              @click=”openInfoWindow()”
              :key=”index”
              v-for=”(m, index) in markers”
              :position=”targetPos(m.position)”
              :icon=’{

            url:”/3402462.png”,
                scaledSize:{width:30, height:30},
                 labelOrigin: {x: 160, y: -100}
              }’

          >
            <GMapInfoWindow
            :opened=”info”
            >

     <div>Your current position <br/> Lat: {{lat}}
      <br/>Long: {{long}}<br/>Radius: {{circleSize}}
              </div>
            </GMapInfoWindow>
          </GMapMarker>
        </GMapCluster>
      </GMapMap>
      </div>
    </div>

  </div>
</template>

<script>
import {Geolocation} from ‚@capacitor/geolocation’
import ‚vue-slider-component/theme/antd.css’
import VueSlider from ‚vue-slider-component’

export default {
  components: {
    VueSlider
  },
  name: ‚HelloWorld’,
  props:[‚msg’],
  data() {
    return {
      circleSize:20000,
      initLat: 55.093048,
      initLong: 20.842120,
      lat: 0,
      long: 0,
      error:””,
      info:false,
      circleOptions: {
        strokeColor: „#FF0000”,
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: „#FF0000”,
        fillOpacity: 0.35,
      },
    }
  },
  async mounted(){
    await this.getPos();
    this.lat=this.initLat;
    this.long=this.initLong;

  },
  computed:{
    center(){

      return {lat: this.initLat, lng: this.initLong}
 },
    markers(){
      return [
        {
          position: {
            lat: this.lat, lng: this.long
          },
        },]
    }
  },
  methods:{
    async getPos (){
      let pos=null;
      try {
        pos = await Geolocation.getCurrentPosition();
        console.log(pos)
        if (pos) {
          this.initLat = pos.coords.latitude;
          this.initLong = pos.coords.longitude;
        }
        return pos;
      }catch (e){
        this.error=e;
      }
      return pos;
    },
    updateCoord(event){
      this.lat=event.latLng.lat();
      this.long=event.latLng.lng();
    },
    openInfoWindow(event){
      this.info=!this.info;
      console.log(„info=”,event)
    },
    targetPos(position){
      let tempPos={
        lat:position.lat-0.1139,
        lng:position.lng+0.003
      }
      return tempPos;
    }
  }
}
</script>

Pentru a rula codul de mai sus, vom suprascrie codul default din src/components/HelloWorld.vue din proiectul nostru. Înainte de a îl rula va trebui să instalăm câteva noi librării:

Vue Slider

<vue-slider  
v-model=”circleSize”  
:min=”10000”  
:max=”100000”  
:interval=”10000”></vue-slider>

Reprezintă sliderul prin care setăm dimensiunea ariei circulare. Va trebui să instalăm versiunea compatibilă cu Vue 3:

npm install vue-slider-component@next -save

Modelul circleSize este folosit direct pentru ajustarea real time a proprietății radius a componentei GMapCircle.

Vue 3 Google maps

Instalare: npm install -S @fawmi/vue-google-maps

Reprezintă un container Vue 3 pentru afișarea hărților de la Google. Este componenta noastră principală, iar pentru a o putea folosi va trebui să obțineți cheia API.

Odată obținută va trebui să o adăugați în proiect, în main.js:

import { createApp } from 'vue'
import App from './App.vue'
import VueGoogleMaps from '@fawmi/vue-google-maps'

const app = createApp(App);

app.use(VueGoogleMaps, { 
load: {
     key: 'AIzaSyC31Wzs1MSYtKfBPtweNMqJmajhlzPbvCA',
    },
}).mount('#app')

Capacitor Geolocation

Instalare: npm install @capacitor/geolocation

Este o componentă necesară pentru obținerea poziției curente. Utilizatorul va fi întrebat pentru acordarea drepturilor de citire a poziției.

Folosirea acestuia este simplă. Primim coordonatele longitudinale și latitudinale astfel:

pos = await Geolocation.getCurrentPosition();

Va trebui să acordăm și drepturile de folosire ale acestora în configurația specifică Androidului: app/src/androidTest/main/AndroidManifest.xml

 <!-- Permissions -->
<uses-permission android:name=
”android.permission.ACCESS_BACKGROUND_LOCATION” />
<uses-permission android:name=
”android.permission.ACCESS_COARSE_LOCATION” />
<uses-permission android:name=
”android.permission.ACCESS_FINE_LOCATION” />
<uses-feature android:name=
”android.hardware.location.gps” />
<uses-permission android:name=
”android.permission.READ_EXTERNAL_STORAGE”/>
<uses-permission android:name=
”android.permission.WRITE_EXTERNAL_STORAGE” />

Imagine target

Descărcăm https://www.iconfinder.com/icons/2939620/cross_minicons_small_target_icon și salvăm fișierul 3402462.png în directorul /public.

Rularea aplicației

Putem acum rula aplicația fie cu emulatorul Android:

npm run build
npx cap sync
npx cap run

sau ca o componentă web

npm run build
npm run serve

Concluzie

Deși poate părea complicat din perspectiva dependințelor, codul sursă este simplu, oferindu-ne rapid o aplicație responsive. De asemenea, nu este necesar să fim foarte familiarizați cu mediul de dezvoltare android. Un alt avantaj al CapacitorJS este ușurința prin care putem transforma un SPA în aplicație mobile. Sper că v-am făcut curioși cu privire la beneficiile aplicării Vue și Capacitorjs. Dacă realizați o aplicație interesantă, ne puteți trimite un e-mail pe adresa redacției.