• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Mapa nie widzi danych w tablicy nie wiem jak to naprawić

Object Storage Arubacloud
0 głosów
200 wizyt
pytanie zadane 21 kwietnia 2020 w JavaScript przez robertos18 Obywatel (1,120 p.)

Po zamontowaniu mapki na moją stronke


state={
items:[{
      "X": 13.6155611,
      "Y": 51.0331258
    },
    ],
}

 addItem = (e) => {
    e.preventDefault();
    const newItem = {
      "Y": parseFloat(this.state.X),
      "X": parseFloat(this.state.Y),
    };
    this.setState(prevState => ({
      items: [...prevState.items, newItem]
    }));

  }
componentDidMount() {
    const map = new mapboxgl.Map({
      container: this.mapContainer,
      center: [this.state.lng, this.state.lat],
      zoom: this.state.zoom,
    });
for (var i = 0; i < this.state.items.length; i++) {
      var obj = this.state.items[i];
      let myLatlng = new mapboxgl.LngLat(obj.X, obj.Y);
      new mapboxgl.Marker()
        .setLngLat(myLatlng)
        .addTo(map);
    }

}

 render() {
    return (
        <div ref={el => this.mapContainer = el} />

<form onSubmit={this.addItem}>
 <input
              type="number"
              value={this.state.X}
              onChange={e => this.setState({
                X: e.target.value
              })}
            />
            <input
              value={this.state.Y}
              onChange={e => this.setState({
                Y: e.target.value
              })}
            />
</Form>
)}

Chciałbym wyswietlac markery po wpisaniu x i y, i czytac te dane z tablicy. Mam 2 inputy jeden dla X drugi dla Y po kliknieciu przycisku "add"
dodaje mi do tablicy te dane i mam 2 obiekty itp.. ale na mapie wyswietla mi się tylko jeden marker ten na sztywno wpisany w state.items mimo, z w tablicy mam wiecej wspolrzednych. Wiem, ze metoda componentDidMount() jest uruchamiana tylko raz i tutaj jest problem. Proszę o pomoc

1 odpowiedź

0 głosów
odpowiedź 22 kwietnia 2020 przez DawidK Nałogowiec (37,910 p.)

Być może ten kod Ci pomoże (na przykładzie leaflet). Rysowanie markerów jest umieszczone w render() return

npm

npm install react-leaflet

index.html (tak naprawde jedyna  zmiana to umieszczenie css z leaflet)

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>
  <title>Mapa</title>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
</head>
<body>
  <div id='root'></div>
</body>
</html>

App.css (mapka z leaflet musi mieć hight, border nie jest potrzebny)

.map {
    border: 1px solid black;
    height: 600px;
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
    <App />,
    document.getElementById('root')
);

App.js (zmienne X i Y zamieniłem na lat i lng , dodałem też funkcje do zmiany wartości poza renderem)

- import elementów z leaflet

- state dla tablicy markerów i nowego markera

- addItem - dodaje nowy marker do tablicy markerów i czyści state odpowiedzialny na wyświetlanie value (lat, lng) w formularzu

- updateNewMarkerLat/Lng - zmieniają state nowego markera (onchange)

- w render() / return mapa i rysowanie markerów (wyrysują się bo state się zmieni) + formularz

import React, {Component} from 'react';
import { Map, TileLayer, Marker} from 'react-leaflet';
import './App.css';

class App extends Component {
  constructor(){
    super();
    this.state = {
      markers:[{
        lat: 51.0331258,
        lng: 13.6155611,
      }],
      newMarker: {
        lat: '',
        lng: '',
      }
    }
  }

  addItem = (e) => {
    const markers = this.state.markers
    markers.push(this.state.newMarker)

    const emptyMarker = {...this.state.newMarker}
    emptyMarker.lat = ''
    emptyMarker.lng = ''
    this.setState({markers:markers,newMarker:emptyMarker})
    e.preventDefault();
  }

  updateNewMarkerLat = (e) => {
    const updatedState = {...this.state.newMarker}
    updatedState.lat = parseFloat(e.target.value)
    this.setState({newMarker:updatedState})
  }

  updateNewMarkerLng = (e) => {
    const updatedState = {...this.state.newMarker}
    updatedState.lng = parseFloat(e.target.value)
    this.setState({newMarker:updatedState})
  }

