מיפוי שיתופי בזמן אמת ב-Firebase

סקירה כללית

במדריך הזה תלמדו איך ליצור מפה אינטראקטיבית באמצעות פלטפורמת האפליקציות של Firebase. אפשר ללחוץ על מיקומים שונים במפה שלמטה כדי ליצור מפת חום.

הקטע הבא מציג את הקוד המלא שדרוש לכם כדי ליצור את המפה במדריך הזה.

/**
 * Firebase config block.
 */
var config = {
  apiKey: 'AIzaSyDX-tgWqPmTme8lqlFn2hIsqwxGL6FYPBY',
  authDomain: 'maps-docs-team.firebaseapp.com',
  databaseURL: 'https://maps-docs-team.firebaseio.com',
  projectId: 'maps-docs-team',
  storageBucket: 'maps-docs-team.appspot.com',
  messagingSenderId: '285779793579'
};

firebase.initializeApp(config);

/**
 * Data object to be written to Firebase.
 */
var data = {sender: null, timestamp: null, lat: null, lng: null};

function makeInfoBox(controlDiv, map) {
  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px';
  controlUI.style.backgroundColor = '#fff';
  controlUI.style.border = '2px solid #fff';
  controlUI.style.borderRadius = '2px';
  controlUI.style.marginBottom = '22px';
  controlUI.style.marginTop = '10px';
  controlUI.style.textAlign = 'center';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.color = 'rgb(25,25,25)';
  controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
  controlText.style.fontSize = '100%';
  controlText.style.padding = '6px';
  controlText.textContent =
      'The map shows all clicks made in the last 10 minutes.';
  controlUI.appendChild(controlText);
}

      /**
      * Starting point for running the program. Authenticates the user.
      * @param {function()} onAuthSuccess - Called when authentication succeeds.
      */
      function initAuthentication(onAuthSuccess) {
        firebase.auth().signInAnonymously().catch(function(error) {
          console.log(error.code + ', ' + error.message);
        }, {remember: 'sessionOnly'});

        firebase.auth().onAuthStateChanged(function(user) {
          if (user) {
            data.sender = user.uid;
            onAuthSuccess();
          } else {
            // User is signed out.
          }
        });
      }

      /**
       * Creates a map object with a click listener and a heatmap.
       */
      function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: 0, lng: 0},
          zoom: 3,
          styles: [{
            featureType: 'poi',
            stylers: [{ visibility: 'off' }]  // Turn off POI.
          },
          {
            featureType: 'transit.station',
            stylers: [{ visibility: 'off' }]  // Turn off bus, train stations etc.
          }],
          disableDoubleClickZoom: true,
          streetViewControl: false,
        });

        // Create the DIV to hold the control and call the makeInfoBox() constructor
        // passing in this DIV.
        var infoBoxDiv = document.createElement('div');
        makeInfoBox(infoBoxDiv, map);
        map.controls[google.maps.ControlPosition.TOP_CENTER].push(infoBoxDiv);

        // Listen for clicks and add the location of the click to firebase.
        map.addListener('click', function(e) {
          data.lat = e.latLng.lat();
          data.lng = e.latLng.lng();
          addToFirebase(data);
        });

        // Create a heatmap.
        var heatmap = new google.maps.visualization.HeatmapLayer({
          data: [],
          map: map,
          radius: 16
        });

        initAuthentication(initFirebase.bind(undefined, heatmap));
      }

      /**
       * Set up a Firebase with deletion on clicks older than expiryMs
       * @param {!google.maps.visualization.HeatmapLayer} heatmap The heatmap to
       */
      function initFirebase(heatmap) {

        // 10 minutes before current time.
        var startTime = new Date().getTime() - (60 * 10 * 1000);

        // Reference to the clicks in Firebase.
        var clicks = firebase.database().ref('clicks');

        // Listen for clicks and add them to the heatmap.
        clicks.orderByChild('timestamp').startAt(startTime).on('child_added',
          function(snapshot) {
            // Get that click from firebase.
            var newPosition = snapshot.val();
            var point = new google.maps.LatLng(newPosition.lat, newPosition.lng);
            var elapsedMs = Date.now() - newPosition.timestamp;

            // Add the point to the heatmap.
            heatmap.getData().push(point);

            // Request entries older than expiry time (10 minutes).
            var expiryMs = Math.max(60 * 10 * 1000 - elapsedMs, 0);

            // Set client timeout to remove the point after a certain time.
            window.setTimeout(function() {
              // Delete the old point from the database.
              snapshot.ref.remove();
            }, expiryMs);
          }
        );

        // Remove old data from the heatmap when a point is removed from firebase.
        clicks.on('child_removed', function(snapshot, prevChildKey) {
          var heatmapData = heatmap.getData();
          var i = 0;
          while (snapshot.val().lat != heatmapData.getAt(i).lat()
            || snapshot.val().lng != heatmapData.getAt(i).lng()) {
            i++;
          }
          heatmapData.removeAt(i);
        });
      }

      /**
       * Updates the last_message/ path with the current timestamp.
       * @param {function(Date)} addClick After the last message timestamp has been updated,
       *     this function is called with the current timestamp to add the
       *     click to the firebase.
       */
      function getTimestamp(addClick) {
        // Reference to location for saving the last click time.
        var ref = firebase.database().ref('last_message/' + data.sender);

        ref.onDisconnect().remove();  // Delete reference from firebase on disconnect.

        // Set value to timestamp.
        ref.set(firebase.database.ServerValue.TIMESTAMP, function(err) {
          if (err) {  // Write to last message was unsuccessful.
            console.log(err);
          } else {  // Write to last message was successful.
            ref.once('value', function(snap) {
              addClick(snap.val());  // Add click with same timestamp.
            }, function(err) {
              console.warn(err);
            });
          }
        });
      }

      /**
       * Adds a click to firebase.
       * @param {Object} data The data to be added to firebase.
       *     It contains the lat, lng, sender and timestamp.
       */
      function addToFirebase(data) {
        getTimestamp(function(timestamp) {
          // Add the new timestamp to the record data.
          data.timestamp = timestamp;
          var ref = firebase.database().ref('clicks').push(data, function(err) {
            if (err) {  // Data was not written to firebase.
              console.warn(err);
            }
          });
        });
      }
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=visualization&callback=initMap" defer></script>
<script src="https://www.gstatic.com/firebasejs/5.3.0/firebase.js"></script>

