谷歌地图v3 - 防止API加载Roboto字体

46

Google会给地图容器添加样式,覆盖了我的样式。
我知道如何解决这个问题。但 API (v3.8 / 9 / exp)还会加载我不太需要/想要的网络字体“Roboto”。

有没有设置/选项/方法可以解决这个问题?
我能否阻止 API 添加额外的 CSS?

这是 Google 地图 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>

这是输出吗?很难确定代码自身在引用什么。 - Josh Burgess
@JoshBurgess 是的,这就是在包含 maps-api-javascript 时 Google 添加到 <head> 的内容。 - Philipp Kyeck
除了使用旧版本的gmapsAPI,我找不到阻止Roboto进入的方法,除非从Apache、IIS或您正在使用的任何等效服务器上阻止对该域的请求。如果这足够的话,我会把它放在答案中,但对我来说似乎有点投降。 - Josh Burgess
@pkyeck,看这里!它正在工作! - coma
@coma 好的,谢谢。 - Philipp Kyeck
5个回答

80

在谷歌脚本调用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选项,但这个“hack”绝对可行 :) - Philipp Kyeck
我在他们的文档中没有找到任何信息,猜测他们想保留其风格。顺便说一下,一旦防止字体加载,您可以恢复更改以跳过每个insertBefore调用。 - coma
非常感谢!对我有用。 - Seeker
4
或者使用newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') !== -1,这个方法适用于http和https。 - Salaros
5
如果地图使用iframe嵌入,则此解决方案无法使用,因为Roboto字体是通过在iframe文档的头部使用css调用加载的,而无法访问该调用。对此有什么提示吗? - Steve
显示剩余5条评论

15

更新 2017年10月

谷歌更改了注入页面样式的方式。现在他们插入一个空的style元素,然后使用机器字体更改该样式元素的内容。这里提供一个新的解决方案:

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

1
非常精彩,非常感谢。您可以轻松地省略两个jQuery引用,这样它就可供任何人使用:将 $('head')[0]; 替换为 document.getElementsByTagName('head')[0]; 将 $(textNode)[0] 替换为 textNode - Vincent Sels

2

对于TypeScript,一个解决方案是:

const head = document.head;
const insertBefore = head.insertBefore;
head.insertBefore = <T extends Node>(
  newElement: T,
  referenceElement: Node
): T => {
  if (
    newElement instanceof Element &&
    newElement?.hasAttribute('href') &&
    newElement?.getAttribute('href')?.includes('fonts.googleapis')
  ) {
    return newElement;
  }

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

0
我发现了上述解决方案,可以防止加载Roboto字体的谷歌地图网站。
如果您像我一样使用WordPress,则可能会有其他插件引用Google字体。
然而,对于我的某些网站,上述代码存在以下问题:(1) 影响其他样式的加载;(2) "杀死"意图不仅包含gm-style,而且包含其他样式的样式; (3) 不影响其他Google字体的加载,其中一个或另一个插件也通过DOM操作添加了链接到fonts.googleapis.com。
以下是适用于我的代码。它只是简单地防止其他脚本添加任何带有https://fonts.googleapis.com的标记到其href属性中。
(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)”,我无法保存该文件。有任何想法为什么它不接受$? - Mario
@Mario 在顶部添加 var $ = jQuery.noConflict();,这样应该就可以解决你的问题了。 - AuRise

0

很不幸,我是一个新手,我无法让其他建议起作用。所以我从DOM中删除了所有Google字体。希望这有所帮助。

const googleFont = document.querySelector('link[rel="stylesheet"][href*="fonts.googleapis.com"]');
    if (googleFont) {
      googleFont.remove();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接