CSS 在 WKWebView 中使用自定义字体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25785179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 02:35:15  来源:igfitidea点击:

Using custom fonts in WKWebView

ioscssfontsuiwebviewwkwebview

提问by Sashke

I'm using custom fonts in my app. They are copied to bundle and hardcoded to appName-info.plist. This fonts works perfectly in the whole app and in UIWebView.

我在我的应用程序中使用自定义字体。它们被复制到 bundle 并硬编码到 appName-info.plist。这种字体在整个应用程序和 UIWebView 中都可以完美运行。

Im loading htmlString [webView loadHTMLString:htmlString baseURL:nil];I use this fonts in webView with css: fontFamily: fontName

我正在加载 htmlString [webView loadHTMLString:htmlString baseURL:nil];我在带有 css 的 webView 中使用这种字体: fontFamily: fontName

But when i try to use WkWebView custom fonts not working. WkWebView displays random default fonts.

但是当我尝试使用 WkWebView 自定义字体时,它不起作用。WkWebView 显示随机的默认字体。

I tried to load it with main bundle path in base url and using font-face in css - WkWebView still displays random fonts.

我尝试使用基本 url 中的主包路径加载它,并在 css 中使用 font-face - WkWebView 仍然显示随机字体。

Any ideas how to make custom fonts work in WKWebView?

任何想法如何使自定义字体在 WKWebView 中工作?

Sorry for my english

对不起我的英语不好

回答by Aditya Deshmane

I faced same issue, in my case i could fix it WITHOUTusing base64 encodingand GCDWebServer.

我遇到了同样的问题,就我而言,我可以在使用base64 编码GCDWebServer 的情况下修复它。

Scenario:

设想:

  • WkWebView loading is through string html
  • WkWebView is using local .css
  • Fonts are local and are added at top level project
  • Entries for fonts are provided in appName-info.plist under key Fonts provided by application
  • WkWebView 加载是通过字符串 html
  • WkWebView 正在使用本地 .css
  • 字体是本地的,并在顶级项目中添加
  • 字体条目在 appName-info.plist 中的 key 下提供 Fonts provided by application


Solution:

解决方案:

Add font face in .css at top level as follows

在顶层.css中添加字体如下

@font-face
{
    font-family: 'FontFamily';
    src: local('FontFamily'),url('FontFileName.otf') format('opentype');
}


DEMO PROJECT:

演示项目:

GitHub Project Link

GitHub 项目链接

NOTE: Fresh demo app run may take 2-3 sec, I have tested it for long html string it works same as UIWebView, no lags. Same font may look bit smaller in WKWebView than UIWebView.

注意:新的演示应用程序运行可能需要 2-3 秒,我已经测试了它的长 html 字符串,它的工作原理与 UIWebView 相同,没有延迟。WKWebView 中的相同字体可能看起来比 UIWebView 小一些。

回答by Henrik Hartz

Assuming you embed the font in your application as a resource that's copied to the target bundle, you can give the WKWebView access to the font by passing a NSURL to it's folder as the baseURL

假设您将字体作为复制到目标包的资源嵌入到应用程序中,您可以通过将 NSURL 作为 baseURL 传递到它的文件夹来让 WKWebView 访问字体

NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSURL *bundleUrl = [NSURL fileURLWithPath:bundlePath];
[self.webView loadHTMLString:HTML baseURL:bundleUrl];

and define the font-face url without any preceeding path elements, which in turn makes WKWebKit prepend the baseURL

并定义没有任何前面路径元素的 font-face url,这反过来使 WKWebKit 在 baseURL 前面

<style>
  @font-face { font-family: 'Custom Font'; src: url('CustomFont.ttf'); }
  ...
</style>

回答by kalsky

Since I don't want to use another third party just for that and since I'm building the html string itself, I took the first part of using the font-face and instead of using a url to a remote or local file, i converted the fonts to base64.

由于我不想为此使用另一个第三方,并且由于我正在构建 html 字符串本身,因此我使用了 font-face 的第一部分,而不是使用远程或本地文件的 url,我将字体转换为 base64。

The css looks like this:

css 看起来是这样的:

@font-face {
    font-family: 'FONTFAMILY';
    src: url(data:font/ttf;base64,FONTBASE64) format('truetype');
}

You can replace the FONTFAMILY with the family that you need and the FONTBASE64 with the base 64 string that was generated from the font.

您可以将 FONTFAMILY 替换为您需要的系列,并将 FONTBASE64 替换为从字体生成的 base 64 字符串。