התנסות עצמית

אפשר להתנסות בקוד הזה ב-JSFiddle על ידי לחיצה על הסמל <> בפינה השמאלית העליונה של חלון הקוד.

<!DOCTYPE html>
<html>
  <head>
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>

    <script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-database.js"></script>
    <script>
/**
 * Firebase config block.
 */
var config = {
  apiKey: 'AIzaSyDX-tgWqPmTme8lqlFn2hIsqwxGL6FYPBY',
  authDomain: 'maps-docs-team.firebaseapp.com',
  databaseURL: 'https://maps-docs-team.firebaseio.com',
  projectId: 'maps-docs-team',
  storageBucket: 'maps-docs-team.appspot.com',
  messagingSenderId: '285779793579'
};

firebase.initializeApp(config);

/**
 * Data object to be written to Firebase.
 */
var data = {sender: null, timestamp: null, lat: null, lng: null};

function makeInfoBox(controlDiv, map) {
  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px';
  controlUI.style.backgroundColor = '#fff';
  controlUI.style.border = '2px solid #fff';
  controlUI.style.borderRadius = '2px';
  controlUI.style.marginBottom = '22px';
  controlUI.style.marginTop = '10px';
  controlUI.style.textAlign = 'center';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.color = 'rgb(25,25,25)';
  controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
  controlText.style.fontSize = '100%';
  controlText.style.padding = '6px';
  controlText.textContent =
      'The map shows all clicks made in the last 10 minutes.';
  controlUI.appendChild(controlText);
}

      /**
      * Starting point for running the program. Authenticates the user.
      * @param {function()} onAuthSuccess - Called when authentication succeeds.
      */
      function initAuthentication(onAuthSuccess) {
        firebase.auth().signInAnonymously().catch(function(error) {
          console.log(error.code + ', ' + error.message);
        }, {remember: 'sessionOnly'});

        firebase.auth().onAuthStateChanged(function(user) {
          if (user) {
            data.sender = user.uid;
            onAuthSuccess();
          } else {
            // User is signed out.
          }
        });
      }

      /**
       * Creates a map object with a click listener and a heatmap.
       */
      function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: 0, lng: 0},
          zoom: 3,
          styles: [{
            featureType: 'poi',
            stylers: [{ visibility: 'off' }]  // Turn off POI.
          },
          {
            featureType: 'transit.station',
            stylers: [{ visibility: 'off' }]  // Turn off bus, train stations etc.
          }],
          disableDoubleClickZoom: true,
          streetViewControl: false,
        });

        // Create the DIV to hold the control and call the makeInfoBox() constructor
        // passing in this DIV.
        var infoBoxDiv = document.createElement('div');
        makeInfoBox(infoBoxDiv, map);
        map.controls[google.maps.ControlPosition.TOP_CENTER].push(infoBoxDiv);

        // Listen for clicks and add the location of the click to firebase.
        map.addListener('click', function(e) {
          data.lat = e.latLng.lat();
          data.lng = e.latLng.lng();
          addToFirebase(data);
        });

        // Create a heatmap.
        var heatmap = new google.maps.visualization.HeatmapLayer({
          data: [],
          map: map,
          radius: 16
        });

        initAuthentication(initFirebase.bind(undefined, heatmap));
      }

      /**
       * Set up a Firebase with deletion on clicks older than expiryMs
       * @param {!google.maps.visualization.HeatmapLayer} heatmap The heatmap to
       */
      function initFirebase(heatmap) {

        // 10 minutes before current time.
        var startTime = new Date().getTime() - (60 * 10 * 1000);

        // Reference to the clicks in Firebase.
        var clicks = firebase.database().ref('clicks');

        // Listen for clicks and add them to the heatmap.
        clicks.orderByChild('timestamp').startAt(startTime).on('child_added',
          function(snapshot) {
            // Get that click from firebase.
            var newPosition = snapshot.val();
            var point = new google.maps.LatLng(newPosition.lat, newPosition.lng);
            var elapsedMs = Date.now() - newPosition.timestamp;

            // Add the point to the heatmap.
            heatmap.getData().push(point);

            // Request entries older than expiry time (10 minutes).
            var expiryMs = Math.max(60 * 10 * 1000 - elapsedMs, 0);

            // Set client timeout to remove the point after a certain time.
            window.setTimeout(function() {
              // Delete the old point from the database.
              snapshot.ref.remove();
            }, expiryMs);
          }
        );

        // Remove old data from the heatmap when a point is removed from firebase.
        clicks.on('child_removed', function(snapshot, prevChildKey) {
          var heatmapData = heatmap.getData();
          var i = 0;
          while (snapshot.val().lat != heatmapData.getAt(i).lat()
            || snapshot.val().lng != heatmapData.getAt(i).lng()) {
            i++;
          }
          heatmapData.removeAt(i);
        });
      }

      /**
       * Updates the last_message/ path with the current timestamp.
       * @param {function(Date)} addClick After the last message timestamp has been updated,
       *     this function is called with the current timestamp to add the
       *     click to the firebase.
       */
      function getTimestamp(addClick) {
        // Reference to location for saving the last click time.
        var ref = firebase.database().ref('last_message/' + data.sender);

        ref.onDisconnect().remove();  // Delete reference from firebase on disconnect.

        // Set value to timestamp.
        ref.set(firebase.database.ServerValue.TIMESTAMP, function(err) {
          if (err) {  // Write to last message was unsuccessful.
            console.log(err);
          } else {  // Write to last message was successful.
            ref.once('value', function(snap) {
              addClick(snap.val());  // Add click with same timestamp.
            }, function(err) {
              console.warn(err);
            });
          }
        });
      }

      /**
       * Adds a click to firebase.
       * @param {Object} data The data to be added to firebase.
       *     It contains the lat, lng, sender and timestamp.
       */
      function addToFirebase(data) {
        getTimestamp(function(timestamp) {
          // Add the new timestamp to the record data.
          data.timestamp = timestamp;
          var ref = firebase.database().ref('clicks').push(data, function(err) {
            if (err) {  // Data was not written to firebase.
              console.warn(err);
            }
          });
        });
      }
    </script>
    <script defer
        src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=visualization&callback=initMap">
    </script>
  </body>
