19、谷歌地图的使用与互动:样式定制与推特集成

谷歌地图的使用与互动:样式定制与推特集成

1. 谷歌地图样式定制

在使用谷歌地图创建更高级的应用程序时,我们常常希望创建自定义的地图样式。这在我们需要突出前景内容而不希望其与背景内容相互干扰时尤为有用。

1.1 地图不可平移的处理

当尝试拖动高级地图(第一个可见地图)时,会发现地图无法移动,即不可平移。谷歌 API v3 不支持直接禁用平移功能,但支持在地图中心点每次更改时进行更新。我们可以通过监听 center_changed 事件来实现地图位置的锁定:

google.maps.event.addListener(mapOut, 'center_changed', function() {
    mapOut.panTo(BASE_CENTER); 
});

这样,每次地图位置改变时,都会强制将其移回原始位置,从而使地图无法移动。

1.2 创建自定义地图样式

以下是创建自定义地图样式的具体步骤:
1. 创建静脉样式数组 :在 init 函数中创建 aVeinStyle 数组,该数组包含了以静脉样式对地图进行皮肤化的所有视觉指南。

var aVeinStyle =  [
  {
    featureType:'water',
    elementType: "geometry",
    stylers:[{color:'#E398BF'}]
  },
  {
    featureType:'road',
    elementType: "geometry",
    stylers:[{color:'#C26580'}]
  },
  {
    featureType:'road.arterial',
    elementType: "geometry",
    stylers:[{color:'#9B2559'}]
  },
  {
    featureType:'road.highway',
    elementType: "geometry",
    stylers:[{color:'#75000D'}]
  },
  {
    featureType:'landscape.man_made',
    elementType: "geometry",
    stylers:[{color:'#F2D2E0'}]
  },
  {
    featureType:'poi',
    elementType: "geometry",
    stylers:[{color:'#C96FB9'}]
  },
  {
    elementType: "labels",
    stylers:[{visibility:'off'}]
  }
];
  1. 创建静脉样式地图对象 :创建一个名为 Veins 的新 google.maps.StyledMapType 地图。
var veinStyle = new google.maps.StyledMapType(aVeinStyle,{name: "Veins"});
  1. 创建公交样式 :创建一个公交样式数组 aBusStyle ,并创建对应的 google.maps.StyledMapType 对象。
var aBusStyle =  [
  {
    stylers: [{saturation: -100}]
  },
  {
    featureType:'transit.station.rail',
    stylers:[{ saturation: 60},{hue:'#0044ff'},{visibility:'on'}]
  }
];
var busStyle = new google.maps.StyledMapType(aBusStyle,{name: "Buses"}); 
  1. 设置内部地图的地图类型控制器 :使内部地图的地图类型控制器可见,并在其中包含我们新地图样式的 ID。
var mapIn = new google.maps.Map(document.getElementById("mapIn"),{
  center: BASE_CENTER,
  zoom: 14,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  disableDefaultUI: true,
  panControl:true,
  mapTypeControl:true,
  mapTypeControlOptions: {
    mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'veinStyle', 'busStyle']
  }
});
  1. 添加地图样式信息 :将地图样式信息添加到 mapIn 对象中。
mapIn.mapTypes.set('veinStyle', veinStyle);
mapIn.mapTypes.set('busStyle', busStyle);    
  1. 设置默认地图类型 :将默认地图类型设置为 busStyle
mapIn.setMapTypeId('busStyle');

重启内部地图的 HTML 文件后,会发现一个控制器菜单,可用于在自定义地图类型之间进行切换。

1.3 样式工作原理

使用谷歌样式的工作方式与 CSS 非常相似。设置样式通常有以下几个步骤:
1. 创建样式规则 :定义样式的具体规则,如颜色、饱和度等。
2. 定义谷歌样式对象 :使用 google.maps.StyledMapType 创建样式对象。
3. 指定适用地图 :将样式信息应用到特定的地图上。需要注意的是,样式只能应用于 google.maps.MapTypeId.ROADMAP 类型的地图。

以下是一些常见的样式属性:
| 属性 | 描述 | 取值范围 |
| ---- | ---- | ---- |
| visibility | 用于添加或移除地图元素,通常用于移除标签和细节文本 | no, off, simplified |
| gamma | 控制视图内的光线量,较低值会增强明暗颜色的对比度,较高值会使一切更亮 | 0.01 - 10(默认 1.0) |
| hue | 以十六进制颜色值表示,类似于戴上与该颜色匹配的有色眼镜对周围颜色的影响 | 如 #222222 |
| lightness | 负值类似于在地图上覆盖一个黑色矩形并改变其不透明度,正值则使用白色矩形 | -100 - 100(默认 0) |
| saturation | 负值创建灰度图像,正值移除灰色使图像更鲜艳 | -100 - 100(默认 0) |

