iOS开发基础33-核心动画(一)CALayer 与 Core Animation 深度解析
CALayer 与 Core Animation 深度解析:图层属性、隐式动画、基本动画、关键帧动画、动画组与转场动画
本文系统梳理 CALayer 图层体系与 Core Animation 核心动画:CALayer 常用属性、position/anchorPoint 定位机制、隐式动画与 CATransaction、CAAnimation 继承结构、CABasicAnimation/CAKeyframeAnimation/CAAnimationGroup/CATransition 四类动画、动画暂停与恢复,以及 CADisplayLink。
一、CALayer 简介
1. 什么是 CALayer
CALayer 定义在 QuartzCore 框架中,是 UIView 内部负责显示的图层。每个 UIView 创建时内部自动创建一个 CALayer,通过 view.layer 访问:
@property(nonatomic, readonly, retain) CALayer *layer;
UIView 负责事件处理与层级管理,CALayer 负责内容显示与动画。UIView 调用 drawRect: 绘图时,内容绘制在自身 layer 上,由 Core Animation 渲染服务呈现到屏幕。
2. CALayer 的基本用途
通过操作 CALayer 可以调整 UIView 外观:圆角、边框、阴影、形变,以及添加动画实现炫酷效果。
二、CALayer 常用属性
| 属性 | 类型 | 说明 |
|---|---|---|
bounds |
CGRect |
宽度和高度(x/y 通常为 0) |
position |
CGPoint |
在父层中的位置(默认指中点,由 anchorPoint 决定) |
anchorPoint |
CGPoint |
锚点(x/y 范围 0~1,默认 0.5,0.5),决定 position 对应图层上的哪个点 |
backgroundColor |
CGColorRef |
背景颜色 |
transform |
CATransform3D |
3D 形变(平移/缩放/旋转) |
borderColor |
CGColorRef |
边框颜色 |
borderWidth |
CGFloat |
边框宽度 |
cornerRadius |
CGFloat |
圆角半径 |
contents |
id |
图层内容(可设为 CGImageRef) |
masksToBounds |
BOOL |
是否裁剪超出图层边界的子层内容 |
shadowOpacity |
float |
阴影透明度(0~1,默认 0 即无阴影) |
shadowColor |
CGColorRef |
阴影颜色 |
shadowOffset |
CGSize |
阴影偏移量 |
shadowRadius |
CGFloat |
阴影模糊半径 |
opacity |
float |
图层透明度(0~1) |
zPosition |
CGFloat |
在父层中的 Z 轴层级(影响显示顺序,不影响命中测试) |
hidden |
BOOL |
是否隐藏 |
sublayers |
NSArray |
子图层数组 |
superlayer |
CALayer |
父图层 |
mask |
CALayer |
蒙版图层(根据透明度裁剪) |
基本使用
// 圆角
self.redView.layer.cornerRadius = 10;
self.redView.layer.masksToBounds = YES; // 裁剪超出圆角的内容
// 边框
self.redView.layer.borderWidth = 2;
self.redView.layer.borderColor = [UIColor blackColor].CGColor;
// 阴影(注意:阴影与 masksToBounds=YES 冲突,阴影会被裁剪掉)
self.redView.layer.shadowOpacity = 0.5;
self.redView.layer.shadowColor = [UIColor blackColor].CGColor;
self.redView.layer.shadowOffset = CGSizeMake(2, 2);
self.redView.layer.shadowRadius = 3;
// 内容(设置图片)
self.layer.contents = (id)[UIImage imageNamed:@"avatar"].CGImage;
cornerRadius只影响背景色和边框,不影响contents(图片)和子层,需配合masksToBounds=YES才能裁剪图片圆角。阴影需要图层外部空间,masksToBounds=YES会裁掉阴影,二者不可同时生效。
三、UIView 与 CALayer 的关系与选择
1. 框架可移植性
CALayer、CGImageRef、CGColorRef定义在 QuartzCore / CoreGraphics 框架,可跨平台(iOS + macOS)。UIColor、UIImage定义在 UIKit,仅 iOS 可用。- 为保证可移植性,CALayer 的颜色/内容属性使用
CGColorRef/CGImageRef,不使用UIColor/UIImage。
2. 选择 UIView 还是 CALayer
CALayer继承自NSObject,不能响应触摸事件(不是 UIResponder 子类)。UIView继承自UIResponder,可以响应事件。- 需要交互 → 用 UIView;不需要交互、纯显示 → CALayer 性能更优(更轻量级)。
Core Animation 动画直接作用在 CALayer 上,对 UIView 做核心动画本质上是对
view.layer做动画。
四、position 与 anchorPoint
position 和 anchorPoint 是 CALayer 定位的核心:
position:图层在父层中的位置,以父层左上角为原点。anchorPoint:锚点,决定图层上的哪个点与position重合。以自身左上角为原点,x/y 范围 0~1,默认(0.5, 0.5)(中心点)。
anchorPoint(0,0) → 左上角
anchorPoint(0.5,0.5) → 中心点(默认)
anchorPoint(1,1) → 右下角
修改 anchorPoint 的注意事项
修改 anchorPoint 时,position 不变,但 anchorPoint 对应的点变了,导致图层位置发生偏移。如需保持视觉位置不变,需重新计算 position:
// 修改 anchorPoint 后保持位置不变
CGPoint oldAnchorPoint = self.layer.anchorPoint;
self.layer.anchorPoint = CGPointMake(0, 0); // 改为左上角
CGFloat deltaX = (self.layer.anchorPoint.x - oldAnchorPoint.x) * self.layer.bounds.size.width;
CGFloat deltaY = (self.layer.anchorPoint.y - oldAnchorPoint.y) * self.layer.bounds.size.height;
self.layer.position = CGPointMake(self.layer.position.x + deltaX, self.layer.position.y + deltaY);
frame 是计算属性
CALayer 的 frame 不是存储属性,而是由 position、anchorPoint、bounds、transform 计算得出。修改 transform(如旋转)后,frame 的值可能变得无意义,此时应使用 bounds + position 定位。
五、隐式动画与 CATransaction
1. 隐式动画
每个 UIView 内部关联的 layer 称为 Root Layer(根层)。手动创建的 CALayer(非 Root Layer)的部分属性修改时,默认自动产生动画,称为隐式动画。这些属性称为 Animatable Properties(可动画属性):
| 可动画属性 | 动画效果 |
|---|---|
bounds |
缩放 |
backgroundColor |
背景色渐变 |
position |
平移 |
opacity |
淡入淡出 |
cornerRadius |
圆角变化 |
borderWidth |
边框宽度变化 |
transform |
形变 |
Root Layer(UIView 内部的 layer)默认关闭隐式动画,因为 UIView 的动画方法(
UIView animateWithDuration:)内部通过 CATransaction 管理动画。直接修改 Root Layer 属性不产生隐式动画。
2. CATransaction 动画事务
通过 CATransaction 可以控制隐式动画的开关、时长、动画曲线:
// 关闭隐式动画
[CATransaction begin];
[CATransaction setDisableActions:YES];
self.myLayer.position = CGPointMake(10, 10);
[CATransaction commit];
// 设置隐式动画时长和曲线
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
self.myLayer.backgroundColor = [UIColor blueColor].CGColor;
self.myLayer.position = CGPointMake(200, 200);
[CATransaction commit];
3. 隐式动画示例(随机位置小游戏)