</html>

תחילת העבודה

תוכלו לפתח גרסה משלכם למפה של Firebase באמצעות הקוד במדריך הזה. כדי להתחיל כשעושים את זה, יוצרים קובץ חדש בכלי לעריכת טקסט ושומרים אותו בשם index.html.

כדאי לקרוא את הקטעים הבאים כדי להבין מהו הקוד שניתן להוסיף לקובץ.

יצירת מפה בסיסית

בקטע הזה מוסבר הקוד שמגדיר את המפה הבסיסית. יכול להיות שזה דומה לאופן שבו יצרת ממפה כאשר איך מתחילים לעבוד עם Maps JavaScript API?

מעתיקים את הקוד שבהמשך לקובץ index.html. הקוד הזה טוען את של Maps JavaScript API, והופך את המפה למסך מלא. הוא גם טוען את התצוגה החזותית שנדרשת בהמשך המדריך כדי ליצור מפת חום.

<!DOCTYPE html>
<html>
  <head>
    <style>
      #map {
        height: 100%;
      }
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script defer
        src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY
        &libraries=visualization&callback=initMap">
    </script>

    <script>
      // The JavaScript code that creates the Firebase map goes here.
    </script>

  </body>
</html>

לוחצים על YOUR_API_KEY בדוגמה של הקוד או פועלים לפי ההוראות כדי קבלת מפתח API. החלפה YOUR_API_KEY מחליפים במפתח ה-API של האפליקציה שלכם.

