美文网首页图形控件
iOS绘制水波纹

iOS绘制水波纹

作者: Streamsle | 来源:发表于2021-09-30 20:45 被阅读0次

一、object-c
创建WaterWaveView,自定义UIView

WaterWaveView.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface WaterWaveView : UIView

@property(nonatomic,strong) UIColor * waveColor;//水纹颜色
@property(nonatomic,strong) UIColor * maskColor;//水纹遮罩颜色

@property(nonatomic,assign) CGFloat waveSpeed;//水纹的速度
@property(nonatomic,assign) CGFloat percent; //水深占据整个view的比例
@property(nonatomic,assign) CGFloat peak;    //水纹的纵向高度


//启动水波纹
-(void)startWave;

//停止水波纹
-(void)stopWave;

@end

NS_ASSUME_NONNULL_END

WaterWaveView.m

#import "WaterWaveView.h"

typedef NS_ENUM(NSInteger ,mCurveType) {
    
    mCurveTypeSin, // 正选
    mCurveTypeCos  // 余弦
};

@interface WaterWaveView ()
{
    CADisplayLink * _link;//定时器,刷新页面
    CGFloat _offset; //波纹移动的上下偏移
    CGFloat _waveHeight;//水的深度(不包含水纹)
    
    CAShapeLayer * waterLayer;//水的波纹
    CAShapeLayer * maskLayer; //水纹的遮罩层
    
    CGFloat _width; //视图宽度
    CGFloat _height;//视图高度
    

}


@end

@implementation WaterWaveView

-(instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        _width = frame.size.width;
        _height = frame.size.height;
        [self setDefauletProperty];
    }
    
    return self;
}

