首页 > 其他分享 >iOS借用WKWebView将svg转码为png

iOS借用WKWebView将svg转码为png

时间:2023-03-20 12:23:07浏览次数:60  
标签:imageDataArray complete nil 转码 svg self iOS error webView

#import "WKSVGConvert.h"
#import <WebKit/WebKit.h>

@interface WKSVGConvert ()
<WKNavigationDelegate>

@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, copy) WKSVGConvertDataCallback waitCallback;

@end

@implementation WKSVGConvert

- (instancetype)init {
    self = [super init];
    if (self) {
        self.webView = [WKWebView new];
        self.webView.navigationDelegate = self;
    }
    return self;
}

- (void)doCallback:(NSError *)error imageDataArray:(NSArray<NSData *> *)imageDataArray {
    [self callback:self.waitCallback error:error imageDataArray:imageDataArray];
}

- (void)callback:(WKSVGConvertDataCallback)callback error:(NSError *)error imageDataArray:(NSArray<NSData *> *)imageDataArray {
    WKSVGConvertDataCallback aCallback = callback;
    if (aCallback) {
        dispatch_async(dispatch_get_main_queue(), ^{
            aCallback(error, imageDataArray);
        });
    }
}

- (void)convertSvgData2Png:(NSArray<NSData *> *)svgDataArray complete:(WKSVGConvertImageCallback)complete {
    [self convertSvgData:svgDataArray complete:complete ? ^(NSError * _Nullable error, NSArray<NSData *> * _Nonnull pictureDataArray) {
        if (error) {
            complete(error, nil);
        } else {
            NSMutableArray<UIImage *> *imageArray = [NSMutableArray array];
            for (NSData *data in pictureDataArray) {
                UIImage *image = [UIImage imageWithData:data];
                [imageArray addObject:image ?: [UIImage new]];
            }
            complete(nil, imageArray);
        }
    } : nil];
}
- (void)convertSvgData:(NSArray<NSData *> *)svgDataArray complete:(WKSVGConvertDataCallback)complete {
    WKSVGConvertDataCallback callback = self.waitCallback;
    NSString *htmlString = [self urlStringForLoadingSvgData:svgDataArray];
    self.waitCallback = complete;
    [self.webView loadHTMLString:htmlString baseURL:nil];
    [self callback:callback error:[NSError errorWithDomain:@"Canceled" code:kCFURLErrorCancelled userInfo:nil] imageDataArray:nil];
}

- (NSString *)urlStringForLoadingSvgData:(NSArray<NSData *> *)svgDataArray {
    NSMutableString *htmlString = [NSMutableString stringWithString:@" \
    <html> \
    <head> \
    </head> \
    <body>"];
    for (NSData *svgData in svgDataArray) {
        NSString *base64Svg = [svgData base64EncodedStringWithOptions:kNilOptions];
        [htmlString appendFormat:@" \
         <img src='data:image/svg+xml;base64,%@'> \
         ", base64Svg];
    }
    [htmlString appendString:@"\
     </body> \
     </html> \
    "];
    return htmlString.copy;
}

- (NSString *)javaScriptForRequestPngData {
    return @"\
           function imagePngData() { \
              var imageArray = document.getElementsByTagName('img'); \
              var pngArray = new Array(); \
              for (var index =0; index < imageArray.length; index++) { \
                  var image = imageArray[index]; \
                  var canvas = document.createElement('canvas'); \
                  canvas.width = image.width; \
                  canvas.height = image.height; \
                  var context = canvas.getContext('2d'); \
                  context.drawImage(image, 0, 0); \
                  pngArray.push(canvas.toDataURL('image/png')) \
              } \
              return pngArray; \
           } \
           imagePngData()";
}

