使用 JavaScript 在 Rails 应用程序的一个视图中渲染一系列 Google 地图

Rendering a series of Google Maps within one View of a Rails app using JavaScript

本文关键字:视图 一个 地图 Google 一系列 Rails JavaScript 应用程序 使用      更新时间:2023-09-26

我正在使用Ruby on Rails构建一个总线跟踪应用程序。它接受来自用户的当前位置,并使用从亚特兰大 MARTA 交通系统的 API 收集的巴士信息显示最近的公交车。

我正在使用一个javascript文件为最近公交车的简短列表中每辆公交车渲染单独的地图,并用一个标记显示用户的当前位置,用另一个标记显示公交车的位置。

我最初使用嵌入在一对<script></script>标签中的 JavaScript 对视图进行编码,并让所有内容按设计工作。此后,我将 JavaScript 移动到资产管道中自己的文件中,并从视图中发送了相关变量。现在,我的视图仅呈现列表中的最终地图,其余地图画布呈现为空框。

我是一个非常新的 Stack Overflow 用户,我有点担心我的问题不够具体,但我非常卡住,不知道下一步该去哪里。我感觉有些不太了解 Rails 如何处理我的 JavaScript 文件以及我从视图中发送的变量,但我在互联网上搜索了一些,还没有找到任何相关的文章。我欢迎有关调试技术或外部资源引用的建议,而不是人们只是为我修复代码。

也就是说,这是我application.js.erb文件中渲染地图的行:

var map = new google.maps.Map(document.getElementById('map_canvas_' + busNum), mapOptions);

您可以在此处查看完整的application.js.erb文件:

$(document).ready(function() {
  function initialize() {
    var currentLatLng = new google.maps.LatLng(currentLat, currentLng);
    var busLatLng = new google.maps.LatLng(busLat, busLng);
    var mapOptions = {
      center: currentLatLng,
      zoom: 14,
      scrollwheel: false
    };
    var map = new google.maps.Map(document.getElementById('map_canvas_' + busNum), mapOptions);
    var userMarker = new google.maps.Marker({
      position: currentLatLng,
      map: map,
      title: 'User',
      animation: google.maps.Animation.DROP
    });
    var imgSize = 30;
    var busIcon = {
      url: "<%= asset_path 'bus-marker.png' %>",
      scaledSize: new google.maps.Size(imgSize, imgSize * 1.5),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(imgSize * 1.5 / 2, imgSize)
    };
    var busMarker = new google.maps.Marker({
      position: busLatLng,
      map: map,
      title: 'Bus',
      icon: busIcon,
      animation: google.maps.Animation.BOUNCE
    });
    var current = 'You are here.';
    var userInfo = new google.maps.InfoWindow({
      content: current
    });
    var route = 'Bus number' + count + 'is on Route ' + busRoute + '. The next stop is at ' + busStop + '.';
    var busInfo = new google.maps.InfoWindow({
      content: route
    });
    google.maps.event.addListener(userMarker, 'click', function() {
      userInfo.open(map, userMarker);
    });
    google.maps.event.addListener(busMarker, 'click', function() {
      busInfo.open(map, busMarker);
    });
  };
  google.maps.event.addDomListener(window, 'load', initialize);
});

以下是我想要渲染该地图的视图中的行:

<div class="well center-block bus-map" id="map_canvas_<%= bus["VEHICLE"] %>"></div>

下面是循环访问关闭总线列表中的每个项目的循环:

<% @proximate_buses.each_with_index do |bus, index| %>
    <div class="col-md-6">
        <div class="panel">
            <div class="panel-header text-center">
                <h3>Route: <%= bus["ROUTE"] %></h3>
                <h3>Bus No: <%= bus["VEHICLE"] %></h3>
                <h3>Next Stop: <%= bus["TIMEPOINT"] %></h3>
            </div>
            <div class="panel-body">
                <%= javascript_tag do %>
                  var currentLat = '<%= j @location.latitude.to_s %>';
                  var currentLng = '<%= j @location.longitude.to_s %>';
                  var busLat = '<%= j bus["LATITUDE"].to_s %>';
                  var busLng = '<%= j bus["LONGITUDE"].to_s %>';
                  var busNum = '<%= j bus["VEHICLE"].to_s %>';
                  var busRoute = '<%= j bus["ROUTE"].to_s %>';
                  var busStop = '<%= j bus["TIMEPOINT"].to_s %>';
                  var count = '<%= j (index + 1).to_s %>';
                <% end %>
                <div class="well center-block bus-map" id="map_canvas_<%= bus["VEHICLE"] %>"></div>
            </div>
        </div>
    </div>
