Android: 자체 애니메이션 실천 - Tencent OS 녹음기 파형 을 예 로 들 면

[전재 출처 밝 혀 주세요] 작가: DrkCore (http://blog.csdn.net/DrkCore) 원본 링크: (http://blog.csdn.net/drkcore/article/details/51822818)
요 며칠 동안 졸업 과 같은 일 로 인해 블 로 그 를 쓰 지 않 았 습 니 다. 마침 최근 에 Bugly 가 발표 한 셀 프 애니메이션 에 관 한 블 로그 인 을 보 았 습 니 다. 깊이 있 게 썼 지만 아 쉽게 도 소스 코드 를 넣 지 못 했 습 니 다.경탄 한 나머지 직접 바퀴 를 만 들 생각 이 들 었 다.
이것 은 Bugly 블 로그 에서 제시 한 효과 그림 입 니 다. 매우 멋 진 모습 을 볼 수 있 습 니 다.
잔말 말고 먼저 효과 도 를 보 여 드 리 겠 습 니 다.
Android:自绘动画实践——以Tencent OS录音机波形为例_第1张图片
사방 으로 날 아 다 니 는 작은 공 과 색깔 이 맞지 않 는 것 외 에 대체적인 효 과 는 많 지 않다 는 것 을 알 수 있다.
다음은 이 효 과 를 어떻게 실현 하 는 지 보 여 준다.
물론 코드 를 직접 보고 싶다 면 끝 을 직접 볼 수 있다.
도형 함수
Bugly 의 블 로그 에서 제시 한 공식 에 따라 우 리 는 먼저 Desmos 도형 계산기 에서 그 려 야 할 도형 을 계산 합 니 다. 다음 과 같 습 니 다.
우 리 는 모두 세 개의 파형 이 있 는데 빨간색 과 파란색 파 는 녹음 파형 의 상하 윤곽 이 고 녹색 파형 은 중간 에 있 으 며 진폭 은 상하 두 파형 의 5 분 의 1 이다.
비록 세 개의 파형 이 있 지만 사실은 우 리 는 하나의 함수 만 필요 하 다. 다른 두 개 는 모두 이 함수 에 대해 간단 한 수학 환산 을 통 해 얻 을 수 있다.
JAVA 로 표현 하면:
    /** *        x   y  * * @param mapX x  * @param offset     * @return */
    private double calcValue(float mapX, float offset) {
        double sinFunc = Math.sin(0.75 * Math.PI * mapX - offset * Math.PI);//   offset * Math.PI    φ
        double recessionFunc = Math.pow(4 / (4 + Math.pow(mapX, 4)), 2.5);
        return 0.5 * sinFunc * recessionFunc;
    }

사인 함수 의 공식 은 y = Asin (ωx+φ)+k, 그 중φ오프셋 입 니 다. 코드 는 offset * Math. PI 를 통 해 이 루어 집 니 다. 그림 을 그 리 는 과정 에서 시간의 흐름 을 오프셋 으로 환산 하면 파형 의 변 화 를 실현 할 수 있 습 니 다. Thread. sleep 에 맞 춰 애니메이션 효 과 를 되 돌 릴 수 있 습 니 다.
그림 에서 빨간색 프레임 을 사용 하여 그 려 진 범 위 는 우리 가 주목 하 는 파형 이 있 는 곳 이 고 수 치 는 다음 과 같다.
x = [-2,2]
y = [-0.5,0.5]

분명히 모든 핸드폰 화면의 크기 가 이 범위 보다 크기 때문에 우 리 는 화면의 좌표 점 을 이 구역 에 일일이 비 춰 야 한다. 또한 Bugly 블 로그 원문 에 따라 우 리 는 샘플링 부분의 점 만 있 으 면 된다. 비 친 코드 는 다음 과 같다.
    //      ,     ,
    //              。
    static final int SAMPLING_SIZE = 64;
    //    X
    float[] samplingX;
    //          [-2,2] X
    float[] mapX;

    if (samplingX == null) {//     
        //      
        width = canvas.getWidth();

        //         
        samplingX = new float[SAMPLING_SIZE + 1];//             +1   
        mapX = new float[SAMPLING_SIZE + 1];//  
        float gap = width / (float) SAMPLING_SIZE;//          
        float x;
        for (int i = 0; i <= SAMPLING_SIZE; i++) {
            x = i * gap;
            samplingX[i] = x;
            mapX[i] = (x / (float) width) * 4 - 2;// x   [-2,2]    
        }
    }

필 자 는 시 뮬 레이 터 에서 샘플링 포 인 트 를 64 개 로 사 용 했 는데 도형 의 가장자리 가 여전히 매우 매끄럽다. 만약 에 낮 거나 높다 고 생각하면 SAMPLING SIZE 의 크기 를 수정 할 수 있다.
우 리 는 파형 함수 가 매 핑 관 계 를 가지 면 파형 상의 모든 샘플링 점 을 쉽게 얻 을 수 있 습 니 다. 그 다음 에 경로 Path 를 사용 하여 샘플링 점 을 연결 하면 됩 니 다. 16ms 의 간격 으로 휴면 그래 픽 스 레 드 를 그린 후에 우 리 는 이러한 효 과 를 얻 을 수 있 습 니 다.
Android:自绘动画实践——以Tencent OS录音机波形为例_第2张图片
여기까지 우 리 는 성공 의 절반 밖 에 남지 않 았 다.
그 라 데 이 션 효과
우 리 는 Bugly 가 제시 한 효과 그림 의 파 내 에 그 라 데 이 션 효과 가 있 는 것 을 볼 수 있 으 며, 아 이 디 어 를 내 는 것 은 Porter DuffXfermode 를 사용 하여 이 루어 지 는 것 이지 만, 원문 에 서 는 그 라 데 이 션 을 그 리 는 사각형 의 위치 계산 방식 을 제시 하지 않 았 다. 좋아, 스스로 하 는 것 도 매우 재 미 있 었 다.
먼저 우 리 는 사각형 의 범 위 를 확정 해 야 한다. 다음 과 같은 그림 이다.
Android:自绘动画实践——以Tencent OS录音机波形为例_第3张图片
분명히 우 리 는 우리 가 필요 로 하 는 점 이 있다 는 것 을 알 수 있다.
1. 현 선과 x 축의 교점
우리 의 샘플링 율 이 결코 높 지 않 기 때문에 우 리 는 y = 0 의 그 샘플링 점 을 찾 을 수 없 을 것 이다. 대신 에 우 리 는 사인 함수 로 절대 치 의 최소 극치 점 을 취 할 수 있다. 그림 과 같다.
Android:自绘动画实践——以Tencent OS录音机波形为例_第4张图片
한 점 의 값 이 옆 두 점 의 값 보다 작 으 면 이 조건 에 부합 한다. 동시에 시작 점 은 x 축 과 뚜렷하게 교차 하 므 로 계산 해 야 한다.
2. 파 봉 점
분명히 우 리 는 사인 행 수의 절대 치 의 최대 극치 점 을 취해 야 한다. 그림 과 같다.
파 봉 점 과 교차점 은 교체 되 어 진행 되 며, 완만 한 곳 에서 정밀도 문제 로 인 한 BUG 를 피하 기 위해 서 는 하나의 표지 교체 로 선택 해 야 합 니 다.
        //      ,     ,       
        float lastV, curV = 0, nextV = (float) (amplitude * calcValue(mapX[0], offset));
        //        ,          
        float absLastV, absCurV, absNextV;
        //                
        boolean lastIsCrest = false;
        //             ,       
        int crestAndCrossCount = 0;

        //       
        for (int i = 0; i <= SAMPLING_SIZE; i++) {
            //        
            x = samplingX[i];
            lastV = curV;
            curV = nextV;
            //           
            nextV = i < SAMPLING_SIZE ? (float) (amplitude * calcValue(mapX[i + 1], offset)) : 0;

            //    
            firstPath.lineTo(x, centerHeight + curV);
            secondPath.lineTo(x, centerHeight - curV);
            //             1/5
            centerPath.lineTo(x, centerHeight + curV / 5F);

            //     
            absLastV = Math.abs(lastV);
            absCurV = Math.abs(curV);
            absNextV = Math.abs(nextV);
            if (i == 0 || i == SAMPLING_SIZE/*    */ || (lastIsCrest && absCurV < absLastV && absCurV < absNextV)/*       ,        */) {
                xy = crestAndCrossPints[crestAndCrossCount++];
                xy[0] = x;
                xy[1] = 0;//    y  0
                lastIsCrest = false;
            } else if (!lastIsCrest && absCurV > absLastV && absCurV > absNextV) {/*       ,      */
                xy = crestAndCrossPints[crestAndCrossCount++];
                xy[0] = x;
                xy[1] = curV;//    
                lastIsCrest = true;
            }
        }

그림% 1 개의 캡 션 을 편 집 했 습 니 다.
    //    
    paint.setColor(Color.BLUE);
    paint.setStyle(Paint.Style.FILL);
    paint.setXfermode(xfermode);
    float startX, crestY, endX;
    for (int i = 2; i < crestAndCrossCount; i += 2) {
        //            。          
        startX = crestAndCrossPints[i - 2][0];
        crestY = crestAndCrossPints[i - 1][1];
        endX = crestAndCrossPints[i][0];

        rectF.set(startX, centerHeight + crestY, endX, centerHeight - crestY);
        canvas.drawRect(rectF, paint);
    }

그 후에 우 리 는 다음 과 같은 효 과 를 얻 을 수 있다.
그 다음 에 그 라 데 이 션 과 SRC IN 의 혼합 모드 를 사용 하면 처음에 제 시 된 효과 도 를 얻 을 수 있 고 여기 서 더 이상 군말 하지 않 습 니 다.
춤 에 대한 작은 점.
우 리 는 Bugly 블 로그 에 파형 외 에 도 몇 개의 날 아 다 니 는 작은 점 이 있 는 것 을 볼 수 있 습 니 다. 그 리 는 점 은 매우 간단 하지만 작은 공이 날 아 다 니 는 경로 함수 박문 은 제시 하지 않 았 습 니 다.
눈 으로 측정 해 보 니 흐 르 는 시간 에 따라 사인 함수 의 값 을 x, y 의 값 으로 환산 할 수 있 을 것 입 니 다. 여 기 는 먼저 구 덩이 를 남기 고 나중에 시간 이 있 으 면 다시 채 웁 시다.
결어
위 에서 실 현 된 Demo 를 달 린 후에 우 리 는 AS 의 Android Monitor 에서 프로그램 이 실행 하 는 메모리 점용 과 CPU 사용률 의 상황 을 볼 수 있 습 니 다. 다음 과 같 습 니 다.
메모리 의 분배 와 GC 는 여전히 매우 완만 하고 4MB 이내 로 안정 적 인 것 을 볼 수 있 지만 CPU 는 약간 폭발 한 것 같 아서 평균 25% 정도 이다. Bugly 의 블 로그 에는 CPU 사용 상황 이 제시 되 지 않 았 지만 필자 가 실현 한 것 보다 훨씬 좋 을 것 이다.
어쨌든 이 데 모 를 실현 함으로써 많은 것 을 배 울 수 있 습 니 다. 여기 서 Bugly 박문 의 작가 에 게 칭찬 을 눌 러 주세요!
마지막 으로 GitHub 주소 보 내기:https://github.com/DrkCore/CoreDemo
'어 머, 괜 찮 네' 라 고 생각 하 시 면 스타 를 주세요. 아니면 스스로 고치 고 싶 으 시 면 포크 를 해 보 세 요.

좋은 웹페이지 즐겨찾기