- (void)layoutSubviews
{
    
    if (!waterLayer) {
        waterLayer = [CAShapeLayer layer];
        [self.layer addSublayer:waterLayer];
    }
    if (!maskLayer) {
        maskLayer = [CAShapeLayer layer];
        [self.layer addSublayer:maskLayer];
    }
    
}
//启动水波纹
-(void)startWave
{
    if (!_link) {
        _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkAction)];//时间间隔为刷屏时间
        [_link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    }
}
//停止水波纹
-(void)stopWave
{
    [_link removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [_link invalidate];
    _link = nil;
}
#pragma  mark - 定时事件
-(void)displayLinkAction
{
    _offset += self.waveSpeed;
    
    UIBezierPath * sinPath = [self pathWithCurveType:mCurveTypeSin];
    waterLayer.path = sinPath.CGPath;
    waterLayer.fillColor = self.waveColor.CGColor;
    
    UIBezierPath * cosPath = [self pathWithCurveType:mCurveTypeCos];
    maskLayer.path = cosPath.CGPath;
    maskLayer.fillColor = self.maskColor.CGColor;
    
}

-(UIBezierPath *)pathWithCurveType:(mCurveType)type
{
    CGFloat startY = _waveHeight + _offset;
    UIBezierPath * mutablePath = [[UIBezierPath alloc] init];
    [mutablePath moveToPoint:CGPointMake(0, startY)];
    CGFloat y = 0;
    CGFloat x = 0;
    while (x < _width) {
        switch (type) {
            case 0:
                // y=Asin(ωx+φ)+h
                y = _waveHeight + self.peak * sin(x * 2 * M_PI/_width + _offset);
                break;
            case 1:
                y = _waveHeight + self.peak * cos(x * 2 * M_PI/_width + _offset);
                break;
            default:
                break;
        }
        [mutablePath addLineToPoint:CGPointMake(x, y)];
        x += 0.1;
    }
    [mutablePath addLineToPoint:CGPointMake(_width, _height)];
    [mutablePath addLineToPoint:CGPointMake(0, _height)];
    [mutablePath closePath];;
    return mutablePath;
}

- (void)setPercent:(CGFloat)percent
{
    _percent = percent;
    _waveHeight = (1 - percent) * self.bounds.size.height;
}

-(void)setDefauletProperty
{
    _waveHeight = self.bounds.size.height/2;
    self.peak = self.bounds.size.height/5;
    self.waveSpeed = 0.1;
    
}

项目中使用

   WaterWaveView * headView = [[WaterWaveView alloc] initWithFrame:CGRectMake(50, 300, 280, 280)];
    headView.waveColor=kHexColor(@"398AE5", 1.0);
    headView.maskColor=kHexColor(@"398AE5", 0.5);
    headView.percent = 0.35;
    headView.wavePeed = 0.05;
    headView.peak = 8;
    [self.view addSubview:headView];
    [headView startWave];

二、swift
创建自定义Swift的UIView,名称为:SwiftWaveView.swift
代码:

import UIKit

class SwiftWaveView: UIView {
    enum mCurveType : NSInteger {
        case mCurveTypeSin = 0
        case mCurveTypeCos = 1
    }
    var _link:CADisplayLink?
    var _offset:CGFloat = 0
    var _waveHeight:CGFloat?
    var _width:CGFloat?
    var _height:CGFloat?
    var _waveLayer:CAShapeLayer?
    var _maskLayer:CAShapeLayer?
    // 波浪移动速度
    public var waveSpeed: CGFloat = 0.1 //水纹的速度
    public var percent:CGFloat? {//水深占据整个view的比例
        didSet{
            assert(percent! >= 0.0 && percent! <= 1, "水波纹完成比例不得小于0或大于1!");
            _waveHeight = _height! * (1 - percent!)
        }
    }
    public var peak:CGFloat? //水纹的纵向高度
    public var waveColor:UIColor?
    public var maskColor:UIColor?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        _width = frame.size.width
        _height = frame.self.height
        setDefaultProperty()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func layoutSubviews() {
        print("layoutSubviews");
        _width = frame.size.width
        _height = frame.size.height
        layoutWaveLayers()
    }
    
    // MARK: 添加水波纹Layer
    func layoutWaveLayers() {
        print("layoutWaveLayers");
        if _waveLayer == nil {
            _waveLayer = CAShapeLayer()
            layer.addSublayer(_waveLayer!)
        }
        if _maskLayer == nil {
            _maskLayer = CAShapeLayer()
            layer.addSublayer(_maskLayer!)
        }

    }
    
    
    @objc func startWave() {
        if _link == nil {
            _link = CADisplayLink.init(target: self, selector: #selector(displayLinkAction))
            _link?.add(to: RunLoop.current, forMode: RunLoop.Mode.common)
        }
    }
    
    
    func stopWave() {
        _link?.remove(from: RunLoop.current, forMode: RunLoop.Mode.common)
        _link?.invalidate()
        _link = nil
    }
    
    // MARK: 定时事件
    
    @objc func displayLinkAction() {
            _offset += waveSpeed
        let sinPath:UIBezierPath = pathWithCurveType(curveType: mCurveType.mCurveTypeSin)
        _waveLayer?.fillColor = waveColor?.cgColor
        _waveLayer?.path = sinPath.cgPath
        
        let cosPath:UIBezierPath = pathWithCurveType(curveType: mCurveType.mCurveTypeCos)
       
        _maskLayer?.fillColor = maskColor?.cgColor
        _maskLayer?.path = cosPath.cgPath
    }
    

    
    //MARK: 通过曲线类型获得对应的曲线路径
    func pathWithCurveType(curveType:mCurveType) -> UIBezierPath {
        let startY:CGFloat = _waveHeight! + _offset
        let mutablePath:UIBezierPath = UIBezierPath()
        mutablePath.move(to: CGPoint.init(x: 0, y: startY))
        var y : CGFloat
        
        var x = CGFloat(0)
        while x <= bounds.size.width {
            // y=Asin(ωx+φ)+h
            switch curveType {
            case .mCurveTypeSin:
                y =  _waveHeight! + peak! * sin(x * 2.0 * CGFloat.pi/_width! + _offset)
            case .mCurveTypeCos:
                y =  _waveHeight! + peak! * cos(x * 2.0 * CGFloat.pi/_width! + _offset)
            }
            mutablePath.addLine(to: CGPoint.init(x: CGFloat(x), y: CGFloat(y)))
            x += 0.1
        }
        mutablePath.addLine(to: CGPoint(x: bounds.size.width, y: bounds.size.height))
        mutablePath.addLine(to: CGPoint(x: 0, y: bounds.size.height))
        mutablePath.close();
        return mutablePath
    }
    func setDefaultProperty() {
        //设置默认值
        _waveHeight = self.bounds.size.height/2;
        peak = self.bounds.size.height/5;
        waveSpeed = 0.1;

    }
    
    
}

项目中使用:

 let headView = SwiftWaveView.init(frame: CGRect(x: 50, y: 120, width: 280, height: 280))
        headView.waveColor = hexColor(str: "398AE5", alpha: 1.0)
        headView.maskColor = hexColor(str: "398AE5", alpha: 0.5)
        headView.percent = 0.35
        headView.waveSpeed = 0.05
        headView.peak = 8
        self.view.addSubview(headView)
        headView.startWave()

绘制结果


image.png

相关文章

网友评论

    本文标题:iOS绘制水波纹

    本文链接:https://www.haomeiwen.com/subject/nsvenltx.html