<% end %>

任何帮助,不胜感激。

问题在application.js.erb中busNum,它只有一个(最后一个)。您必须循环并创建所有可用的总线编号(以及相对映射)。

>@Andrea,你是对的,busNum只得到一个值,这是一个问题。

经过一些工具,我已经弄清楚了如何编码它,以便 javascript 在 @display_buses 中为每个总线运行,这是@proximate_buses前八个元素的子集。我还对视图进行了一些清理,以便业务全部发生在单独的locations.js.erb文件中。

下面是新视图:

<p id="notice">
  <%=n otice %>
</p>
<div class="row">
  <h2>The <%= NumbersInWords.in_words(@display_buses.length) %> closest buses</h2>
  <% if @display_buses.length==0 %>
    <h3>...are pretty far away, actually! Consider an alternative mode of transportation.</h3>
    <% end %>
      <div class="well center-block bus-map" id="map"></div>
</div>

这是JavaScript文件中发生的循环:

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require bootstrap-sprockets
//= require_tree .
$(document).ready(function() {
  var currentLat = gon.current_lat;
  var currentLng = gon.current_lng;
  var displayBuses = gon.display_buses;
  var currentLatLng = new google.maps.LatLng(currentLat, currentLng);
  function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
      center: currentLatLng,
      zoom: 15,
      scrollwheel: false
    });
    setMarkers(map);
  }
  function setMarkers(map) {
    var userMarker = new google.maps.Marker({
      position: currentLatLng,
      map: map,
      title: 'User',
      animation: google.maps.Animation.DROP
    });
    var userInfo = new google.maps.InfoWindow({
      content: 'You are here.'
    });
    google.maps.event.addListener(userMarker, 'click', function() {
      userInfo.open(map, userMarker);
    });
    var imgHt = 30;
    var imgWd = imgHt * 1.5;
    var busIcon = {
      url: "<%= asset_path 'bus-marker.png' %>",
      scaledSize: new google.maps.Size(imgHt, imgWd),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(imgWd / 2, imgHt)
    };
    var infoWindow = new google.maps.InfoWindow;
    var busLatLng, busMarker, i;
    var busInfo = [];
    for (i = 0; i < displayBuses.length; i++) {
      var busLat = displayBuses[i].LATITUDE;
      var busLng = displayBuses[i].LONGITUDE;
      var busNum = displayBuses[i].VEHICLE;
      var busRoute = displayBuses[i].ROUTE;
      var busStop = displayBuses[i].TIMEPOINT;
      busLatLng = new google.maps.LatLng(busLat, busLng);
      busMarker = new google.maps.Marker({
        position: busLatLng,
        map: map,
        title: 'Bus number ' + busNum,
        icon: busIcon,
        animation: google.maps.Animation.BOUNCE
      });
      busInfo[i] = new google.maps.InfoWindow({
        content: 'Bus number ' + busNum + ' is on Route ' + busRoute + '. The next stop is at ' + busStop + '.'
      });
      google.maps.event.addListener(busMarker, 'click', (function(busMarker, busInfo) {
        return function() {
          infoWindow.setContent(busInfo.content);
          infoWindow.open(map, busMarker);
        }
      })(busMarker, busInfo[i]));
    }
  };
  google.maps.event.addDomListener(window, 'load', initMap);
});

我正在使用一个名为 gon 的 gem,它为 js 提供变量,而不是我之前繁琐的定义。这让我可以通过locations控制器发送@location属性和@display_buses - 非常流畅。