用drawRect以及CAReplicatorLayer绘制动态水波纹

大大简化了写水波纹效果的难度,你可以根据示例自己组装水波纹效果,本设计是几个工具组合在一起完成的效果, DrawRectObject 以及 ReplicatorLineAnimationView 均可以独立完成更复杂的功能.

说明

1. 用sine计算正玄曲线

2. 用CAReplicatorLayer实现重复移动的效果

效果

源码

https://github.com/YouXianMing/UI-Component-Collection 中的 DrawRectObject

//
//  WaveView.h
//  DrawRectObject
//
//  Created by YouXianMing on 16/8/1.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "CustomDrawingView.h"

typedef enum : NSUInteger {

    kStrokeWave = 1 << 2,
    kFillWave   = 1 << 3 ,

} EWaveViewType;

@interface WaveView : CustomDrawingView

/**
 *  Wave type, default is kFillWave.
 */
@property (nonatomic) EWaveViewType type;

/**
 *  Sine phase, default is 0.
 */
@property (nonatomic) CGFloat  phase;

/**
 *  Wave crest height, Default is 10.
 */
@property (nonatomic) CGFloat  waveCrest;

/**
 *  Full wave count,  default is 1.
 */
@property (nonatomic) NSInteger waveCount;

/**
 *  The fill style.
 */
@property (nonatomic, strong) DrawingStyle *fillStyle;

/**
 *  The stroke style.
 */
@property (nonatomic, strong) DrawingStyle *strokeStyle;

@end
//
//  WaveView.m
//  DrawRectObject
//
//  Created by YouXianMing on 16/8/1.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "WaveView.h"

@implementation WaveView

- (instancetype)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {

        self.waveCrest = 10.f;
        self.waveCount = 1;
        self.phase     = 0.f;
        self.type      = kFillWave;

        DrawingStyle *fillStyle = [DrawingStyle new];
        fillStyle.fillColor     = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.5f]];
        self.fillStyle          = fillStyle;

        DrawingStyle *strokeStyle = [DrawingStyle new];
        strokeStyle.strokeColor   = [DrawingColor colorWithUIColor:[UIColor redColor]];
        strokeStyle.lineWidth     = 0.5f;
        self.strokeStyle          = strokeStyle;
    }

    return self;
}

- (void)drawRect:(CGRect)rect {

    NSParameterAssert(self.fillStyle);
    NSParameterAssert(self.strokeStyle);

    [super drawRect:rect];

    CGFloat width  = self.frame.size.width;
    CGFloat height = self.frame.size.height;

    if (self.type & kFillWave) {

        [self.drawRectObject useDrawingStyle:_fillStyle drawFillBlock:^(DrawRectObject *drawRectObject) {

            for (CGFloat x = 0; x <= width; x++) {

                if (x == 0) {

                    [drawRectObject moveToStartPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                    continue;

                } else {

                    [drawRectObject addLineToPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                }
            }

            [drawRectObject addLineToPoint:CGPointMake(width, height)];
            [drawRectObject addLineToPoint:CGPointMake(0, height)];
            [drawRectObject addLineToPoint:CGPointMake(0, _waveCrest * sin((2 * M_PI) * _waveCount / width * 0 + _phase) + height / 2.f)];
        }];
    }

    if (self.type & kStrokeWave) {

        [self.drawRectObject useDrawingStyle:_strokeStyle drawStrokeBlock:^(DrawRectObject *drawRectObject) {

            for (CGFloat x = 0; x <= width; x++) {

                if (x == 0) {

                    [drawRectObject moveToStartPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                    continue;

                } else {

                    [drawRectObject addLineToPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                }
            }
        }];
    }
}

@end
//
//  ViewController.m
//  DrawRectObject
//
//  Created by YouXianMing on 16/7/30.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "WaveView.h"
#import "ReplicatorLineAnimationView.h"
#import "UIView+SetRect.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    // Wave 1
    {
        WaveView *waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, Width, Height)];
        waveView.phase     = 0.f;
        waveView.waveCrest = 5.f;
        waveView.waveCount = 1;
        waveView.type      = kStrokeWave | kFillWave;

        {
            DrawingStyle *fillStyle = [DrawingStyle new];
            fillStyle.fillColor     = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.25f]];
            waveView.fillStyle      = fillStyle;

            DrawingStyle *strokeStyle = [DrawingStyle new];
            strokeStyle.strokeColor   = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.5f]];
            strokeStyle.lineWidth     = 0.5f;
            waveView.strokeStyle      = strokeStyle;
        }

        ReplicatorLineAnimationView *replicatorLineView = [[ReplicatorLineAnimationView alloc] initWithFrame:waveView.bounds];
        replicatorLineView.direction   = kReplicatorLeft;
        replicatorLineView.speed       = 0.1f;
        replicatorLineView.contentView = waveView;
        [replicatorLineView startAnimation];
        [self.view addSubview:replicatorLineView];
    }

    // Wave 2
    {
        WaveView *waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, Width, Height)];
        waveView.phase     = 0.f;
        waveView.waveCrest = 10.f;
        waveView.waveCount = 1;
        waveView.type      = kStrokeWave | kFillWave;

        {
            DrawingStyle *fillStyle = [DrawingStyle new];
            fillStyle.fillColor     = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.5f]];
            waveView.fillStyle      = fillStyle;

            DrawingStyle *strokeStyle = [DrawingStyle new];
            strokeStyle.strokeColor   = [DrawingColor colorWithUIColor:[UIColor redColor]];
            strokeStyle.lineWidth     = 0.5f;
            waveView.strokeStyle      = strokeStyle;
        }

        ReplicatorLineAnimationView *replicatorLineView = [[ReplicatorLineAnimationView alloc] initWithFrame:waveView.bounds];
        replicatorLineView.direction = kReplicatorLeft;
        replicatorLineView.speed     = 0.3f;
        replicatorLineView.contentView = waveView;
        [replicatorLineView startAnimation];
        [self.view addSubview:replicatorLineView];
    }

    // Wave 3
    {
        WaveView *waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, Width, Height)];
        waveView.phase     = 10.f;
        waveView.waveCrest = 15.f;
        waveView.waveCount = 1;
        waveView.type      = kFillWave;

        {
            DrawingStyle *fillStyle = [DrawingStyle new];
            fillStyle.fillColor     = [DrawingColor colorWithUIColor:[UIColor redColor]];
            waveView.fillStyle      = fillStyle;
        }

        ReplicatorLineAnimationView *replicatorLineView = [[ReplicatorLineAnimationView alloc] initWithFrame:waveView.bounds];
        replicatorLineView.direction   = kReplicatorLeft;
        replicatorLineView.speed       = 0.5f;
        replicatorLineView.contentView = waveView;
        [replicatorLineView startAnimation];
        [self.view addSubview:replicatorLineView];
    }
}

