Google Maps v3 - 防止 API 加载 Roboto 字体

Posted

技术标签:

【中文标题】Google Maps v3 - 防止 API 加载 Roboto 字体【英文标题】:Google Maps v3 - prevent API from loading Roboto font 【发布时间】:2014-10-20 20:10:18 【问题描述】:

Google 将样式添加到地图容器中以覆盖我的样式。 我知道如何解决这个问题。但是 API (v3.8/9/exp) 也加载了我并不真正需要/不想要的 webfont "Roboto"。

是否有任何设置/选项/解决方法? 我可以阻止 API 添加额外的 CSS 吗?

这是 google-maps-API 添加到我页面的 <head> 的代码:

<style type="text/css">
  .gm-style .gm-style-cc span,
  .gm-style .gm-style-cc a,
  .gm-style .gm-style-mtc div 
    font-size:10px
  
</style>

<link type="text/css" 
      rel="stylesheet" 
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">

<style type="text/css">
  @media print 
    .gm-style .gmnoprint,
    .gmnoprint 
      display:none
    
  
  @media screen 
   .gm-style .gmnoscreen,
   .gmnoscreen 
     display:none
   
  
</style>
<style type="text/css">
  .gm-style 
    font-family: Roboto,Arial,sans-serif;
    font-size: 11px;
    font-weight: 400;
    text-decoration: none
  
</style>

【问题讨论】:

这是输出吗?很难判断代码本身引用了什么。 @JoshBurgess 是的,这是 google 在包含 maps-api-javascript 时添加到 &lt;head&gt; 的内容 由于没有使用旧版本的 gmapsAPI,我无法找到一种方法来阻止 Roboto 在不阻止来自 Apache、IIS 或您正在使用的任何等效项的请求的情况下访问该域。如果这已经足够了,我会将其添加到答案中,但这对我来说似乎是一种逃避。 @pkyeck,看看吧!正在工作! @coma 可以,谢谢 【参考方案1】:

您可以在 Google 脚本调用它之前替换 insertBefore 方法:

http://jsfiddle.net/coma/7st6d9p2/

var head = document.getElementsByTagName('head')[0];

// Save the original method
var insertBefore = head.insertBefore;

// Replace it!
head.insertBefore = function (newElement, referenceElement) 

    if (newElement.href && newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') > -1) 

        console.info('Prevented Roboto from loading!');
        return;
    

    insertBefore.call(head, newElement, referenceElement);
;

// Check it!
new google.maps.Map(document.getElementById('map'), 
    center           : new google.maps.LatLng(51.508742,-0.120850),
    zoom             : 16,
    mapTypeId        : google.maps.MapTypeId.ROADMAP,
    streetViewControl: false,
    zoomControl      : false,
    panControl       : false,
    mapTypeControl   : false
);

【讨论】:

感谢您的回答。希望您可以使用某种 API 选项,但这种“黑客”绝对有效:) 我在他们的文档上没有找到任何东西,猜想他们想保留它的风格。顺便说一句,一旦阻止了字体加载,您可以在每次 insertBefore 调用时恢复更改以跳过该更改。 非常感谢!为我工作。 @AymanSalah 或只使用适用于 http 和 https 的 newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') !== -1 如果地图是使用 iframe 嵌入的,则此解决方案不起作用,因为 Roboto 字体是由 iframe 文档的 head 部分中的 css 调用加载的,无法访问。有什么提示吗?【参考方案2】:

2017 年 10 月更新

Google 改变了在页面上注入样式的方式。目前他们插入了一个空的 style 元素,然后用 Robot 字体更改了这个样式元素的内容。这是一个新的解决方案:

// Preventing the Google Maps libary from downloading an extra font
(function() 
    var isRobotoStyle = function (element) 

        // roboto font download
        if (element.href
            && element.href.indexOf('https://fonts.googleapis.com/css?family=Roboto') === 0) 
            return true;
        
        // roboto style elements
        if (element.tagName.toLowerCase() === 'style'
            && element.styleSheet
            && element.styleSheet.cssText
            && element.styleSheet.cssText.replace('\r\n', '').indexOf('.gm-style') === 0) 
            element.styleSheet.cssText = '';
            return true;
        
        // roboto style elements for other browsers
        if (element.tagName.toLowerCase() === 'style'
            && element.innerhtml
            && element.innerHTML.replace('\r\n', '').indexOf('.gm-style') === 0) 
            element.innerHTML = '';
            return true;
        
        // when google tries to add empty style
        if (element.tagName.toLowerCase() === 'style'
            && !element.styleSheet && !element.innerHTML) 
            return true;
        

        return false;
    

    // we override these methods only for one particular head element
    // default methods for other elements are not affected
    var head = $('head')[0];

    var insertBefore = head.insertBefore;
    head.insertBefore = function (newElement, referenceElement) 
        if (!isRobotoStyle(newElement)) 
            insertBefore.call(head, newElement, referenceElement);
        
    ;

    var appendChild = head.appendChild;
    head.appendChild = function (textNode) 
        if (!isRobotoStyle($(textNode)[0])) 
            appendChild.call(head, textNode);
        
    ;
)();

原始答案

感谢 coma 的解决方案!我还决定拦截覆盖字体系列、字体大小和字体粗细的样式。现代浏览器和 IE8+ 的完整解决方案:

// Preventing the Google Maps libary from downloading an extra font
var head = $('head')[0];
var insertBefore = head.insertBefore;
head.insertBefore = function (newElement, referenceElement) 
    // intercept font download
    if (newElement.href
        && newElement.href.indexOf('https://fonts.googleapis.com/css?family=Roboto') === 0) 
        return;
    
    // intercept style elements for IEs
    if (newElement.tagName.toLowerCase() === 'style'
        && newElement.styleSheet
        && newElement.styleSheet.cssText
        && newElement.styleSheet.cssText.replace('\r\n', '').indexOf('.gm-style') === 0) 
        return;
    
    // intercept style elements for other browsers
    if (newElement.tagName.toLowerCase() === 'style'
        && newElement.innerHTML
        && newElement.innerHTML.replace('\r\n', '').indexOf('.gm-style') === 0) 
        return;
    
    insertBefore.call(head, newElement, referenceElement);
;

【讨论】:

太棒了,非常感谢。您可以轻松省略 2 个 jQuery 引用,因此任何人都可以使用它:document.getElementsByTagName('head')[0] 而不是 $('head')[0]; textNode 而不是 $(textNode)[0]【参考方案3】:

我找到了上述解决方案,以防止带有 Google 地图的网站加载 Roboto。

如果您 - 像我一样 - 使用 Wordpress,可能会有其他插件引用 Google 字体。

但是,我在使用上述代码的一些网站上遇到了困难,因为它的某些部分 (1) 也影响了其他要加载的样式,(2) “杀死”的样式,它故意不仅包含 gm 样式,还包含其他样式样式以及 (3) 不影响其他 Google 字体的加载,其中一个或另一个插件也通过 DOM 操作添加了指向 fonts.googleapis.com 的链接。

以下内容对我有用。它只是阻止其他脚本在其 href 属性中添加任何带有 https://fonts.googleapis.com 的标签。

(function($) 
var isGoogleFont = function (element) 
    // google font download
    if (element.href
        && element.href.indexOf('https://fonts.googleapis.com') === 0) 
        return true;
           
    return false;


// we override these methods only for one particular head element
// default methods for other elements are not affected
var head = $('head')[0];

var insertBefore = head.insertBefore;
head.insertBefore = function (newElement, referenceElement) 
    if (!isGoogleFont(newElement)) 
        insertBefore.call(head, newElement, referenceElement);
    
;

var appendChild = head.appendChild;
head.appendChild = function (textNode) 
    if (!isGoogleFont($(textNode)[0])) 
        appendChild.call(head, textNode);
    
;
)(jQuery);

【讨论】:

首先感谢您的代码。不幸的是,我无法让它发挥作用。当我将它添加到我的子主题的functions.php 文件时,它说:“语法错误,意外'$',期望变量(T_VARIABLE)”,我无法保存文件。知道为什么它不接受 $?

以上是关于Google Maps v3 - 防止 API 加载 Roboto 字体的主要内容,如果未能解决你的问题,请参考以下文章

google maps js v3 api教程 -- 在地图上添加标记

Google Maps API V3 错误:RefererDeniedMapError

google maps js v3 api教程 -- 创建一个地图

JavaScript Google Maps API V3 Javascript基本示例

JavaScript Google Maps API V3 Javascript完整示例

在 Google Maps API v3 中删除标记