- (void)requestSvg2PngDataByJavaScript {
    __weak typeof(self) weakSelf = self;
    [self.webView evaluateJavaScript:[self javaScriptForRequestPngData] completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (error) {
            [strongSelf doCallback:error imageDataArray:nil];
            return;
        }
        if (!result || ![result isKindOfClass:[NSArray class]]) {
            [strongSelf doCallback:[NSError errorWithDomain:@"Bad Response" code:kCFURLErrorBadServerResponse userInfo:nil] imageDataArray:nil];
            return;
        }
        NSString *pngPrefix = @"data:image/png;base64,";
        NSMutableArray<NSData *> *pngDataArray = [NSMutableArray array];
        for (NSString *pngBase64 in result) {
            if (![pngBase64 hasPrefix:pngPrefix]) {
                [pngDataArray addObject:[NSData data]];
            } else {
                NSString *base64String = [pngBase64 stringByReplacingCharactersInRange:NSMakeRange(0, pngPrefix.length) withString:@""];
                NSData *data = [[NSData alloc] initWithBase64EncodedString:base64String options:kNilOptions];
                [pngDataArray addObject:data ?: [NSData data]];
            }
        }
        [strongSelf doCallback:nil imageDataArray:pngDataArray];
    }];
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [self requestSvg2PngDataByJavaScript];
}

- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    [self doCallback:error imageDataArray:nil];
}


@end

 

标签:imageDataArray,complete,nil,转码,svg,self,iOS,error,webView
From: https://www.cnblogs.com/yuxiaoyiyou/p/17235859.html

相关文章

  • Vue全局挂载axios
    前言在vue开发过程中我们有时会把需要的一些模块挂载的全局,以便在各个组件或页面中使用。vue2与vue3中全局挂载是有一些不同的。一、全局挂载示例:pandas是基于NumPy的一......
  • Vue axios简易封装
    1.安装axiosnpminstallaxios-g 2.创建utils文件夹,新建文件request.js对axios进行封装3.设置请求超时通过axios.defaults.timeout设置默认的请求超时时间。例......
  • iOS之RunLoop - 前期准备:RunLoop运行逻辑
    什么是RunLoop1-RunLoop即运行循环:在程序运行中循环做一些事情2-RunLoop应用范围① 定时器(Timer)、PerformSelector② GCDAsyncMainQueue③ 事件响应、手......
  • 使用vue2+element-ui+axios实现后台管理系统的增删改查
    以下仅作为自己个人学习使用前言:需要后端的接口已经在另外一篇博客写了,需要的小伙伴们可以去那边参考,下面是链接https://www.cnblogs.com/Amyel/p/17233060.html正片......
  • 安装axios和二次封装
    [email protected] 二次封装:项目中新建api目录,及request.js//对于axios进行二次封测importaxiosfrom'axios';//1.利用axios读写的方法create,创......
  • Vue3 + go + axios 的前后端交互
    下载npminstallaxiosaxios全局配置创建一个js文件用于保存axios设置,配置文件自行搜索在main.js中使用保存好的axios设置```jsimportaxiosfrom'@/plugins/axi......
  • axios
    axiosaxios可以局部导入和全局导入首先要下载axios插件全局导入当把axios挂载到mainjs中,就是全局了,在其他的组件中就不需要再导入了①main.js导入axiosimportaxios......
  • H5下滑sectionScroll这个事件在ios实现执行一次
    H5下滑sectionScroll这个事件在ios实现执行一次H5下滑sectionScroll这个事在ios执行很多次:$$(document).on('infinite','#sectionScroll',function(){ if(loadi......
  • 用TS封装Axios遇到的奇怪问题
    按照王红元课程中的代码去封装,出现这个错误。//一、实例拦截器:从config中取出的拦截器是对应的实例的拦截器this.instance.interceptors.request.use(this.......
  • iostream,iostream.h,stdio.h的纠葛
    include<iostream.h>非标准输入输出流include标准输入输出流C++中为了避免名字定义冲突,特别引入了“名字空间的定义”,即namespace。当代码中用<iostream.h>时,输出可直......