Diferència entre revisions de la pàgina «Mòduls amb Javascript»

De wikijoan
Salta a la navegació Salta a la cerca
 
(Hi ha 7 revisions intermèdies del mateix usuari que no es mostren)
Línia 18: Línia 18:
 
Trobem els ''exports'' en els scripts de la carpeta ''modules/'': ''canvas.js'' i ''square.js''. Les funcions definides en aquests mòduls s'importen en el ''main.js'', que és el fitxer principal de Javascript. El ''index.html'' és el punt d'entrada de la web/html, i fa referència al ''main.js'' com has fet moltes vegades.
 
Trobem els ''exports'' en els scripts de la carpeta ''modules/'': ''canvas.js'' i ''square.js''. Les funcions definides en aquests mòduls s'importen en el ''main.js'', que és el fitxer principal de Javascript. El ''index.html'' és el punt d'entrada de la web/html, i fa referència al ''main.js'' com has fet moltes vegades.
  
Debes prestar atención a las pruebas locales — si intentas cargar el archivo HTML localmente (es decir, con una URL file:///), te encontrarás con errores de CORS debido a los requisitos de seguridad del módulo JavaScript. Necesitas hacer tus pruebas a través de un servidor.
+
Has de tindre en compte els problemes que et trobaràs amb les proves locals (si intentes carregar l'arxiu HTML localment, és a dir, amb una URL file:///, ettrobaràs amb errors de CORS degut als requisits de seguretat del mòdul JavaScript. Necessites fer les teves proves en el teu servidor web:
 
+
*http://ruta_apache/index.html
 
Comprovar que el primer exemple funciona correctament (''basic-modules''), i comprovar que funciona la resta d'exemples.
 
Comprovar que el primer exemple funciona correctament (''basic-modules''), i comprovar que funciona la resta d'exemples.
  
=Cas pràctic. Dibuixar un mapa amb la llibreria OpenLayers=
+
=Utilitzar mòduls a la consola.=
==Treballar amb llibreries==
+
En aquesta cas hem d'utilitzar l'extensió ''.mjs'' (mòduls de js en comptes de .js). El codi mínim i que no té interfície gràfica seria:
A high-performance, feature-packed library for all your mapping needs.
 
*https://openlayers.org/
 
 
 
Donar una ullada a tots els exemples que podem fer a:
 
*https://openlayers.org/en/latest/examples/
 
 
 
Però el ''hola món'' de com pintar un mapa és a:
 
*https://openlayers.org/en/latest/doc/quickstart.html
 
 
 
En el primer exemple no utilitzem els mòduls, ho fem amb les llibreries:
 
 
 
script ''pintar_mapa.html'':
 
<pre>
 
<!doctype html>
 
<html lang="en">
 
  <head>
 
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css" type="text/css">
 
    <style>
 
      .map {
 
        height: 400px;
 
        width: 100%;
 
      }
 
    </style>
 
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
 
    <title>OpenLayers example</title>
 
  </head>
 
  <body>
 
    <h2>My Map</h2>
 
    <div id="map" class="map"></div>
 
    <script type="text/javascript">
 
      var map = new ol.Map({
 
        target: 'map',
 
        layers: [
 
          new ol.layer.Tile({
 
            source: new ol.source.OSM()
 
          })
 
        ],
 
        view: new ol.View({
 
          center: ol.proj.fromLonLat([37.41, 8.82]),
 
          zoom: 4
 
        })
 
      });
 
    </script>
 
  </body>
 
</html>
 
</pre>
 
*Pintar el mapa sobre la teva ciutat amb un nivell de zoom adequat.
 
*Provar una altra servidor de ''tiles'':
 
<pre>
 
source: new ol.source.Stamen({layer: 'toner'})
 
</pre>
 
Ara farem aquest mateix exercici amb mòduls. Els exemples que hem vist anteriorment estan tots amb mòduls.
 
 
 
==Treballar amb mòduls==
 
Per treballar amb mòduls, que és la manera recomanable, hem d'anar als ''Tutorials'', i anar al primer de tots: ''Building an OpenLayers Application'':
 
*https://openlayers.org/en/latest/doc/tutorials/
 
*https://openlayers.org/en/latest/doc/tutorials/bundle.html
 
<pre>
 
$ mkdir app
 
$ cd app
 
</pre>
 
Per crear l'aplicació i importar tots els mòduls de Openlayers, utilitzarem ''npm''.
 
<pre>
 
$ npm init
 
</pre>
 
Quan et pregunta, pots deixar totes les opcions per defecte. S'ha creat el fitxer package.json.
 
 
 
This will create a package.json file in your working directory. Add OpenLayers as dependency to your application with
 
<pre>
 
$ npm install ol
 
</pre>
 
Es crea la carpeta ''node_modules'' amb totes les dependències.
 
At this point you can ask NPM to add required development dependencies by running
 
<pre>
 
$ npm install --save-dev parcel-bundler
 
</pre>
 
Què és parcel?
 
*https://parceljs.org/
 
Blazing fast, zero configuration web application bundler
 
 
 
 
 
Ara necessitem construir l'aplicació, amb els fitxers ''index.js'' i ''index.html''.
 
 
 
script ''index.js'':
 
<pre>
 
import 'ol/ol.css';
 
import {Map, View} from 'ol';
 
import TileLayer from 'ol/layer/Tile';
 
import {fromLonLat} from 'ol/proj'; //línia nova
 
import OSM from 'ol/source/OSM';
 
 
 
const map = new Map({
 
  target: 'map',
 
  layers: [
 
    new TileLayer({
 
      source: new OSM()
 
    })
 
  ],
 
  view: new View({
 
    //center: [0, 0],
 
    center: fromLonLat([1.9858, 41.9176]), //línia modificada
 
    zoom: 0
 
  })
 
});
 
</pre>
 
 
 
script ''index.html'':
 
<pre>
 
<!DOCTYPE html>
 
<html>
 
  <head>
 
    <meta charset="utf-8">
 
    <title>Using Parcel with OpenLayers</title>
 
    <style>
 
      #map {
 
        width: 400px;
 
        height: 250px;
 
      }
 
    </style>
 
  </head>
 
  <body>
 
    <div id="map"></div>
 
    <script src="./index.js"></script>
 
  </body>
 
</html>
 
</pre>
 
 
 
Modifiquem el fitxer ''package.json'' per definir com es fa el ''build'' de l'aplicació i com s'engega (''start''):
 
 
 
''package.json'':
 
<pre>
 
{
 
  "name": "test",
 
  "version": "1.0.0",
 
  "description": "",
 
  "main": "index.js",
 
  "scripts": {
 
    "test": "echo \"Error: no test specified\" && exit 1",
 
    "start": "parcel index.html",
 
    "build": "parcel build --public-url . index.html"
 
  },
 
  "author": "",
 
  "license": "ISC"
 
}
 
</pre>
 
Finalment, per fer córrer l'aplicació, farem:
 
<pre>
 
$ npm start
 
 
 
> app@1.0.0 start /home/joan/M06_WEC_2021/UF2/openlayers/app
 
> parcel index.html
 
 
 
Server running at http://localhost:1234
 
✨  Built in 13.21s.
 
</pre>
 
*localhost:1234
 
Per crear un production bundle (es crea la carpeta dist/)
 
<pre>
 
$ npm run build
 
 
 
> app@1.0.0 build /home/joan/M06_WEC_2021/UF2/openlayers/app
 
> parcel build --public-url . index.html
 
 
 
✨  Built in 21.59s.
 
 
 
dist/app.ef0d89f9.js.map    ⚠️  1.95 MB    248ms
 
dist/app.ef0d89f9.js          540.56 KB    19.16s
 
dist/app.bb28b584.css.map      7.18 KB      3ms
 
dist/app.bb28b584.css          3.96 KB    5.42s
 
dist/index.html                  273 B    2.06s
 
 
 
</pre>
 
and copy the ''dist/'' folder to your production server.
 
 
 
Aquesta carpeta '''dist/''' conté totes les llibreries i el codi comprimit. L'objectiu és ara posar aquesta carpeta ''dist/'' dins el teu Apache/XAMP i veure que funciona. Per tant, distingim entre l'entorn de desenvolupament, i l'entorn de desplegament en la fase de producció.
 
  
=Dòlmens de Catalunya=
+
script ''square.mjs'':
==Posar una icona sobre un mapa==
 
Se't proporciona el codi mínim per pintar una icona sobre un mapa. En aquest cas, com a mapa escollim el render de OSM:
 
<pre>
 
import 'ol/ol.css';
 
import Feature from 'ol/Feature';
 
import Map from 'ol/Map';
 
import VectorSource from 'ol/source/Vector';
 
import View from 'ol/View';
 
import {Icon, Style} from 'ol/style';
 
import {LineString, Point} from 'ol/geom';
 
import {getVectorContext} from 'ol/render';
 
import {fromLonLat} from 'ol/proj';
 
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
 
import OSM from 'ol/source/OSM';
 
 
 
var features = new Array();
 
var feature = new Feature({
 
  'geometry': new Point(fromLonLat([1.9858, 41.9176])),
 
  'name': 'nom element',
 
});
 
 
 
features.push(feature)
 
 
 
var iconStyle = new Style({
 
  image: new Icon({
 
    anchor: [0.5,20],
 
    anchorXUnits: 'fraction',
 
    anchorYUnits: 'pixels',
 
    src: 'img/dolmen_16.png'
 
  })
 
});
 
 
 
var vectorSource = new VectorSource({
 
  features: features,
 
  wrapX: false,
 
});
 
 
 
var vector = new VectorLayer({
 
  source: vectorSource,
 
  style: iconStyle,
 
});
 
 
 
var map = new Map({
 
  layers: [
 
    new TileLayer({
 
      source: new OSM({
 
        layer: 'OSM'
 
      })
 
    }),
 
    vector
 
  ],
 
  target: 'map',
 
  view: new View({
 
    center: fromLonLat([1.9858, 41.9176]),
 
    zoom: 9
 
  })
 
});
 
</pre>
 
==Dibuixar tots els dòlmens. Solució==
 
[[Fitxer:Dolmens.zip]]
 
En el següent fitxer se't proporciona:
 
*dolmens.js (llistat dels dòlmens en format json, geolocalitzats, a punt per exportar el mòdul, veure la última línea)
 
*img/dolmen_16.png: és la icona que farem servir.
 
*solució_v0: index_v0.html i main_v0.html. Pintem només una icona (un dolmen) sobre el mapa.
 
*solució_v1: index_v1.html i main_v1.html. Pintem tots els dòlmens. En l'exercici anterior havies aconseguit pintar un marker (icona). Ara es tracta de recórrer tots els dòlmens, omplir tota la matriu, i posar una icona ben geolocalitzada per cada dolmen.
 
*solució_v2: index_v2.html i main_v2.html. Volem ampliar la funcionalitat. Quan cliquem sobre el dolmen se'ns mostra una caixa de text amb el nom i el municipi del dolmen.
 
 
 
=Feina per l'alumne=
 
*El primer objectiu és fer funcionar (i entendre) tots els exemples proposats
 
*Partint de l'aplicatiu dels dòlmens, ara l'objectiu és pintar sobre un mapa una altra informació de nodes geolocalitzats que puguis aconseguir de OSM (consulta a Overpass Turbo). Per exemple, se't proposa el llistat de vèrtex geodèsics de Catalunya:
 
<pre>
 
https://wiki.openstreetmap.org/wiki/ES:Tag:man_made%3Dsurvey_point
 
man_made=survey_point
 
</pre>
 
O bé qualsevol altra informació que consideris d'interès (però han de ser nodes/punts, no vies). En cas de dubte, consultar el professor.
 
 
 
Exemple real: mapa interactiu de les restes de la muralla medieval de Màlaga:
 
*https://umap.openstreetmap.fr/es/map/muralla-medieval-de-malaga_563990#16/36.7246/-4.4135
 
Un altre exemple: Catalunya Màgica, topònims catalans amb les paraueles ''bruixa'', ''dimoni'', ''diable'', ''drac'', ''infern'':
 
*https://catalunyamagica.joanillo.org/
 
 
 
=Desplegament de l'aplicatiu=
 
Mira aquest projecte similar:
 
*http://wiki.joanillo.org/index.php/Catalunya_M%C3%A0gica
 
i llegeix atentament l'apartat de ''desplegament''. Ho comentarem a classe.
 
 
 
=Entrega al Classroom=
 
Entregaràs al Classroom la teva solució, dins del termini previst per fer-ho.
 
 
 
=Utilitzar mòduls a la consola. Actualitzar Node=
 
El codi mínim i que no té interfície gràfica seria:
 
 
 
script ''square.js'':
 
 
<pre>
 
<pre>
 
const name = 'square';
 
const name = 'square';
Línia 315: Línia 47:
 
</pre>
 
</pre>
  
script ''main.js'':
+
script ''main.mjs'':
 
<pre>
 
<pre>
 
import { name, instanciar, reportArea, reportPerimeter } from './square.mjs';
 
import { name, instanciar, reportArea, reportPerimeter } from './square.mjs';
Línia 326: Línia 58:
 
I si fem:
 
I si fem:
 
<pre>
 
<pre>
$ node main.js
+
$ node main.mjs  
import { name, instanciar, reportArea, reportPerimeter } from './square.js';
 
      ^
 
 
 
SyntaxError: Unexpected token {
 
    at Module._compile (internal/modules/cjs/loader.js:723:23)
 
...
 
</pre>
 
dóna error, no sap què és aquesta sintaxi. I és que cal tenir el node ben actualitzat. Com es comenta a:
 
*https://stackoverflow.com/questions/39436322/node-js-syntaxerror-unexpected-token-import
 
això funciona en la versió 13. Jo tinc la versió:
 
<pre>
 
$ node --version
 
v10.19.0
 
</pre>
 
i per tal de què funcioni el codi s'ha de fer:
 
#posar els scripts amb extensió .mjs en comptes de .js
 
#utilitzar l'opció --experimental-modules
 
<pre>
 
$ node --experimental-modules main.mjs
 
(node:5212) ExperimentalWarning: The ESM module loader is experimental.
 
 
10000
 
10000
 
400
 
400
 
</pre>
 
</pre>
==Actualitzar Node a la última versió==
+
Podem provar aquest codi en l'espai que tens en el servidor '''vps-89148e22.vps.ovh.net'''.
*https://phoenixnap.com/kb/update-node-js-version
+
 
1. First, clear the npm cache:
+
=Tasques a realitzar=
 +
[[Fitxer:Arc sant marti.png | thumbnail | (c) by Levon]]
 +
L'exemple mínim per dibuixar un cercle en un canvas el trobaràs per exemple a:
 +
*https://www.w3schools.com/tags/canvas_arc.asp
 
<pre>
 
<pre>
$ npm cache clean -f
+
var c = document.getElementById("myCanvas");
 +
var ctx = c.getContext("2d");
 +
ctx.beginPath();
 +
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
 +
ctx.stroke();
 
</pre>
 
</pre>
2. Install n, Node’s version manager:
+
En realitat, més que un cercle estàs dibuixant un arc de circunferència. Quan l'angle són 360º (=2*Pi) aleshores l'arc és una circunferència sencera.
<pre>
+
 
$ sudo npm install -g n
+
El mètode ''arc()'' té 5 paràmetres: la posició x i y del centre, el radi, l'angle on comença l'arc, i la longitud de l'arc (en graus).
</pre>
+
 
3. With the n module installed, you can use it to:
+
Basan-te en el codi que has vist a ''square.js'', faràs el script ''circle.js'' on definiràs els següents mètodes:
<pre>
+
*draw()
$ n latest
+
*randomCirlce()
$ sudo n latest
+
*reportArea()
  installing : node-v16.1.0
+
*reportPerimeter
      mkdir : /usr/local/n/versions/node/16.1.0
+
 
      fetch : https://nodejs.org/dist/v16.1.0/node-v16.1.0-linux-x64.tar.xz
+
Seguint el mateix esquema, programaràs el script ''index.html'' (que contindrà dos canvas diferents) i el script ''main.js''.
  installed : v16.1.0 (with npm 7.11.2)
+
 
 +
'''1.''' En el primer canvas, dibuixaràs l'arc de Sant Martí (semicercles concèntrics). En una matriu posaràs els colors de l'Arc de Sant Martí (https://www.krishnamani.in/color-codes-for-rainbow-vibgyor-colours/), i tot recorrent aquesta matriu aniràs construint l'Arc de Sant Martí.
  
Note: the node command changed location and the old location may be remembered in your current shell.
+
'''2.''' En el segon canvas dibuixaràs 10 cercles aleatoris amb diferents graus de gris (serà aleatori el centre, el radi i el nivell de gris).
        old : /usr/bin/node
 
        new : /usr/local/bin/node
 
To reset the command location hash either start a new shell, or execute PATH="$PATH"
 
</pre>
 
Tanco la consola i n'obro una altra, i ara ja tenim la última versió:
 
<pre>
 
$ node --version
 
v16.1.0
 
</pre>
 
i podem provar el nostre codi, que ara ja funciona sense experimental:
 
<pre>
 
$ node main.mjs
 
10000
 
400
 
</pre>
 
ara bé, si vull utilitzar l'extensió .js, necessito un package.json:
 
<pre>
 
$ node main.js
 
(node:7055) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
 
(Use `node --trace-warnings ...` to show where the warning was created)
 
/home/joan/main.js:1
 
import { name, instanciar, reportArea, reportPerimeter } from './square.js';
 
^^^^^^
 
  
SyntaxError: Cannot use import statement outside a module
+
=Entrega al Classroom=
</pre>
+
Entregaràs al Classroom, dins del termini, un pdf amb dues captures de pantalla dels dos canvas, el codi del script ''circle.js'', i el codi del fitxer ''main.js''.
{{Autor}}, març 2021
+
{{Autor}}, març 2022

Revisió de 17:39, 31 març 2022

Mòduls. Introducció

$ unzip js-examples-master.zip

Anem al primer exemple:

$ cd js-examples-master/modules/basic-modules/
$ ls
index.html
main.js
modules/
    canvas.js
    square.js

Trobem els exports en els scripts de la carpeta modules/: canvas.js i square.js. Les funcions definides en aquests mòduls s'importen en el main.js, que és el fitxer principal de Javascript. El index.html és el punt d'entrada de la web/html, i fa referència al main.js com has fet moltes vegades.

Has de tindre en compte els problemes que et trobaràs amb les proves locals (si intentes carregar l'arxiu HTML localment, és a dir, amb una URL file:///, ettrobaràs amb errors de CORS degut als requisits de seguretat del mòdul JavaScript. Necessites fer les teves proves en el teu servidor web:

Comprovar que el primer exemple funciona correctament (basic-modules), i comprovar que funciona la resta d'exemples.

Utilitzar mòduls a la consola.

En aquesta cas hem d'utilitzar l'extensió .mjs (mòduls de js en comptes de .js). El codi mínim i que no té interfície gràfica seria:

script square.mjs:

const name = 'square';

function instanciar(length, color) {
  return {
    length: length,
    color: color
  };
}

function reportArea(length) {
  console.log(length*length);
}

function reportPerimeter(length) {
    console.log(4*length);
}

export { name, instanciar, reportArea, reportPerimeter };

script main.mjs:

import { name, instanciar, reportArea, reportPerimeter } from './square.mjs';

let square1 = instanciar(100, 'blue');
reportArea(square1.length);
reportPerimeter(square1.length);

I si fem:

$ node main.mjs 
10000
400

Podem provar aquest codi en l'espai que tens en el servidor vps-89148e22.vps.ovh.net.

Tasques a realitzar

(c) by Levon

L'exemple mínim per dibuixar un cercle en un canvas el trobaràs per exemple a:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.stroke();

En realitat, més que un cercle estàs dibuixant un arc de circunferència. Quan l'angle són 360º (=2*Pi) aleshores l'arc és una circunferència sencera.

El mètode arc() té 5 paràmetres: la posició x i y del centre, el radi, l'angle on comença l'arc, i la longitud de l'arc (en graus).

Basan-te en el codi que has vist a square.js, faràs el script circle.js on definiràs els següents mètodes:

  • draw()
  • randomCirlce()
  • reportArea()
  • reportPerimeter

Seguint el mateix esquema, programaràs el script index.html (que contindrà dos canvas diferents) i el script main.js.

1. En el primer canvas, dibuixaràs l'arc de Sant Martí (semicercles concèntrics). En una matriu posaràs els colors de l'Arc de Sant Martí (https://www.krishnamani.in/color-codes-for-rainbow-vibgyor-colours/), i tot recorrent aquesta matriu aniràs construint l'Arc de Sant Martí.

2. En el segon canvas dibuixaràs 10 cercles aleatoris amb diferents graus de gris (serà aleatori el centre, el radi i el nivell de gris).

Entrega al Classroom

Entregaràs al Classroom, dins del termini, un pdf amb dues captures de pantalla dels dos canvas, el codi del script circle.js, i el codi del fitxer main.js.


creat per Joan Quintana Compte, març 2022