我们还可以通过 elementType featureType 属性来过滤要控制的地图元素:
- elementType 选项 :有 all (默认选项)、 geometry labels 三种类型。
- featureType 属性 :用于指定要关注的具体特征类型,如 landscape.man_made 等。完整的 featureType 属性选项列表可访问 http://goo.gl/H7HSO

2. 连接推特提要到谷歌地图

将推特提要与谷歌地图连接是一个有趣的实验。目标是在推特帖子和谷歌地图之间建立联系,当用户点击地图上的任何区域时,会连接到推特 API 并搜索该区域内包含 “HTML5” 一词的推文。搜索结果返回后,会在点击区域弹出一个新标记,并显示该位置关于该主题的最新推文。

2.1 准备工作

在开始之前,建议先了解谷歌地图的基本使用,并确保已经设置好谷歌 API。

2.2 具体实现步骤
  1. 创建 HTML 文件 :添加以下代码到 HTML 文件中,并使用自己的 API 密钥:
<!DOCTYPE html>
<html>
  <head>
    <title>Google Maps Markers and Events</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style>
      html { height: 100% }
      body { height: 100%; margin: 0; padding: 0 }
      #map { height: 100%; width:100%; position:absolute; top:0px; left:0px }
    </style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="http://maps.googleapis.com/maps/api/js?key=AIzaSyAywwIFJPo67Yd4vZgPz4EUSVu10BLHroE&sensor=true"></script>
    <script src="./10.01.socielmap.js"></script>
  </head>
  <body onload="init();">
    <div id="map"></div>
  </body>
</html>
  1. 编写 JavaScript 代码 :在 init 函数中编写所有代码。
function init(){
    // 1. 设置地图中心点
    var BASE_CENTER = new google.maps.LatLng(48.516817734860105,13.005318750000015 );
    // 2. 创建黑白样式
    var aGray =  [
        {
            stylers: [{saturation: -100}]
        }
    ];
    var grayStyle = new google.maps.StyledMapType(aGray,{name: "Black & White"});
    // 3. 创建新的谷歌地图
    var map = new google.maps.Map(document.getElementById("map"),{
        center: BASE_CENTER,
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true,
    });
    // 4. 设置默认样式
    map.mapTypes.set('grayStyle', grayStyle);
    map.setMapTypeId('grayStyle');
    // 5. 创建地图点击事件
    google.maps.event.addListener(map, 'click', function(e) {
        var searchKeyWord = 'html5';
        var geocode=e.latLng.lat() + "," + e.latLng.lng()+",50km";
        var searchLink = 'http://search.twitter.com/search.json?q='+ searchKeyWord+ '&geocode=' + geocode +"&result_type=recent&rpp=1";
        $.getJSON(searchLink, function(data) {
            showTweet(data.results[0],e.latLng);
        });
    });
    // 6. 显示推文
    function showTweet(obj,latLng){
        if(!obj) obj = {text:'No tweet found in this area for this topic'};
        console.log(obj);
        var marker = new google.maps.Marker({
            map: map,
            position: latLng,
            title:obj.text    
        });
    }
}
2.3 工作原理

在当今时代,几乎所有数据都越来越多地与地理位置数据和地图重叠。推特一直在努力捕捉用户的位置信息,虽然目前大部分时间位置信息仍为空,但随着时间推移,其准确性有望提高。

具体工作流程如下:
1. 构建搜索查询 :用户点击地图时,根据点击位置构建一个包含搜索关键词 “HTML5” 和搜索范围(50 公里)的查询链接。

var searchKeyWord = 'html5';
var geocode=e.latLng.lat() + "," + e.latLng.lng()+",50km";
var searchLink = 'http://search.twitter.com/search.json?q='+ searchKeyWord+ '&geocode=' + geocode +"&result_type=recent&rpp=1";
  1. 发送请求并获取结果 :使用 jQuery 的 $.getJSON 函数将请求发送到推特 API,并将返回的 JSON 数据解码为普通 JavaScript 对象。
$.getJSON(searchLink, function(data) {
    showTweet(data.results[0],e.latLng);
});
  1. 创建标记 :在 showTweet 函数中,检查返回的第一个元素是否有数据。如果没有,则创建一个包含占位信息的新对象。最后,创建一个标记并将其添加到地图上。
function showTweet(obj,latLng){
    if(!obj) obj = {text:'No tweet found in this area for this topic'};
    var marker = new google.maps.Marker({
        map: map,
        position: latLng,
        title:obj.text    
    });
}

