cocoa绘制动态折线图代码,包含.h和.m文件
时间: 2023-12-14 10:03:32 浏览: 92
以下是一个简单的 Cocoa 绘制动态折线图的代码示例,包含 .h 和 .m 文件:
DynamicLineChart.h:
```objective-c
#import <Cocoa/Cocoa.h>
@interface DynamicLineChart : NSView
@property (nonatomic, strong) NSColor *lineColor; // 折线颜色
@property (nonatomic, assign) CGFloat lineWidth; // 折线宽度
@property (nonatomic, assign) CGFloat pointRadius; // 数据点半径
@property (nonatomic, assign) NSTimeInterval animationDuration; // 动画时长
- (void)addDataPoint:(CGFloat)dataPoint; // 添加一个数据点
@end
```
DynamicLineChart.m:
```objective-c
#import "DynamicLineChart.h"
@interface DynamicLineChart()
@property (nonatomic, strong) NSMutableArray *dataPoints; // 存储数据点的数组
@property (nonatomic, assign) CGFloat maxValue; // 数据最大值
@property (nonatomic, assign) CGFloat minValue; // 数据最小值
@property (nonatomic, assign) CGFloat valueRange; // 数据值范围
@end
@implementation DynamicLineChart
- (instancetype)initWithFrame:(NSRect)frameRect {
if (self = [super initWithFrame:frameRect]) {
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
[self setup];
}
return self;
}
- (void)setup {
self.dataPoints = [NSMutableArray array];
self.lineColor = [NSColor blackColor];
self.lineWidth = 2.0;
self.pointRadius = 3.0;
self.animationDuration = 0.5;
}
- (void)addDataPoint:(CGFloat)dataPoint {
// 将数据点添加到数组中
[self.dataPoints addObject:@(dataPoint)];
// 更新最大值和最小值
if (self.dataPoints.count == 1) {
self.maxValue = dataPoint;
self.minValue = dataPoint;
} else {
self.maxValue = MAX(dataPoint, self.maxValue);
self.minValue = MIN(dataPoint, self.minValue);
}
self.valueRange = self.maxValue - self.minValue;
// 刷新视图
[self setNeedsDisplay:YES];
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
if (self.dataPoints.count == 0) {
return;
}
// 绘制折线
NSBezierPath *path = [[NSBezierPath alloc] init];
[[self.lineColor colorWithAlphaComponent:0.8] set];
path.lineWidth = self.lineWidth;
CGFloat xInterval = self.bounds.size.width / (self.dataPoints.count - 1);
for (NSInteger i = 0; i < self.dataPoints.count; i++) {
CGFloat dataPoint = [self.dataPoints[i] floatValue];
CGFloat y = (dataPoint - self.minValue) / self.valueRange * self.bounds.size.height;
CGFloat x = i * xInterval;
if (i == 0) {
[path moveToPoint:CGPointMake(x, y)];
} else {
[path lineToPoint:CGPointMake(x, y)];
}
}
[path stroke];
// 绘制数据点
for (NSInteger i = 0; i < self.dataPoints.count; i++) {
CGFloat dataPoint = [self.dataPoints[i] floatValue];
CGFloat y = (dataPoint - self.minValue) / self.valueRange * self.bounds.size.height;
CGFloat x = i * xInterval;
NSRect pointRect = NSMakeRect(x - self.pointRadius, y - self.pointRadius, self.pointRadius * 2, self.pointRadius * 2);
NSBezierPath *pointPath = [NSBezierPath bezierPathWithOvalInRect:pointRect];
[[self.lineColor colorWithAlphaComponent:0.8] set];
[pointPath fill];
}
}
- (void)animate {
if (self.dataPoints.count == 0) {
return;
}
// 将视图高度缩小到 0
NSRect startRect = self.bounds;
NSRect endRect = NSMakeRect(startRect.origin.x, startRect.origin.y, startRect.size.width, 0);
CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"bounds"];
animation1.fromValue = [NSValue valueWithRect:startRect];
animation1.toValue = [NSValue valueWithRect:endRect];
animation1.duration = self.animationDuration / 2;
animation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
animation1.removedOnCompletion = NO;
animation1.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation1 forKey:@"animation1"];
// 更新数据并刷新视图
CGFloat lastDataPoint = [[self.dataPoints lastObject] floatValue];
[self.dataPoints removeAllObjects];
[self addDataPoint:lastDataPoint];
// 将视图高度恢复
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"bounds"];
animation2.fromValue = [NSValue valueWithRect:endRect];
animation2.toValue = [NSValue valueWithRect:startRect];
animation2.duration = self.animationDuration / 2;
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation2.beginTime = CACurrentMediaTime() + self.animationDuration / 2;
animation2.removedOnCompletion = NO;
animation2.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation2 forKey:@"animation2"];
}
@end
```
使用时,可以创建一个 DynamicLineChart 的实例,并调用 addDataPoint 方法添加数据点。如果需要动态更新折线图,可以调用 animate 方法实现动画效果。例如:
```objective-c
DynamicLineChart *lineChart = [[DynamicLineChart alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
[lineChart addDataPoint:10.0];
[lineChart addDataPoint:20.0];
[lineChart addDataPoint:30.0];
[lineChart animate];
```
这里只是一个简单的示例,具体实现还需要根据实际需求进行调整。
阅读全文