  render(){
      return (
        <div>
            <p>mapa</p>
            <Map className='map' center={[51,13.6]} zoom={12}>
              <TileLayer attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
              {this.state.markers.map((position, id) =>
                        <Marker key={`marker-${id}`} position={position}></Marker>
                    )}
            </Map>
            <form onSubmit={this.addItem}>
              <input type="number" value={this.state.newMarker.lat} onChange={this.updateNewMarkerLat}/>
              <input type="number" value={this.state.newMarker.lng} onChange={this.updateNewMarkerLng}/>
              <button type='submit'>dodaj</button>
            </form>
        </div>
      );
    }
  }

export default App;

Jakoś działa nie wiem jednak czy jest to najbardziej elegancki i zgodny z praktykami sposób - może ktoś jeszcze się wypowie.

komentarz 22 kwietnia 2020 przez robertos18 Obywatel (1,120 p.)
Dzięki ale potrzebna mi mapa mapbox gl js bo tam mam tez inne elementy dodane wiesz moze jak zrobic to na przykladzie mapboxa ? W sensie wyjac inicjalizacjr mapy z componentDidmount i wrzucic ja do klasy?
1
komentarz 22 kwietnia 2020 przez DawidK Nałogowiec (37,910 p.)

Nie korzystałem wcześniej z mapboxgl - także to co jest poniżej powinno działać, ale coś czuje, że to mega chory plan.

npm

npm install mapbox-gl

index.html (podobnie jak w przypadku leaflet - dodany css dla  mapbox

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>
  <title>Mapa</title>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.9.1/mapbox-gl.css' rel='stylesheet' />
</head>
<body>
  <div id='root'></div>
</body>
</html>

App.css (style dla mapy z dokumentacji + wrapper)

.wrapper {
  position: relative;
  height: 600px;
}

.mapContainer {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
  }

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
    <App />,
  document.getElementById('root')
);

i wkońcu chory plan w App.js

- import map-box

- token (trzeba zmienić na wlasny)

- state dla markerów

- przy montowaniu komponentu umieszczenie mapy i markerów

- i to co podejrzewam, że jest mega dziwne - za każdym dodaniem markera znowu umieszczenie mapy i markerów

import React, {Component} from 'react';
import mapboxgl from 'mapbox-gl';
import './App.css';

mapboxgl.accessToken = '...................................'; // zmienić na własny

class App extends Component {
  constructor(){
    super();
    this.state = {
      markers:[{
        lat: 51.0331258,
        lng: 10.6155611,
      }],
      newMarker: {
        lat: '',
        lng: '',
      }
    }
  }

  componentDidMount() {
        const map = new mapboxgl.Map({
        container: this.mapContainer,
        style: 'mapbox://styles/mapbox/streets-v11',
        center:[13,51],
        zoom: 6
      });
        for(let i=0; i<this.state.markers.length;i++){
          let coord = this.state.markers[i]
          let marker = new mapboxgl.Marker().setLngLat([coord.lng,coord.lat]).addTo(map);
        }
    }

  addItem = (e) => {
    const markers = this.state.markers
    markers.push(this.state.newMarker)

    const emptyMarker = {...this.state.newMarker}
    emptyMarker.lat = ''
    emptyMarker.lng = ''
    this.setState({markers:markers,newMarker:emptyMarker})

    const map = new mapboxgl.Map({
      container: this.mapContainer,
      style: 'mapbox://styles/mapbox/streets-v11',
      center:[13,51],
      zoom: 6
    });
      for(let i=0; i<this.state.markers.length;i++){
        let coord = this.state.markers[i]
        let marker = new mapboxgl.Marker().setLngLat([coord.lng,coord.lat]).addTo(map);
      }
    e.preventDefault();
  }

  updateNewMarkerLat = (e) => {
    const updatedState = {...this.state.newMarker}
    updatedState.lat = parseFloat(e.target.value)
    this.setState({newMarker:updatedState})
  }

  updateNewMarkerLng = (e) => {
    const updatedState = {...this.state.newMarker}
    updatedState.lng = parseFloat(e.target.value)
    this.setState({newMarker:updatedState})
  }

  render(){
      return (
        <div>
            <p className='sidebarStyle'>mapa</p>
            <div className="wrapper">
              <div ref={el => this.mapContainer = el} className="mapContainer" />
            </div>
            <form onSubmit={this.addItem}>
              <input type="number" value={this.state.newMarker.lat} onChange={this.updateNewMarkerLat}/>
              <input type="number" value={this.state.newMarker.lng} onChange={this.updateNewMarkerLng}/>
              <button type='submit'>dodaj</button>
            </form>
        </div>
      );
    }
  }

