iOS繪制水波紋

一、object-c
創(chuàng)建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; //水深占據(jù)整個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)];//時間間隔為刷屏?xí)r間
        [_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
創(chuàng)建自定義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? {//水深占據(jù)整個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: 通過曲線類型獲得對應(yīng)的曲線路徑
    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() {
        //設(shè)置默認(rèn)值
        _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()

繪制結(jié)果


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 歡迎 star 歡迎到我的博客查看更多我的文章看到很多安卓 APP 的 按鈕帶有這種點擊效果忍不住寫了一個看看iO...
    maker997閱讀 3,756評論 1 4
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,582評論 30 472
  • 點贊再看,養(yǎng)成習(xí)慣,白嫖不好,歡迎大家關(guān)注我面試小專欄 : iOS中高級進(jìn)階之路 有我準(zhǔn)備的一線大廠面試資料和簡歷...
    iOS弗森科閱讀 4,446評論 1 36
  • 聲明:面試是對自我審視的一種過程,面試題和iOS程序員本身技術(shù)水平?jīng)]有對等關(guān)聯(lián),無論你能否全部答出,都不要對自己產(chǎn)...
    Kevin_wzx閱讀 2,343評論 1 2
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,814評論 28 54

友情鏈接更多精彩內(nèi)容