@interface ViewController ()
@property (nonatomic, weak) CALayer *layer1;
@property (nonatomic, weak) CALayer *layer2;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
for (int i = 0; i < 2; i++) {
CALayer *layer = [CALayer layer];
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.position = CGPointMake(50, 50 + i * 110);
layer.anchorPoint = CGPointMake(0, 0);
layer.backgroundColor = (i == 0 ? [UIColor redColor] : [UIColor yellowColor]).CGColor;
[self.view.layer addSublayer:layer];
if (i == 0) self.layer1 = layer;
else self.layer2 = layer;
}
}
- (void)animateLayer:(CALayer *)layer {
[CATransaction begin];
[CATransaction setAnimationDuration:1];
layer.position = CGPointMake(arc4random_uniform(275), arc4random_uniform(550));
layer.backgroundColor = [self randomColor].CGColor;
layer.cornerRadius = arc4random_uniform(50);
layer.borderColor = [self randomColor].CGColor;
layer.borderWidth = arc4random_uniform(10);
[CATransaction commit];
}
- (IBAction)start:(id)sender {
[self animateLayer:self.layer1];
[self animateLayer:self.layer2];
}
- (UIColor *)randomColor {
CGFloat r = arc4random_uniform(256) / 255.0;
CGFloat g = arc4random_uniform(256) / 255.0;
CGFloat b = arc4random_uniform(256) / 255.0;
return [UIColor colorWithRed:r green:g blue:b alpha:1];
}
@end
六、Core Animation 概述
1. 继承结构
CAAnimation(抽象类,遵守 CAMediaTiming 协议)
├── CAPropertyAnimation(抽象类)
│ ├── CABasicAnimation 基本动画
│ └── CAKeyframeAnimation 关键帧动画
├── CAAnimationGroup 动画组
└── CATransition 转场动画

