การจับคู่แบบเรียลไทม์ร่วมกันด้วย 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 Maps ที่โค้ดสร้างขึ้น ให้เปิด index.html ในเว็บเบราว์เซอร์

การตั้งค่า Firebase

ในการทำให้แอปพลิเคชันนี้ทำงานร่วมกันได้ คุณจะต้องจัดเก็บการคลิกใน ที่ผู้ใช้ทุกคนเข้าถึงได้ ฐานข้อมูลเรียลไทม์ของ Firebase เหมาะกับวัตถุประสงค์นี้ และไม่ต้องใช้ความรู้เกี่ยวกับ SQL

ขั้นแรก ให้ลงชื่อสมัครใช้บัญชี Firebase โดยไม่มีค่าใช้จ่าย หากคุณเพิ่งเริ่มใช้ Firebase คุณจะเห็นแอปใหม่ชื่อ "My First App" ถ้า เมื่อคุณสร้างแอปใหม่ คุณสามารถตั้งชื่อใหม่และ URL ของ Firebase ที่กำหนดเองที่ลงท้ายด้วย firebaseIO.com ตัวอย่างเช่น คุณอาจตั้งชื่อแอปว่า "Jane's Firebase Map" ด้วย 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 ออบเจ็กต์นี้จะบันทึกข้อมูล เช่น ละติจูดและลองจิจูดของวัตถุ รวมถึงรหัสที่ไม่ซ้ำกันของเบราว์เซอร์ที่สร้างการคลิก

/**
 * 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));

โปรดสังเกตว่าหากคุณคลิกแผนที่ความหนาแน่น แผนที่ความหนาแน่นจะยังไม่สร้างจุด ถึง สร้างจุดบนแผนที่ คุณจะต้องตั้งค่า Listener แผนที่

การสร้างคะแนนบนแผนที่ความหนาแน่น

โค้ดด้านล่างจะเพิ่ม Listener ภายใน 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 และ Maps JavaScript API

เมื่อคุณคลิกแผนที่ความร้อน ละติจูดและลองจิจูดของการคลิกควร ตอนนี้จะปรากฏในฐานข้อมูล Firebase คุณสามารถดูข้อมูลนี้ได้โดยเข้าสู่ระบบ บัญชี Firebase แล้วไปที่แท็บข้อมูลของแอป ในจุดนี้ หากผู้อื่นคลิกบนแผนที่ของคุณ คุณรวมทั้งบุคคลดังกล่าวจะสามารถเห็น ตำแหน่งต่างๆ บนแผนที่ ตำแหน่งของการคลิกจะยังคงอยู่แม้ว่าผู้ใช้จะแล้ว ปิดหน้า ในการทดสอบฟังก์ชันการทำงาน การทำงานร่วมกันแบบเรียลไทม์ เปิดหน้าเว็บในหน้าต่าง 2 หน้าแยกกัน เครื่องหมายควรจะปรากฏบนทั้ง 2 ที่ แบบเรียลไทม์

ดูข้อมูลเพิ่มเติม

Firebase คือแพลตฟอร์มแอปพลิเคชันที่จัดเก็บข้อมูลเป็น JSON และซิงค์กับ ที่เชื่อมต่อกันได้แบบเรียลไทม์ ซึ่งพร้อมใช้งานแม้ในขณะที่แอปออฟไลน์อยู่ บทแนะนำนี้ใช้ฐานข้อมูลแบบเรียลไทม์ของบทแนะนำนี้