需要注意的是,目前从推特返回的对象中 geo 属性始终为空,但这可能是一个即将发布或部分实现的功能。在未来,我们可以尝试检查 obj.geo 属性是否有值,并使用该信息使标记位置更准确。

通过以上步骤,我们可以实现谷歌地图的样式定制以及与推特提要的连接,为地图应用增添更多的交互性和实用性。

谷歌地图的使用与互动:样式定制与推特集成

3. 构建高级交互式标记

高级交互式标记可以为地图增添更多的交互性和信息展示能力。以下是构建高级交互式标记的一些思路和实现步骤。

3.1 设计标记交互逻辑

高级交互式标记通常需要具备一些特殊的交互行为,例如点击标记弹出详细信息窗口、鼠标悬停显示提示信息等。我们可以通过监听标记的事件来实现这些交互逻辑。

// 创建标记
var marker = new google.maps.Marker({
    map: map,
    position: latLng,
    title: 'Advanced Marker'
});

// 监听标记的点击事件
google.maps.event.addListener(marker, 'click', function() {
    // 显示详细信息窗口
    var infoWindow = new google.maps.InfoWindow({
        content: '<p>This is a detailed description of the marker.</p>'
    });
    infoWindow.open(map, marker);
});

// 监听标记的鼠标悬停事件
google.maps.event.addListener(marker, 'mouseover', function() {
    // 显示提示信息
    marker.setTitle('Hovered Marker');
});

google.maps.event.addListener(marker, 'mouseout', function() {
    // 恢复原始标题
    marker.setTitle('Advanced Marker');
});
3.2 自定义标记外观

除了交互逻辑,我们还可以自定义标记的外观,使其更加个性化。可以使用自定义图标或样式来替换默认的标记图标。

// 自定义标记图标
var customIcon = {
    url: 'custom-marker.png',
    scaledSize: new google.maps.Size(32, 32)
};

// 创建带有自定义图标的标记
var customMarker = new google.maps.Marker({
    map: map,
    position: latLng,
    icon: customIcon,
    title: 'Custom Marker'
});
4. 向信息窗口气泡中添加多条推文

在之前的基础上,我们可以进一步改进,向信息窗口气泡中添加多条推文,以提供更丰富的信息。

4.1 修改搜索链接和结果处理

首先,我们需要修改搜索链接,以获取更多的推文结果。

google.maps.event.addListener(map, 'click', function(e) {
    var searchKeyWord = 'html5';
    var geocode = e.latLng.lat() + "," + e.latLng.lng() + ",50km";
    // 修改 rpp 参数以获取更多推文
    var searchLink = 'http://search.twitter.com/search.json?q=' + searchKeyWord + '&geocode=' + geocode + "&result_type=recent&rpp=5";

    $.getJSON(searchLink, function(data) {
        showTweets(data.results, e.latLng);
    });
});
4.2 显示多条推文

然后,在 showTweets 函数中,将多条推文添加到信息窗口中。

function showTweets(results, latLng) {
    var content = '<div>';
    if (results.length === 0) {
        content += '<p>No tweets found in this area for this topic</p>';
    } else {
        for (var i = 0; i < results.length; i++) {
            content += '<p>' + results[i].text + '</p>';
        }
    }
    content += '</div>';

    var marker = new google.maps.Marker({
        map: map,
        position: latLng
    });

    var infoWindow = new google.maps.InfoWindow({
        content: content
    });

    google.maps.event.addListener(marker, 'click', function() {
        infoWindow.open(map, marker);
    });
}
5. 自定义标记的外观和感觉

除了前面提到的自定义图标,我们还可以通过其他方式自定义标记的外观和感觉,例如改变标记的颜色、形状等。

5.1 使用 SVG 图标

SVG 图标具有可扩展性和良好的兼容性,可以用于创建各种形状和颜色的标记。

// 定义 SVG 图标
var svgIcon = {
    path: 'M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm61.8-104.4l-84.9-61.7c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v141.7l66.8 48.6c5.4 3.9 6.5 11.4 2.6 16.8l-32 48c-4.4 6.6-12.3 8.9-18.8 5.3z',
    fillColor: '#FF5722',
    fillOpacity: 1,
    strokeWeight: 0,
    scale: 0.5
};

// 创建带有 SVG 图标的标记
var svgMarker = new google.maps.Marker({
    map: map,
    position: latLng,
    icon: svgIcon,
    title: 'SVG Marker'
});
5.2 动画效果

为标记添加动画效果可以使其更加生动。

// 创建标记并添加动画
var animatedMarker = new google.maps.Marker({
    map: map,
    position: latLng,
    animation: google.maps.Animation.BOUNCE
});