2. 使用步骤
- 有一个 CALayer;
- 创建 CAAnimation 子类对象,设置动画属性;
- 调用
[layer addAnimation:forKey:]添加动画到图层; - 调用
[layer removeAnimationForKey:]可移除动画。
Xcode 5 之后项目自动链接 QuartzCore,无需手动添加框架;仍需
#import <QuartzCore/QuartzCore.h>。
3. CAAnimation 基类属性
| 属性 | 说明 |
|---|---|
duration |
动画持续时间 |
repeatCount |
重复次数(无限循环设 HUGE_VALF 或 MAXFLOAT) |
repeatDuration |
重复时间(与 repeatCount 互斥) |
autoreverses |
动画结束后是否原路返回 |
removedOnCompletion |
动画结束后是否从图层移除(默认 YES) |
fillMode |
非 active 时间段的行为(开始前/结束后) |
beginTime |
延迟执行时间(CACurrentMediaTime() + 延迟) |
timingFunction |
速度控制函数 |
delegate |
动画代理 |
4. fillMode 填充模式
fillMode 生效需配合 removedOnCompletion = NO:
| fillMode | 说明 |
|---|---|
kCAFillModeRemoved |
默认值,动画开始前和结束后对 layer 无影响,结束后恢复原状 |
kCAFillModeForwards |
动画结束后保持最后状态 |
kCAFillModeBackwards |
动画加入 layer 后立即进入初始状态并等待开始 |
kCAFillModeBoth |
Forwards + Backwards 合成 |
即使设置
removedOnCompletion=NO+fillMode=Forwards,图层的真实属性值并未改变,只是视觉上保持动画结束状态。如需真实改变属性,应在动画开始前直接设置 layer 的目标属性值。
5. timingFunction 速度控制
| 常量 | 说明 |
|---|---|
kCAMediaTimingFunctionLinear |
匀速 |
kCAMediaTimingFunctionEaseIn |
先慢后快(渐进) |
kCAMediaTimingFunctionEaseOut |
先快后慢(渐出) |
kCAMediaTimingFunctionEaseInEaseOut |
先慢后快再慢(默认) |
kCAMediaTimingFunctionDefault |
默认,中间较快 |
6. 动画代理
@interface NSObject (CAAnimationDelegate)
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end
7. 动画的暂停与恢复
// 暂停
- (void)pauseLayer:(CALayer *)layer {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0; // 时间停止
layer.timeOffset = pausedTime; // 记录暂停时刻
}
// 恢复
- (void)resumeLayer:(CALayer *)layer {
CFTimeInterval pausedTime = layer.timeOffset;
layer.speed = 1.0; // 时间继续
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause; // 补偿暂停时间
}
七、CABasicAnimation 基本动画
CABasicAnimation 是 CAPropertyAnimation 的子类,通过 keyPath 指定图层属性,从 fromValue 渐变到 toValue。
常用 keyPath
| keyPath | 说明 |
|---|---|
position |
位置(平移) |
bounds |
尺寸(缩放) |
transform.translation.x/y |
平移 x/y |
transform.scale |
缩放 |
transform.rotation.z |
旋转(z 轴,平面旋转) |
opacity |
透明度 |
backgroundColor |
背景色 |
cornerRadius |
圆角 |
borderWidth |
边框宽度 |
shadowOpacity |
阴影透明度 |
示例:缩放动画
CABasicAnimation *anim = [CABasicAnimation animation];
anim.keyPath = @"transform.scale";
anim.fromValue = @1.0;
anim.toValue = @0.5;
anim.duration = 0.5;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
[self.imageView.layer addAnimation:anim forKey:nil];
示例:旋转动画
CABasicAnimation *anim = [CABasicAnimation animation];
anim.keyPath = @"transform.rotation.z";
anim.toValue = @(M_PI); // 旋转 180°
anim.duration = 1.0;
[self.view.layer addAnimation:anim forKey:nil];
byValue表示相对变化量(如@(M_PI)表示在当前基础上再转 180°)。fromValue+toValue为绝对变化,fromValue+byValue为相对变化,toValue+byValue不常用。
八、CAKeyframeAnimation 关键帧动画
CAKeyframeAnimation 通过 values 数组保存多个关键帧,图层依次经过每个关键帧;也可通过 path 指定移动轨迹。
| 属性 | 说明 |
|---|---|
values |
关键帧值数组 |
path |
移动路径(CGPathRef),设置后 values 被忽略,仅对 position/anchorPoint 生效 |
keyTimes |
每个关键帧对应的时间点(0~1),不设置则时间平分 |
示例:左右摇晃

CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"transform";
anim.duration = 0.5;
anim.repeatCount = MAXFLOAT;
NSValue *v1 = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-25 / 180.0 * M_PI, 0, 0, 1)];
NSValue *v2 = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(25 / 180.0 * M_PI, 0, 0, 1)];
NSValue *v3 = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-25 / 180.0 * M_PI, 0, 0, 1)];
anim.values = @[v1, v2, v3];
[self.layer addAnimation:anim forKey:nil];
示例:沿路径移动
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"position";
anim.duration = 3.0;
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 200, 200)];
anim.path = path.CGPath;
[self.imageView.layer addAnimation:anim forKey:nil];
CABasicAnimation可看作只有 2 个关键帧的CAKeyframeAnimation。
九、CAAnimationGroup 动画组
CAAnimationGroup 将多个动画对象组合,同时并发执行:
// 缩放 + 旋转 + 平移 同时执行
CABasicAnimation *scaleAnim = [CABasicAnimation animation];
scaleAnim.keyPath = @"transform.scale";
scaleAnim.toValue = @0.5;
CABasicAnimation *rotateAnim = [CABasicAnimation animation];
rotateAnim.keyPath = @"transform.rotation.z";
rotateAnim.toValue = @(M_PI);
CABasicAnimation *positionAnim = [CABasicAnimation animation];
positionAnim.keyPath = @"position";
positionAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 300)];
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[scaleAnim, rotateAnim, positionAnim];
group.duration = 1.0;
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
[self.imageView.layer addAnimation:group forKey:nil];
组内各动画的
duration不生效,以CAAnimationGroup.duration为准。可通过设置子动画的beginTime错开执行时间。
十、CATransition 转场动画
CATransition 用于图层的转场效果(移出/移入屏幕),UINavigationController 的 push 动画即通过 CATransition 实现。
| 属性 | 说明 |
|---|---|
type |
转场类型 |
subtype |
转场方向 |
startProgress |
动画起点(0~1) |
endProgress |
动画终点(0~1) |
公开的转场类型(type)

