Android: 자체 애니메이션 실천 - Tencent OS 녹음기 파형 을 예 로 들 면
요 며칠 동안 졸업 과 같은 일 로 인해 블 로 그 를 쓰 지 않 았 습 니 다. 마침 최근 에 Bugly 가 발표 한 셀 프 애니메이션 에 관 한 블 로그 인 을 보 았 습 니 다. 깊이 있 게 썼 지만 아 쉽게 도 소스 코드 를 넣 지 못 했 습 니 다.경탄 한 나머지 직접 바퀴 를 만 들 생각 이 들 었 다.
이것 은 Bugly 블 로그 에서 제시 한 효과 그림 입 니 다. 매우 멋 진 모습 을 볼 수 있 습 니 다.
잔말 말고 먼저 효과 도 를 보 여 드 리 겠 습 니 다.
사방 으로 날 아 다 니 는 작은 공 과 색깔 이 맞지 않 는 것 외 에 대체적인 효 과 는 많 지 않다 는 것 을 알 수 있다.
다음은 이 효 과 를 어떻게 실현 하 는 지 보 여 준다.
물론 코드 를 직접 보고 싶다 면 끝 을 직접 볼 수 있다.
도형 함수
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 의 간격 으로 휴면 그래 픽 스 레 드 를 그린 후에 우 리 는 이러한 효 과 를 얻 을 수 있 습 니 다.
여기까지 우 리 는 성공 의 절반 밖 에 남지 않 았 다.
그 라 데 이 션 효과
우 리 는 Bugly 가 제시 한 효과 그림 의 파 내 에 그 라 데 이 션 효과 가 있 는 것 을 볼 수 있 으 며, 아 이 디 어 를 내 는 것 은 Porter DuffXfermode 를 사용 하여 이 루어 지 는 것 이지 만, 원문 에 서 는 그 라 데 이 션 을 그 리 는 사각형 의 위치 계산 방식 을 제시 하지 않 았 다. 좋아, 스스로 하 는 것 도 매우 재 미 있 었 다.
먼저 우 리 는 사각형 의 범 위 를 확정 해 야 한다. 다음 과 같은 그림 이다.
분명히 우 리 는 우리 가 필요 로 하 는 점 이 있다 는 것 을 알 수 있다.
1. 현 선과 x 축의 교점
우리 의 샘플링 율 이 결코 높 지 않 기 때문에 우 리 는 y = 0 의 그 샘플링 점 을 찾 을 수 없 을 것 이다. 대신 에 우 리 는 사인 함수 로 절대 치 의 최소 극치 점 을 취 할 수 있다. 그림 과 같다.
한 점 의 값 이 옆 두 점 의 값 보다 작 으 면 이 조건 에 부합 한다. 동시에 시작 점 은 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
'어 머, 괜 찮 네' 라 고 생각 하 시 면 스타 를 주세요. 아니면 스스로 고치 고 싶 으 시 면 포크 를 해 보 세 요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
SwiftUI에서 Lottie를 사용하여 풍부한 애니메이션을 쉽게 실현해보세요이하의 기사를 이전 썼지만, 최근 SwiftUI를 사용해 Lottie를 이용했으므로 그 방법에 대해서 써 간다. Lottie에 관한 설명은 여러가지 기사에서도 되고 있으므로 여기서는 언급하지 말고, SwiftUI상에...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.