// 可以在适当的时候停止动画
setTimeout(function() {
    animatedMarker.setAnimation(null);
}, 3000);
6. 最终项目:构建实时行程

结合前面的知识,我们可以构建一个实时行程项目,将地图、标记和推文信息整合在一起,为用户提供一个实时的行程规划和信息展示平台。

6.1 项目架构设计

实时行程项目的架构可以分为以下几个部分:
1. 地图显示 :使用谷歌地图显示行程的地理位置。
2. 标记添加 :根据用户的行程安排,在地图上添加标记,代表不同的地点。
3. 推文信息 :在标记上显示与该地点相关的推文信息,为用户提供更多的实时资讯。
4. 行程管理 :允许用户添加、删除和修改行程中的地点。

6.2 实现步骤

以下是实现实时行程项目的大致步骤:

graph LR
    A[初始化地图] --> B[设置地图样式]
    B --> C[添加行程地点标记]
    C --> D[监听标记点击事件]
    D --> E[搜索并显示相关推文]
    E --> F[提供行程管理功能]
// 初始化地图
function initMap() {
    var BASE_CENTER = new google.maps.LatLng(48.516817734860105, 13.005318750000015);
    var aGray = [
        {
            stylers: [{ saturation: -100 }]
        }
    ];
    var grayStyle = new google.maps.StyledMapType(aGray, { name: "Black & White" });
    var map = new google.maps.Map(document.getElementById("map"), {
        center: BASE_CENTER,
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true
    });
    map.mapTypes.set('grayStyle', grayStyle);
    map.setMapTypeId('grayStyle');

    // 行程地点数组
    var itineraryPlaces = [
        { latLng: new google.maps.LatLng(48.516817734860105, 13.005318750000015), name: 'Place 1' },
        { latLng: new google.maps.LatLng(49.516817734860105, 14.005318750000015), name: 'Place 2' }
    ];

    // 添加行程地点标记
    itineraryPlaces.forEach(function(place) {
        var marker = new google.maps.Marker({
            map: map,
            position: place.latLng,
            title: place.name
        });

        // 监听标记点击事件
        google.maps.event.addListener(marker, 'click', function() {
            var searchKeyWord = 'HTML5';
            var geocode = place.latLng.lat() + "," + place.latLng.lng() + ",50km";
            var searchLink = 'http://search.twitter.com/search.json?q=' + searchKeyWord + '&geocode=' + geocode + "&result_type=recent&rpp=5";

            $.getJSON(searchLink, function(data) {
                var content = '<div>';
                if (data.results.length === 0) {
                    content += '<p>No tweets found in this area for this topic</p>';
                } else {
                    for (var i = 0; i < data.results.length; i++) {
                        content += '<p>' + data.results[i].text + '</p>';
                    }
                }
                content += '</div>';

                var infoWindow = new google.maps.InfoWindow({
                    content: content
                });
                infoWindow.open(map, marker);
            });
        });
    });

    // 行程管理功能示例:添加新地点
    function addNewPlace(latLng, name) {
        var newPlace = { latLng: latLng, name: name };
        itineraryPlaces.push(newPlace);

        var newMarker = new google.maps.Marker({
            map: map,
            position: latLng,
            title: name
        });

        // 监听新标记的点击事件
        google.maps.event.addListener(newMarker, 'click', function() {
            var searchKeyWord = 'HTML5';
            var geocode = latLng.lat() + "," + latLng.lng() + ",50km";
            var searchLink = 'http://search.twitter.com/search.json?q=' + searchKeyWord + '&geocode=' + geocode + "&result_type=recent&rpp=5";

            $.getJSON(searchLink, function(data) {
                var content = '<div>';
                if (data.results.length === 0) {
                    content += '<p>No tweets found in this area for this topic</p>';
                } else {
                    for (var i = 0; i < data.results.length; i++) {
                        content += '<p>' + data.results[i].text + '</p>';
                    }
                }
                content += '</div>';

                var infoWindow = new google.maps.InfoWindow({
                    content: content
                });
                infoWindow.open(map, newMarker);
            });
        });
    }

    // 示例:添加新地点
    addNewPlace(new google.maps.LatLng(50.516817734860105, 15.005318750000015), 'New Place');
}

通过以上步骤,我们可以构建一个实时行程项目,为用户提供一个集成地图、标记和推文信息的交互平台,帮助用户更好地规划和了解行程。

综上所述,谷歌地图提供了丰富的功能和强大的扩展性,通过样式定制、与推特集成以及构建各种交互元素,我们可以创建出功能丰富、交互性强的地图应用程序。无论是个人项目还是商业应用,都可以利用这些技术来满足不同的需求。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值