בקטעים הבאים נסביר מהו קוד ה-JavaScript שיוצר את מפת Firebase. אפשר להעתיק ולשמור את הקוד בקובץ firebasemap.js, ולהפנות אותו בין תגי סקריפט בתור שלמטה.

<script>firebasemap.js</script>

לחלופין, אפשר להוסיף את הקוד ישירות בין תגי הסקריפט, כמו קוד דוגמה מלא בתחילת המדריך הזה.

צריך להוסיף את הקוד שבהמשך לקובץ firebasemap.js, או בין תגי הסקריפט הריקים של את קובץ index.html שלך. זאת נקודת ההתחלה להפעלת התוכנית על ידי יצירת שמאתחלת את אובייקט המפה.

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 0, lng: 0},
    zoom: 3,
    styles: [{
      featureType: 'poi',
      stylers: [{ visibility: 'off' }]  // Turn off points of interest.
    }, {
      featureType: 'transit.station',
      stylers: [{ visibility: 'off' }]  // Turn off bus stations, train stations, etc.
    }],
    disableDoubleClickZoom: true,
    streetViewControl: false
  });
}

כדי שיהיה קל יותר להשתמש במפת החום קליקבילית הזו, הקוד שלמעלה משתמש עיצוב מפה להשבתה של נקודות עניין ותחנות תחבורה ציבורית (שמוצגות חלון מידע כשלוחצים עליו). היא גם משביתה את המרחק מהתצוגה בלחיצה כפולה כדי למנוע שינוי מרחק התצוגה בטעות. מידע נוסף על עיצוב המפה.

אחרי שה-API נטען במלואו, פרמטר הקריאה החוזרת (callback) בתג הסקריפט מפעיל את הפונקציה initMap() בקובץ ה-HTML.

<script defer
    src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY
    &libraries=visualization&callback=initMap">
</script>

צריך להוסיף את הקוד שבהמשך כדי ליצור את פקד הטקסט בחלק העליון של המפה.

function makeInfoBox(controlDiv, map) {
  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px';
  controlUI.style.backgroundColor = '#fff';
  controlUI.style.border = '2px solid #fff';
  controlUI.style.borderRadius = '2px';
  controlUI.style.marginBottom = '22px';
  controlUI.style.marginTop = '10px';
  controlUI.style.textAlign = 'center';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.color = 'rgb(25,25,25)';
  controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
  controlText.style.fontSize = '100%';
  controlText.style.padding = '6px';
  controlText.innerText = 'The map shows all clicks made in the last 10 minutes.';
  controlUI.appendChild(controlText);
}

צריך להוסיף את הקוד שבהמשך בתוך הפונקציה initMap, אחרי var map, כדי לטעון את התיבה של פקד הטקסט.