@end
时间: 2024-12-18 08:43:12

用drawRect以及CAReplicatorLayer绘制动态水波纹的相关文章

OSGEarth绘制动态水效果

在OSGEarth上绘制水效果的思路为: 1. 使用OSG::Geometry的方式绘制多边形: 2. 在绘制的多边形上贴一个水的纹理: 3. 对纹理使用shader效果,使之动态展示. 此种方式适用于小范围的不严格的水效果,若需要大范围或者有水底效果的请使用OSGOcean. 代码如下:water.h class Water : public HandleAdapter { public: Water(GraphicsView* view); ~Water(); protected: virt

Android 自定义view实现水波纹效果

http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她: 在这样的关键时候,身子板就一定得硬了,可千万别说不行,爷们儿怎么能说不行呢: 好了,为了让大家都能给妹纸们想要的,后面会逐渐分享一些比较比较不错的效果,目的只有一个,通过自定义view实现我们所能实现的动效: 今天主要分

自定义控件---继承View类方式(五彩绚烂的水波纹案例)

---------------------------------------看效果(还有动画效果哦)---------------------------------------------------- activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

多个彩色水波纹扩散效果

布局 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=

单个水波纹扩散

布局 <com.ee.MyWaveD android:layout_width="match_parent" android:layout_height="match_parent" > </com.ee.MyWaveD> 类 package com.ee; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color

动画绘制水波纹

使用drawRect:方式绘制的动画效果,右图为占用了多少CPU. 虽然画起来挺好看的,但占用的内存真心吃不消,原因其实很简单哦,drawRect:方法只调用CPU进行图形绘制,所以非常非常的消耗CPU性能,把它集成到应用程序中,我觉得是不靠谱的呢. // // WaterView.h // Cell // // Copyright (c) 2014年 Y.X. All rights reserved. // #import <UIKit/UIKit.h> @interface WaterVi

手把手教你画一个 逼格满满圆形水波纹loadingview Android

才没有完结呢o( ̄︶ ̄)n .大家好,这里是番外篇. 拜读了爱哥的博客,又学到不少东西.爱哥曾经说过: 要站在巨人的丁丁上. 那么今天,我们就站在爱哥的丁丁上来学习制作一款自定义view(开个玩笑,爱哥看到别打我). 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50523713 上一篇 带领大家做了一款炫酷的loading动画view 手把手带你做一个超炫酷loading成功动画view  不知道大家跟着做了一遍没有呢? 在开始之

三角函数之美-水波纹加载LoadingView

一.前言 学习是要总结的,最近几天学习了绘图相关的,但是使用的机会较少,现在又快要遗忘了,这次看了水波纹的绘制,觉得十分有意思,还是 把实现的方法记录下来.技术无他,为手熟尔,还是要多练习,空淡误国,实干兴邦,让我们看看今天的三角函数之美吧. 二.概述 肯定大家对中学学习的三角函数都不陌生吧,不过学习的sin.cos是超越函数一类函数,是初等函数的一种,借用维基百科的一张图: 一个完整的正弦函数应该是这样的:>y=Asin(ωx+φ)+h,A决定峰值,ω决定周期,φ表示初相位,h表示y轴的位置.

Android -- 贝塞尔实现水波纹动画(划重点!!)

1,昨天看到了一个挺好的ui效果,是使用贝塞尔曲线实现的,就和大家来分享分享,还有,在写博客的时候我经常会把自己在做某种效果时的一些问题给写出来,而不是像很多文章直接就给出了解决方法,这里给大家解释一下,这里写出我遇到的一些问题不是为了凑整片文章的字数,而是希望大家能从根源下知道它是怎么解决的,而不是你直接百度搜索这个问题解决的代码,好了,说了这么多,只是想告诉大家,我后面会在过程中提很多问题(邪恶脸,嘿嘿嘿),好吧,来看看今天的效果: 2,what is the fuck?,这就是你说的很好看