| 常量 | 说明 |
|---|---|
kCATransitionFade |
淡入淡出 |
kCATransitionMoveIn |
新图覆盖旧图 |
kCATransitionPush |
推挤(旧图被推出) |
kCATransitionReveal |
揭开(旧图移开露出新图) |
转场方向(subtype)
| 常量 | 说明 |
|---|---|
kCATransitionFromRight |
从右侧 |
kCATransitionFromLeft |
从左侧 |
kCATransitionFromTop |
从顶部 |
kCATransitionFromBottom |
从底部 |
示例:图片切换转场
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
static int index = 1;
NSString *imageName = [NSString stringWithFormat:@"%d", index];
self.imageView.image = [UIImage imageNamed:imageName];
index = (index % 3) + 1;
CATransition *anim = [CATransition animation];
anim.type = kCATransitionPush; // 推挤
anim.subtype = kCATransitionFromLeft; // 从左侧
anim.duration = 0.5;
[self.imageView.layer addAnimation:anim forKey:nil];
}



转场代码(修改图层内容)与转场动画必须写在一起,否则无效。
关于私有转场效果
cube(立方体)、suckEffect(吮吸)、oglFlip(翻转)、rippleEffect(波纹)、pageCurl(翻页)、pageUnCurl(反翻页)、cameraIrisHollowOpen/Close(镜头开关)等效果属于私有 API,没有公开的常量定义,需用字符串字面量。使用私有 API 可能导致 App Store 审核被拒,生产环境建议使用公开类型或自定义转场。
十一、UIView 转场动画
UIKit 封装了基于 CATransition 的转场方法,使用更简便:
单视图转场
[UIView transitionWithView:self.imageView
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
// 在此修改视图内容
self.imageView.image = [UIImage imageNamed:@"newImage"];
} completion:^(BOOL finished) {
// 动画完成
}];
双视图转场(替换视图)
[UIView transitionFromView:self.oldView
toView:self.newView
duration:0.5
options:UIViewAnimationOptionTransitionCurlUp
completion:^(BOOL finished) {
// 动画完成,oldView 已被移除,newView 已被添加
}];
常用转场 options
| 常量 | 说明 |
|---|---|
UIViewAnimationOptionTransitionFlipFromLeft |
从左翻转 |
UIViewAnimationOptionTransitionFlipFromRight |
从右翻转 |
UIViewAnimationOptionTransitionCurlUp |
向上翻页 |
UIViewAnimationOptionTransitionCurlDown |
向下翻页 |
UIViewAnimationOptionTransitionCrossDissolve |
淡入淡出 |
十二、CADisplayLink
CADisplayLink 是与屏幕刷新频率同步的定时器(约 60 次/秒),适合频繁重绘的动画,比 NSTimer 更精准、无延迟。
- (void)awakeFromNib {
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
// 停止:[link invalidate];
}
setNeedsDisplay不会立即调用drawRect:,而是给控件绑定重绘标识,屏幕刷新时统一重绘。UIScrollView 滚动时需使用NSRunLoopCommonModes才能继续执行。
十三、Swift 版本对照
CALayer 属性
let view = UIView()
view.layer.cornerRadius = 10
view.layer.masksToBounds = true
view.layer.borderWidth = 2
view.layer.borderColor = UIColor.black.cgColor
view.layer.shadowOpacity = 0.5
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 2, height: 2)
view.layer.shadowRadius = 3
view.layer.contents = UIImage(named: "avatar")?.cgImage
隐式动画(CATransaction)
CATransaction.begin()
CATransaction.setAnimationDuration(1.0)
CATransaction.setDisableActions(false)
layer.position = CGPoint(x: 200, y: 200)
layer.backgroundColor = UIColor.blue.cgColor
CATransaction.commit()
CABasicAnimation
let anim = CABasicAnimation(keyPath: "transform.scale")
anim.fromValue = 1.0
anim.toValue = 0.5
anim.duration = 0.5
anim.isRemovedOnCompletion = false
anim.fillMode = .forwards
imageView.layer.add(anim, forKey: nil)
CAKeyframeAnimation
let anim = CAKeyframeAnimation(keyPath: "transform")
anim.duration = 0.5
anim.repeatCount = .infinity
let v1 = NSValue(caTransform3D: CATransform3DMakeRotation(-25 / 180 * .pi, 0, 0, 1))
let v2 = NSValue(caTransform3D: CATransform3DMakeRotation(25 / 180 * .pi, 0, 0, 1))
anim.values = [v1, v2, v1]
layer.add(anim, forKey: nil)
CAAnimationGroup
let scale = CABasicAnimation(keyPath: "transform.scale")
scale.toValue = 0.5
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.toValue = CGFloat.pi
let group = CAAnimationGroup()
group.animations = [scale, rotate]
group.duration = 1.0
group.isRemovedOnCompletion = false
group.fillMode = .forwards
imageView.layer.add(group, forKey: nil)
CATransition
let anim = CATransition()
anim.type = .push
anim.subtype = .fromLeft
anim.duration = 0.5
imageView.image = UIImage(named: "new")
imageView.layer.add(anim, forKey: nil)
动画暂停与恢复
func pauseLayer(_ layer: CALayer) {
let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil)
layer.speed = 0
layer.timeOffset = pausedTime
}
func resumeLayer(_ layer: CALayer) {
let pausedTime = layer.timeOffset
layer.speed = 1
layer.timeOffset = 0
layer.beginTime = 0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
layer.beginTime = timeSincePause
}
十四、总结
- CALayer:UIView 内部负责显示的图层,继承 NSObject,不能响应事件;可设置圆角、边框、阴影、形变、内容等。
- position/anchorPoint:position 是图层在父层的位置,anchorPoint 决定图层上哪个点与 position 重合(默认中心点);修改 anchorPoint 会导致位置偏移,需重新计算 position;frame 是计算属性,transform 后可能无效。
- 隐式动画:手动创建的非 Root Layer 修改可动画属性时默认产生动画;Root Layer(UIView 内部 layer)隐式动画被禁用;通过 CATransaction 控制开关、时长、曲线。
- Core Animation:直接作用于 CALayer,后台执行不阻塞主线程;继承结构 CAAnimation → CAPropertyAnimation → CABasicAnimation/CAKeyframeAnimation,以及 CAAnimationGroup、CATransition。
- CABasicAnimation:通过 keyPath 指定属性,fromValue→toValue 渐变;动画结束后图层真实属性值未变,只是视觉保持(removedOnCompletion=NO + fillMode=Forwards)。
- CAKeyframeAnimation:values 多关键帧或 path 路径移动,keyTimes 指定各帧时间点。
- CAAnimationGroup:多动画并发执行,duration 以组为准,子动画 beginTime 可错开。
- CATransition:转场动画,公开 type 有 Fade/MoveIn/Push/Reveal,subtype 指定方向;cube/rippleEffect 等为私有 API 可能被拒;转场代码与动画必须写在一起。
- UIView 转场:transitionWithView:(单视图)和 transitionFromView:toView:(双视图)封装了 CATransition,使用更简便。
- 动画暂停恢复:通过 speed=0/timeOffset 暂停,恢复时补偿 beginTime。
- CADisplayLink:与屏幕刷新同步(60fps),适合频繁重绘;UIScrollView 滚动时需 NSRunLoopCommonModes。

浙公网安备 33010602011771号