// Create the DIV to hold the control and call the makeInfoBox() constructor
// passing in this DIV.
var infoBoxDiv = document.createElement('div');
var infoBox = new makeInfoBox(infoBoxDiv, map);
infoBoxDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_CENTER].push(infoBoxDiv);
לניסיון

כדי להציג את מפת Google שהקוד יוצר, צריך לפתוח את index.html בדפדפן אינטרנט.

הגדרת Firebase

כדי להפוך את האפליקציה הזו לשיתופית, צריך לאחסן את הקליקים בקובץ חיצוני מסד נתונים שכל המשתמשים יכולים לגשת אליו. מסד הנתונים בזמן אמת ב-Firebase מתאים למטרה הזו, ולא צריך שום ידע ב-SQL.

קודם כול, נרשמים לחשבון Firebase ללא תשלום. אם זו הפעם הראשונה שאתם משתמשים ב-Firebase, תופיע לכם אפליקציה חדשה בשם 'האפליקציה הראשונה שלי'. אם המיקום כשיוצרים אפליקציה חדשה, אפשר לתת לה שם חדש וכתובת URL מותאמת אישית ב-Firebase שמסתיימת ב- firebaseIO.com לדוגמה, אפשר לתת לאפליקציה את השם 'מפת Firebase של ג'יין' עם כתובת ה-URL https://janes-firebase-map.firebaseIO.com אפשר להשתמש בכתובת ה-URL הזו כדי לקשר את מסד הנתונים לאפליקציית JavaScript.

צריך להוסיף את השורה הבאה אחרי תגי ה-<head> של קובץ ה-HTML כדי לייבא את ספריית Firebase.

<script src="www.gstatic.com/firebasejs/5.3.0/firebase.js"></script>

מוסיפים את השורה הבאה לקובץ ה-JavaScript:

var firebase = new Firebase("<Your Firebase URL here>");

אחסון נתוני קליקים ב-Firebase

בקטע הזה נסביר את הקוד שמאחסן נתונים ב-Firebase, לגבי קליקים של העכבר על המפה.

בכל לחיצה על העכבר על המפה, הקוד שבהמשך יוצר אובייקט נתונים גלובלי ושומר את ב-Firebase. האובייקט הזה מתעד נתונים כמו ה-latLng שלו וחותמת הזמן של הקליק, וכן מזהה ייחודי של הדפדפן שיצר את הקליק.

/**
 * Data object to be written to Firebase.
 */
var data = {
  sender: null,
  timestamp: null,
  lat: null,
  lng: null
};

הקוד הבא מתעד מזהה סשן ייחודי לכל קליק, מה שעוזר לשלוט בקצב התנועה במפה, תוך שמירה על האבטחה של Firebase כללים.

/**
* Starting point for running the program. Authenticates the user.
* @param {function()} onAuthSuccess - Called when authentication succeeds.
*/
function initAuthentication(onAuthSuccess) {
  firebase.auth().signInAnonymously().catch(function(error) {
      console.log(error.code + ", " + error.message);
  }, {remember: 'sessionOnly'});

  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      data.sender = user.uid;
      onAuthSuccess();
    } else {
      // User is signed out.
    }
  });
}

הקטע הבא בקוד שבהמשך מקשיב לקליקים על המפה, ומתווסף 'ילד' אל מסד נתונים ב-Firebase. במצב כזה, הפונקציה snapshot.val() מקבל את ערכי הנתונים של הרשומה ויוצר אובייקט LatLng חדש.

// Listen for clicks and add them to the heatmap.
clicks.orderByChild('timestamp').startAt(startTime).on('child_added',
  function(snapshot) {
    var newPosition = snapshot.val();
    var point = new google.maps.LatLng(newPosition.lat, newPosition.lng);
    heatmap.getData().push(point);
  }
);

הקוד שבהמשך מגדיר את Firebase כך:

  • הקשב לקליקים על המפה. כשמתרחש קליק, האפליקציה מתעדת חותמת זמן, ואז מוסיפה 'ילד' למסד הנתונים ב-Firebase.
  • מחיקת כל הקליקים במפה שהתרחשו לפני יותר מ-10 דקות, ב בזמן אמת.
/**
 * Set up a Firebase with deletion on clicks older than expirySeconds
 * @param {!google.maps.visualization.HeatmapLayer} heatmap The heatmap to
 * which points are added from Firebase.
 */