export default App;

 

komentarz 22 kwietnia 2020 przez robertos18 Obywatel (1,120 p.)

Tylko teraz za każdym razem gdy klikne przycisk dodaj tworzy mi nową mapę i np gdy klikne 3 razy dodaj to mam 3 mapy na stronie ;p Probowałem zrobić tak: 

state={
items:[{
      "X": 13.6155611,
      "Y": 51.0331258
    },
    ],
}

 addItem = (e) => {
    e.preventDefault();
    const newItem = {
      "Y": parseFloat(this.state.X),
      "X": parseFloat(this.state.Y),
    };
    this.setState(prevState => ({
      items: [...prevState.items, newItem]
    }));

  }
componentDidUpdate(prevProps, prevState, snapshot) {
  if (this.state.items.length !== prevState.items.length) {
    const map = new mapboxgl.Map({
      container: this.mapContainer,
      center: [this.state.lng, this.state.lat],
      zoom: this.state.zoom,
    });
    for (var i = 0; i < this.state.items.length; i++) {
      var obj = this.state.items[i];
      let myLatlng = new mapboxgl.LngLat(obj.X, obj.Y);
      new mapboxgl.Marker()
        .setLngLat(myLatlng)
        .addTo(map);
    }
  }
}
render() {
    return (
        <div ref={el => this.mapContainer = el} />

<form onSubmit={this.addItem}>
 <input
              type="number"
              value={this.state.X}
              onChange={e => this.setState({
                X: e.target.value
              })}
            />
            <input
              value={this.state.Y}
              onChange={e => this.setState({
                Y: e.target.value
              })}
            />
 <button>ADD</button>
</form>
)}

ale efekt jest ten sam....

komentarz 22 kwietnia 2020 przez DawidK Nałogowiec (37,910 p.)
edycja 22 kwietnia 2020 przez DawidK
u mnie wygladą to troszkę inaczej - pewnie przez css i wrapper. faktycznie tworzą się kolejne mapy, ale jedna zasłania drugą - tak czy inaczej jak przypuszczałem - to nie do końca to o co chodzi, pozmóżdżam się nad tym pewnie jeszcze troche
komentarz 22 kwietnia 2020 przez robertos18 Obywatel (1,120 p.)
dziękuję, ja tez pokombinuję, ale nie sadziłem, że tyle problemow z tym bedzie..
1
komentarz 22 kwietnia 2020 przez DawidK Nałogowiec (37,910 p.)
chyba, wprowadziłem Cie trochę w błąd dodałem kilka markerów i to nie mapy się tworzą tylko zagnieżdżone divy z warstwami, czyli mapa jest jedna, więc ten kod, który przesłałem wyżej powinien dzialać i wyświetlać 1 mapę. Jednak szósty zmysł pająka podpowiada mi, że coś tam jest nie tak jak powinno.
komentarz 22 kwietnia 2020 przez robertos18 Obywatel (1,120 p.)
edycja 23 kwietnia 2020 przez robertos18
Okej, zrobiłem tak, ze na moim kodzie tez działa sugerując się Twoim przykładem ;) Mam jeszcze pytanie do Ciebie, robie taka mini aplikacje dla siebie i chciałbym w niej tworzyć trasy od punktu do punktow. W sesnie zaznaczam na mapie kilka markerów i klikajać w nie tworzą się na mapce trasy, narazie udało mi sie zrobić tyle ze klikajac na jeden marker tworzy mi się trasa od ustalonego punktu potem jak klikne w kolejny marker to tamta sie wyłacza i robi sie nowa trasa do tego nowego markera, robiłes cos kiedys na podobe moze ?
komentarz 23 kwietnia 2020 przez DawidK Nałogowiec (37,910 p.)
W google maps o ile pamiętam można tam było umieszczać linie jako tablica z punktami początek/koniec zaczal bym od pogrzebania w dokumentacji i szukania przykładów na add line/add polygon - pewnie jest coś takiego, albo zbliżone
komentarz 23 kwietnia 2020 przez DawidK Nałogowiec (37,910 p.)
To może być ciekawy punkt wyjścia

https://docs.mapbox.com/mapbox-gl-js/example/geojson-line/

Podobne pytania

0 głosów
0 odpowiedzi 464 wizyt
0 głosów
1 odpowiedź 139 wizyt
pytanie zadane 13 maja 2022 w JavaScript przez chrystian Gaduła (4,780 p.)

92,572 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...