Ei kuvausta

AAChartView.m 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. //
  2. // AAChartView.m
  3. // AAChartKit
  4. //
  5. // Created by An An on 17/1/16.
  6. // Copyright © 2017年 An An. All rights reserved.
  7. //*************** ...... SOURCE CODE ...... ***************
  8. //***...................................................***
  9. //*** https://github.com/AAChartModel/AAChartKit ***
  10. //*** https://github.com/AAChartModel/AAChartKit-Swift ***
  11. //***...................................................***
  12. //*************** ...... SOURCE CODE ...... ***************
  13. /*
  14. * -------------------------------------------------------------------------------
  15. *
  16. * 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
  17. *
  18. * Please contact me on GitHub,if there are any problems encountered in use.
  19. * GitHub Issues : https://github.com/AAChartModel/AAChartKit/issues
  20. * ------------------------------------------------------------------------------
  21. * And if you want to contribute for this project, please contact me as well
  22. * GitHub : https://github.com/AAChartModel
  23. * StackOverflow : https://stackoverflow.com/users/7842508/codeforu
  24. * JianShu : http://www.jianshu.com/u/f1e6753d4254
  25. * SegmentFault : https://segmentfault.com/u/huanghunbieguan
  26. *
  27. * -------------------------------------------------------------------------------
  28. */
  29. #import "AAChartView.h"
  30. #import <WebKit/WebKit.h>
  31. /**
  32. * Get the system version number
  33. */
  34. #define AASYSTEM_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]
  35. /**
  36. * The console output log
  37. */
  38. #ifdef DEBUG // Debug status, open the LOG function
  39. #define AADetailLog(fmt, ...) NSLog((@"-------> %@ [Line %d] \n"fmt "\n\n"), [[NSString stringWithFormat:@"%s",__FILE__] lastPathComponent], __LINE__, ##__VA_ARGS__);
  40. #else // Release status, turn off the LOG function
  41. #define AADetailLog(...)
  42. #endif
  43. #define kDevice_Is_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
  44. @interface AAChartView()<WKNavigationDelegate,UIWebViewDelegate> {
  45. UIWebView *_uiWebView;
  46. WKWebView *_wkWebView;
  47. NSString *_optionJson;
  48. }
  49. @end
  50. @implementation AAChartView
  51. - (instancetype)initWithFrame:(CGRect)frame {
  52. self = [super initWithFrame:frame];
  53. if (self) {
  54. [self setUpBasicWebView];
  55. }
  56. return self;
  57. }
  58. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  59. self = [super initWithCoder:aDecoder];
  60. if (self) {
  61. [self setUpBasicWebView];
  62. }
  63. return self;
  64. }
  65. - (void)setUpBasicWebView {
  66. if (AASYSTEM_VERSION >= 9.0) {
  67. _wkWebView = [[WKWebView alloc] init];
  68. _wkWebView.navigationDelegate = self;
  69. _wkWebView.backgroundColor = [UIColor whiteColor];
  70. [self addSubview:_wkWebView];
  71. _wkWebView.translatesAutoresizingMaskIntoConstraints = NO;
  72. [self addConstraints:[self configureTheConstraintArrayWithItem:_wkWebView toItem:self]];
  73. } else {
  74. _uiWebView = [[UIWebView alloc] init];
  75. _uiWebView.delegate = self;
  76. _uiWebView.backgroundColor = [UIColor whiteColor];
  77. [self addSubview:_uiWebView];
  78. _uiWebView.translatesAutoresizingMaskIntoConstraints = NO;
  79. [self addConstraints:[self configureTheConstraintArrayWithItem:_uiWebView toItem:self]];
  80. }
  81. }
  82. - (NSArray *)configureTheConstraintArrayWithItem:(UIView *)childView toItem:(UIView *)fatherView{
  83. return @[[NSLayoutConstraint constraintWithItem:childView
  84. attribute:NSLayoutAttributeLeft
  85. relatedBy:NSLayoutRelationEqual
  86. toItem:fatherView
  87. attribute:NSLayoutAttributeLeft
  88. multiplier:1.0
  89. constant:0],
  90. [NSLayoutConstraint constraintWithItem:childView
  91. attribute:NSLayoutAttributeRight
  92. relatedBy:NSLayoutRelationEqual
  93. toItem:fatherView
  94. attribute:NSLayoutAttributeRight
  95. multiplier:1.0
  96. constant:0],
  97. [NSLayoutConstraint constraintWithItem:childView
  98. attribute:NSLayoutAttributeTop
  99. relatedBy:NSLayoutRelationEqual
  100. toItem:fatherView
  101. attribute:NSLayoutAttributeTop
  102. multiplier:1.0
  103. constant:0],
  104. [NSLayoutConstraint constraintWithItem:childView
  105. attribute:NSLayoutAttributeBottom
  106. relatedBy:NSLayoutRelationEqual
  107. toItem:fatherView
  108. attribute:NSLayoutAttributeBottom
  109. multiplier:1.0
  110. constant:0],
  111. ];
  112. }
  113. - (NSURLRequest *)getJavaScriptFileURLRequest {
  114. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  115. NSString *webPath = [bundle pathForResource:@"AAChartView" ofType:@"html" inDirectory:@"AAJSFiles.bundle"];
  116. NSURL *webURL = [NSURL fileURLWithPath:webPath];
  117. NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:webURL];
  118. return URLRequest;
  119. }
  120. - (void)configureTheOptionsJsonStringWithAAOptions:(AAOptions *)options {
  121. if (self.isClearBackgroundColor == YES) {
  122. options.chart.backgroundColor = @"rgba(0,0,0,0)";
  123. }
  124. _optionJson = [AAJsonConverter getPureOptionsString:options];
  125. }
  126. - (NSString *)configTheJavaScriptString {
  127. CGFloat chartViewContentWidth = self.contentWidth;
  128. CGFloat contentHeight = self.frame.size.height;
  129. if (kDevice_Is_iPhoneX == YES) {
  130. contentHeight = contentHeight - 20;
  131. }
  132. CGFloat chartViewContentHeight = self.contentHeight == 0 ? contentHeight : self.contentHeight;
  133. NSString *javaScriptStr = [NSString stringWithFormat:@"loadTheHighChartView('%@','%@','%@')",
  134. _optionJson,
  135. [NSNumber numberWithFloat:chartViewContentWidth],
  136. [NSNumber numberWithFloat:chartViewContentHeight-1]];
  137. return javaScriptStr;
  138. }
  139. //***********************CONFIGURE THE CHART VIEW CONTENT WITH `AACHARTMODEL`***********************//
  140. //
  141. - (void)aa_drawChartWithChartModel:(AAChartModel *)chartModel {
  142. AAOptions *options = [AAOptionsConstructor configureChartOptionsWithAAChartModel:chartModel];
  143. [self aa_drawChartWithOptions:options];
  144. }
  145. - (void)aa_refreshChartWithChartModel:(AAChartModel *)chartModel {
  146. AAOptions *options = [AAOptionsConstructor configureChartOptionsWithAAChartModel:chartModel];
  147. [self aa_refreshChartWithOptions:options];
  148. }
  149. - (void)aa_onlyRefreshTheChartDataWithChartModelSeries:(NSArray<NSDictionary *> *)series {
  150. [self aa_onlyRefreshTheChartDataWithOptionsSeries:series];
  151. }
  152. //
  153. //***********************CONFIGURE THE CHART VIEW CONTENT WITH `AACHARTMODEL`***********************//
  154. //=======================CONFIGURE THE CHART VIEW CONTENT WITH `AAOPTIONS`=======================//
  155. //
  156. - (void)aa_drawChartWithOptions:(AAOptions *)options {
  157. if (!_optionJson) {
  158. [self configureTheOptionsJsonStringWithAAOptions:options];
  159. NSURLRequest *URLRequest = [self getJavaScriptFileURLRequest];
  160. if (AASYSTEM_VERSION >= 9.0) {
  161. [_wkWebView loadRequest:URLRequest];
  162. } else {
  163. [_uiWebView loadRequest:URLRequest];
  164. }
  165. } else {
  166. [self aa_refreshChartWithOptions:options];
  167. }
  168. }
  169. - (void)aa_refreshChartWithOptions:(AAOptions *)options {
  170. [self configureTheOptionsJsonStringWithAAOptions:options];
  171. [self drawChart];
  172. }
  173. - (void)aa_onlyRefreshTheChartDataWithOptionsSeries:(NSArray<NSDictionary *> *)series {
  174. NSString *seriesJsonStr = [AAJsonConverter getPureSeriesString:series];
  175. NSString *javaScriptStr = [NSString stringWithFormat:@"onlyRefreshTheChartDataWithSeries('%@')",seriesJsonStr];
  176. [self evaluateJavaScriptWithFunctionNameString:javaScriptStr];
  177. }
  178. //
  179. //=======================CONFIGURE THE CHART VIEW CONTENT WITH `AAOPTIONS`=======================//
  180. - (void)drawChart {
  181. NSString *javaScriptStr = [self configTheJavaScriptString];
  182. [self evaluateJavaScriptWithFunctionNameString:javaScriptStr];
  183. }
  184. ///WKWebView did finish load
  185. - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
  186. [self drawChart];
  187. [self.delegate AAChartViewDidFinishLoad];
  188. }
  189. //UIWebView did finish load
  190. - (void)webViewDidFinishLoad:(UIWebView *)webView {
  191. [self drawChart];
  192. [self.delegate AAChartViewDidFinishLoad];
  193. }
  194. - (void)aa_showTheSeriesElementContentWithSeriesElementIndex:(NSInteger)elementIndex {
  195. NSString *javaScriptStr = [NSString stringWithFormat:@"showTheSeriesElementContentWithIndex(%ld)",(long)elementIndex];
  196. [self evaluateJavaScriptWithFunctionNameString:javaScriptStr];
  197. }
  198. - (void)aa_hideTheSeriesElementContentWithSeriesElementIndex:(NSInteger)elementIndex {
  199. NSString *javaScriptStr = [NSString stringWithFormat:@"hideTheSeriesElementContentWithIndex(%ld)",(long)elementIndex];
  200. [self evaluateJavaScriptWithFunctionNameString:javaScriptStr];
  201. }
  202. - (void)evaluateJavaScriptWithFunctionNameString:(NSString *)functionNameStr {
  203. if (AASYSTEM_VERSION >= 9.0) {
  204. [_wkWebView evaluateJavaScript:functionNameStr completionHandler:^(id item, NSError * _Nullable error) {
  205. if (error) {
  206. AADetailLog(@"☠️☠️💀☠️☠️WARNING!!!!! THERE ARE SOME ERROR INFOMATION_______%@",error);
  207. }
  208. }];
  209. } else {
  210. [_uiWebView stringByEvaluatingJavaScriptFromString:functionNameStr];
  211. }
  212. }
  213. #pragma mark -- setter method
  214. - (void)setScrollEnabled:(BOOL)scrollEnabled {
  215. _scrollEnabled = scrollEnabled;
  216. if (AASYSTEM_VERSION >= 9.0) {
  217. _wkWebView.scrollView.scrollEnabled = _scrollEnabled;
  218. } else {
  219. _uiWebView.scrollView.scrollEnabled = _scrollEnabled;
  220. }
  221. }
  222. - (void)setContentWidth:(CGFloat)contentWidth {
  223. _contentWidth = contentWidth;
  224. NSString *javaScriptStr = [NSString stringWithFormat:@"setTheChartViewContentWidth(%f)",_contentWidth];
  225. [self evaluateJavaScriptWithSetterMethodNameString:javaScriptStr];
  226. }
  227. - (void)setContentHeight:(CGFloat)contentHeight {
  228. _contentHeight = contentHeight;
  229. NSString *javaScriptStr = [NSString stringWithFormat:@"setTheChartViewContentHeight(%f)",_contentHeight];
  230. [self evaluateJavaScriptWithSetterMethodNameString:javaScriptStr];
  231. }
  232. - (void)setChartSeriesHidden:(BOOL)chartSeriesHidden {
  233. _chartSeriesHidden = chartSeriesHidden;
  234. NSString *jsStr = [NSString stringWithFormat:@"setChartSeriesHidden(%d)",_chartSeriesHidden];
  235. [self evaluateJavaScriptWithSetterMethodNameString:jsStr];
  236. }
  237. - (void)evaluateJavaScriptWithSetterMethodNameString:(NSString *)JSFunctionStr {
  238. if (_optionJson) {
  239. [self evaluateJavaScriptWithFunctionNameString:JSFunctionStr];
  240. }
  241. }
  242. - (void)setIsClearBackgroundColor:(BOOL)isClearBackgroundColor {
  243. _isClearBackgroundColor = isClearBackgroundColor;
  244. if (_isClearBackgroundColor == YES) {
  245. self.backgroundColor = [UIColor clearColor];
  246. if (AASYSTEM_VERSION >= 9.0) {
  247. [_wkWebView setBackgroundColor:[UIColor clearColor]];
  248. [_wkWebView setOpaque:NO];
  249. } else {
  250. [_uiWebView setBackgroundColor:[UIColor clearColor]];
  251. [_uiWebView setOpaque:NO];
  252. }
  253. }
  254. }
  255. - (void)setBlurEffectEnabled:(BOOL)blurEffectEnabled {
  256. _blurEffectEnabled = blurEffectEnabled;
  257. if (_blurEffectEnabled) {
  258. UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
  259. UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
  260. [self addSubview:effectView];
  261. [self sendSubviewToBack:effectView];
  262. effectView.translatesAutoresizingMaskIntoConstraints = NO;
  263. [self addConstraints:[self configureTheConstraintArrayWithItem:effectView toItem:self]];
  264. }
  265. }
  266. @end
  267. #import <objc/runtime.h>
  268. @implementation AAJsonConverter
  269. + (NSDictionary*)getObjectData:(id)obj {
  270. NSMutableDictionary *dic = [NSMutableDictionary dictionary];
  271. unsigned int propsCount;
  272. Class class = [obj class];
  273. do {
  274. objc_property_t *props = class_copyPropertyList(class, &propsCount);
  275. for (int i = 0;i < propsCount; i++) {
  276. objc_property_t prop = props[i];
  277. NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];
  278. id value = [obj valueForKey:propName];
  279. if (value == nil) {
  280. value = [NSNull null];
  281. continue;
  282. } else {
  283. value = [self getObjectInternal:value];
  284. }
  285. [dic setObject:value forKey:propName];
  286. }
  287. free(props);
  288. class = [class superclass];
  289. } while (class != [NSObject class]);
  290. return dic;
  291. }
  292. + (NSData*)getJSON:(id)obj options:(NSJSONWritingOptions)options error:(NSError**)error {
  293. return [NSJSONSerialization dataWithJSONObject:[self getObjectData:obj] options:options error:error];
  294. }
  295. + (id)getObjectInternal:(id)obj {
  296. if ( [obj isKindOfClass:[NSString class]]
  297. || [obj isKindOfClass:[NSNumber class]]
  298. || [obj isKindOfClass:[NSNull class]] ) {
  299. return obj;
  300. }
  301. if ([obj isKindOfClass:[NSArray class]]) {
  302. NSArray *objarr = obj;
  303. NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count];
  304. for (int i = 0;i < objarr.count; i++) {
  305. [arr setObject:[self getObjectInternal:[objarr objectAtIndex:i]] atIndexedSubscript:i];
  306. }
  307. return arr;
  308. }
  309. if ([obj isKindOfClass:[NSDictionary class]]) {
  310. NSDictionary *objdic = obj;
  311. NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]];
  312. for (NSString *key in objdic.allKeys) {
  313. [dic setObject:[self getObjectInternal:[objdic objectForKey:key]] forKey:key];
  314. }
  315. return dic;
  316. }
  317. return [self getObjectData:obj];
  318. }
  319. + (NSString*)convertDictionaryIntoJson:(NSDictionary *)dictionary {
  320. NSError *parseError = nil;
  321. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&parseError];
  322. NSString *string =[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  323. return string;
  324. }
  325. + (NSString*)wipeOffTheLineBreakAndBlankCharacter:(NSString *)originalString {
  326. NSString *str =[originalString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  327. str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  328. return str;
  329. }
  330. + (NSString *)getPureOptionsString:(id)optionsObject {
  331. NSDictionary *dic;
  332. if ([optionsObject isKindOfClass:[NSDictionary class]] ) {
  333. dic = optionsObject;
  334. } else {
  335. dic = [self getObjectData:optionsObject];
  336. }
  337. NSString *str = [self convertDictionaryIntoJson:dic];
  338. return [self wipeOffTheLineBreakAndBlankCharacter:str];
  339. }
  340. + (NSString *)getPureSeriesString:(NSArray<NSDictionary*> *)series {
  341. NSError *parseError = nil;
  342. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:series options:NSJSONWritingPrettyPrinted error:&parseError];
  343. NSString *seriesStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  344. return [self wipeOffTheLineBreakAndBlankCharacter:seriesStr];
  345. }
  346. @end