function initFirebase(heatmap) {

  // 10 minutes before current time.
  var startTime = new Date().getTime() - (60 * 10 * 1000);

  // Reference to the clicks in Firebase.
  var clicks = firebase.database().ref('clicks');

  // Listen for clicks and add them to the heatmap.
  clicks.orderByChild('timestamp').startAt(startTime).on('child_added',
    function(snapshot) {
      // Get that click from firebase.
      var newPosition = snapshot.val();
      var point = new google.maps.LatLng(newPosition.lat, newPosition.lng);
      var elapsedMs = Date.now() - newPosition.timestamp;

      // Add the point to the heatmap.
      heatmap.getData().push(point);

      // Request entries older than expiry time (10 minutes).
      var expiryMs = Math.max(60 * 10 * 1000 - elapsed, 0);
      // Set client timeout to remove the point after a certain time.
      window.setTimeout(function() {
        // Delete the old point from the database.
        snapshot.ref.remove();
      }, expiryMs);
    }
  );

  // Remove old data from the heatmap when a point is removed from firebase.
  clicks.on('child_removed', function(snapshot, prevChildKey) {
    var heatmapData = heatmap.getData();
    var i = 0;
    while (snapshot.val().lat != heatmapData.getAt(i).lat()
      || snapshot.val().lng != heatmapData.getAt(i).lng()) {
      i++;
    }
    heatmapData.removeAt(i);
  });
}

מעתיקים את כל קוד ה-JavaScript בקטע הזה לקובץ firebasemap.js.

יצירת מפת החום

השלב הבא הוא להציג מפת חום שמעניקה לצופים חשיפה גרפית של מספר יחסי של קליקים במיקומים שונים במפה. למידע נוסף, אפשר לקרוא את המדריך למפות חום.

צריך להוסיף את הקוד שבהמשך בתוך הפונקציה initMap() כדי ליצור מפת חום.

// Create a heatmap.
var heatmap = new google.maps.visualization.HeatmapLayer({
  data: [],
  map: map,
  radius: 16
});

הקוד שבהמשך מפעיל את initFirebase, addToFirebase ו-getTimestamp.

initAuthentication(initFirebase.bind(undefined, heatmap));

שימו לב שלחיצה על מפת החום עדיין לא יוצרת נקודות. שפת תרגום יוצרים נקודות במפה, תצטרכו להגדיר האזנה למפה.

יצירת נקודות במפת החום

הקוד שבהמשך מוסיף אוזן בתוך initMap(), אחרי את הקוד שיוצר את המפה. הקוד הזה מאזין לנתונים של כל קליק, שמאחסנת את המיקום של הקליק במסד הנתונים של Firebase, ומציגה את נקודות במפת החום שלך.

// Listen for clicks and add the location of the click to firebase.
map.addListener('click', function(e) {
  data.lat = e.latLng.lat();
  data.lng = e.latLng.lng();
  addToFirebase(data);
});
לניסיון

צריך ללחוץ על מיקומים במפה כדי ליצור נקודות במפת החום.

עכשיו יש לכם אפליקציה בזמן אמת שמשתמשת באופן מלא ב-Firebase, API של מפות Google ל-JavaScript.

כשלוחצים על מפת החום, קווי האורך והרוחב של הקליק מופיעים במסד הנתונים של Firebase. כדי לראות את זה, צריך להיכנס אל חשבון Firebase ועוברים לכרטיסיית הנתונים של האפליקציה. בשלב הזה, אם מישהו אחר ילחץ על המפה, גם אתם וגם אותו אדם יכולים לראות נקודות במפה. מיקום הקליקים נמשך גם לאחר שהמשתמש סוגר את הדף. כדי לבדוק את הפונקציונליות של שיתוף פעולה בזמן אמת, לפתוח את הדף בשני חלונות נפרדים. הסמנים אמורים להופיע בשני הסוגים בזמן אמת.

מידע נוסף

Firebase היא פלטפורמת אפליקציות שמאחסנת נתונים כ-JSON ומסתנכרנת עם כל של לקוחות מקושרים בזמן אמת. היא זמינה גם כשהאפליקציה במצב אופליין. המדריך הזה מתבסס על מסד הנתונים שלו בזמן אמת.