web-dev-qa-db-fra.com

Utilisation de polices personnalisées dans WKWebView

J'utilise des polices personnalisées dans mon application. Ils sont copiés en bundle et codés en dur dans appName-info.plist. Ces polices fonctionnent parfaitement dans toute l'application et dans UIWebView.

Im chargement de htmlString [webView loadHTMLString:htmlString baseURL:nil]; J'utilise ces polices dans webView avec css: fontFamily: fontName

Mais lorsque j'essaie d'utiliser des polices personnalisées WkWebView ne fonctionnant pas. WkWebView affiche des polices par défaut aléatoires.

J'ai essayé de le charger avec le chemin du bundle principal dans l'url de base et en utilisant font-face en css - WkWebView affiche toujours des polices aléatoires.

Des idées sur la façon de faire fonctionner les polices personnalisées dans WKWebView?

Désolé pour mon anglais

51
Sashke

J'ai rencontré le même problème, dans mon cas, je pouvais le résoudre [~ # ~] sans [~ # ~] en utilisant encodage base64 et GCDWebServer .

Scénario:

  • Le chargement de WkWebView s'effectue via une chaîne html
  • WkWebView utilise .css local
  • Les polices sont locales et ajoutées au projet de niveau supérieur
  • Les entrées pour les polices sont fournies dans appName-info.plist sous la clé Fonts provided by application

Solution:

Ajoutez le visage de police dans .css au niveau supérieur comme suit

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

PROJET DEMO:

Lien du projet GitHub

[~ # ~] note [~ # ~] : La nouvelle application de démonstration peut prendre 2 à 3 secondes, je l'ai testée pour une longue chaîne html, fonctionne de la même manière que UIWebView, pas de décalage. La même police peut sembler un peu plus petite dans WKWebView que dans UIWebView.

36
Aditya Deshmane

En supposant que vous incorporiez la police dans votre application en tant que ressource copiée dans le groupe cible, vous pouvez donner à WKWebView l'accès à la police en passant une NSURL à son dossier comme baseURL

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

et définir l'url de la police sans aucun élément de chemin précédent, ce qui fait que WKWebKit ajoute le baseURL

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

Comme je ne veux pas utiliser un autre tiers juste pour cela et que je construis la chaîne html elle-même, j'ai pris la première partie de l'utilisation de la police et au lieu d'utiliser une URL vers un fichier distant ou local, je converti les polices en base64.

Le CSS ressemble à ceci:

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

Vous pouvez remplacer le FONTFAMILY par la famille dont vous avez besoin et le FONTBASE64 par la chaîne de base 64 générée à partir de la police.

Si vous avez besoin de créer la chaîne base64 dans votre application, vous pouvez l'utiliser, il suffit de fournir le nom de fichier et le type (je l'ai également utilisé pour obtenir d'autres fichiers, il est donc plus générique, vous pouvez supprimer le paramètre ofType et utiliser @ "ttf" au lieu):

- (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;
}

si vous ne voulez le faire qu'une seule fois puis l'enregistrer dans un fichier, vous pouvez utiliser n'importe lequel des sites Web en ligne qui convertit les fichiers en base64, comme ceci: http://www.opinionatedgeek.com/dotnet/ tools/base64encode /

20
kalsky

Je suppose que le WKWebView ne peut plus accéder aux polices spécifiques à l'application, car il est maintenant dans un processus distinct (XPC).

J'ai contourné cela en ajoutant la police avec les déclarations @font-face En CSS. Voir ici pour plus de détails sur MDN sur la façon de procéder.

Exemple:

@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;
}

Mais cela va référencer un fichier local, ce que le WKWebView ne peut pas faire (je suppose que vous l'avez déjà découvert parce que vous chargez une chaîne HTML au lieu du fichier local). Selon un commentaire sur cette question , j'ai pu utiliser GCDWebServer pour faire fonctionner mon fichier HTML local. Dans votre délégué d'application, après avoir ajouté les fichiers pertinents à votre projet selon le wiki de GCDWebServer sur GitHub:

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];

Vous pouvez maintenant référencer un fichier HTML nommé test.html Dans votre bundle comme ceci:

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

Mettez la déclaration @font-face Susmentionnée dans un élément style dans votre fichier HTML (ou dans votre chaîne HTML si vous avez vraiment besoin de charger une chaîne) et vous devriez être prêt à partir.

9
Tom Hamming

Voici une Swift 3 version de @Henrik Hartz réponse impressionnante:

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