If you need to create the base64 string in your application, you can use this, just provide the filename and type (i used it to get other files as well so it's more generic, you can remove the ofType parameter and use @"ttf" instead):

如果您需要在应用程序中创建 base64 字符串,您可以使用它,只需提供文件名和类型(我也用它来获取其他文件,因此它更通用,您可以删除 ofType 参数并使用 @"ttf"反而):

- (NSString*)getBase64FromFile:(NSString*)fileName ofType:(NSString*)type
{
    NSString * filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:type];

    // Create NSData object
    NSData *nsdata = [NSData dataWithContentsOfFile:filePath];

    // Get NSString from NSData object in Base64
    NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];

    return base64Encoded;
}

if you want to do it only one time and then save it in some file, you can use any of the online websites that converts files to base64, like this: http://www.opinionatedgeek.com/dotnet/tools/base64encode/

如果您只想执行一次然后将其保存在某个文件中,您可以使用任何将文件转换为 base64 的在线网站,如下所示:http: //www.opinionatedgeek.com/dotnet/tools/base64encode/

回答by Tom Hamming

Update:This is now possible using WKURLSchemeHandler.

更新:现在可以使用WKURLSchemeHandler.

@interface MySchemeHandler : NSObject <WKURLSchemeHandler>
@end

@implementation MySchemeHandler

- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask
{
  NSURL *url = urlSchemeTask.request.URL;
  NSString *mimeType = [NSString stringWithFormat:@"text/%@", url.pathExtension]; //or whatever you need
  NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:mimeType expectedContentLength:-1 textEncodingName:nil];
  [urlSchemeTask didReceiveResponse:response];
  NSData *data = [self getResponseData];
  [urlSchemeTask didReceiveData:data];
  [urlSchemeTask didFinish];
}
@end

And when configuring your WKWebViewinstance:

在配置您的WKWebView实例时:

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
MySchemeHandler *handler = [[MySchemeHandler alloc] init];
[config setURLSchemeHandler:handler forURLScheme:@"myScheme"];
//now pass the config to your WKWebView

------Old answer----------

------旧答案----------

My guess is that the WKWebViewcan no longer access fonts specific to the application because it's now in a separate process (XPC).

我的猜测是WKWebView无法再访问特定于应用程序的字体,因为它现在处于单独的进程 (XPC) 中。

I got around this by adding the font with @font-facedeclarations in CSS. See herefor details on MDN about how to do this.

我通过@font-face在 CSS 中添加带有声明的字体来解决这个问题。有关如何执行此操作的 MDN 的详细信息,请参见此处

Example:

例子:

@font-face
{
  font-family: "MyFontFace";
  src:url('url-to-font.ttf');
}

//And if you have a font with files with different variants, add this:
@font-face
{
  font-family: "MyFontFace";
  src:url('url-to-italic-variant.ttf');
  font-style:italic;
}

But this is going to reference a local file, which the WKWebViewcan't do (I assume you've already discovered this because you're loading an HTML string instead of the local file). As per a comment on this question, I was able to use GCDWebServerto get my local HTML file working. In your app delegate, after adding the relevant files to your project as per the GCDWebServer's wiki on GitHub:

但这将引用一个本地文件,这是WKWebView不能做到的(我假设您已经发现了这一点,因为您正在加载一个 HTML 字符串而不是本地文件)。根据对这个问题的评论,我能够使用GCDWebServer来让我的本地 HTML 文件工作。在您的应用程序委托中,根据 GitHub 上的 GCDWebServer 维基将相关文件添加到您的项目后:

GCDWebServer *server = [[[GCDWebServer alloc]init]autorelease];
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
[server addGETHandlerForBasePath:@"/"
   directoryPath:bundlePath indexFilename:nil
   cacheAge:0 allowRangeRequests:YES];
[server startWithPort:8080 bonjourName:nil];

Now you can reference an HTML file named test.htmlin your bundle like this:

现在,您可以test.html像这样引用包中命名的 HTML 文件:

NSString *path = @"http://localhost:8080/test.html";
NSURL *url = [NSURL URLWithString:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[myWebView loadRequest:request];

Put the aforementioned @font-facedeclaration in a styleelement in your HTML file (or in your HTML string if you really just need to load a string) and you should be good to go.

将上述@font-face声明放在styleHTML 文件的元素中(或者如果您真的只需要加载一个字符串,则放在您的 HTML 字符串中),您应该很高兴。

回答by Dorad

Here is a swift 3 version of @Henrik Hartz awesome answer:

这是@Henrik Hartz 很棒的答案的 swift 3 版本:

loadHTMLString(htmlString, baseURL: NSURL.fileURL(withPath: Bundle.main.bundlePath))