Canvas API에 대한 자세한 설명(1부)


이 섹션 소개:

우리는 Android에서 일반적으로 사용되는 Paint 클래스의 API를 대부분 자세히 설명하는 13개의 섹션을 사용했습니다. Canvas(드로잉 보드)의 일부 일반적인 API에 대해

  • 에서 호출할 수 있는 몇 가지 메서드를 나열했습니다. 8.3.1 세 가지 그리기 도구 클래스에 대한 자세한 설명
  • , 이를 다음 범주로 나눕니다.
    • drawXxx 메소드 계열: 현재 그리기 영역에 특정 좌표 값으로 그림을 그리면 레이어가 겹쳐집니다. 즉, 나중에 칠한 레이어가 이전에 칠한 레이어를 덮게 됩니다.
    • clipXXX 메소드 계열: 현재 그리기 영역에서 새 그리기 영역을 자릅니다. 그리기 영역은 캔버스 개체의 현재 그리기 영역입니다. 예: clipsRect(new Rect()), 그런 다음 직사각형 영역이 캔버스의 현재 그리기 영역입니다
    • getXxx 메소드 패밀리: 너비, 높이, 화면 밀도 등과 같은 캔버스와 관련된 일부 값을 가져옵니다.
    • save(), restore(), saveLayer(), restoreToCount() 및 레이어를 저장하고 복원하는 기타 방법
    • translate(pan), scale(zoom), Rotate (회전), skew(기울기)

    물론 분산된 방법도 있지만, 이 섹션부터 시작해서 흥미로운 API를 골라서 배워보겠습니다~

    그리고 이 섹션이 먼저 여러분에게 주어질 것입니다 What translate(번역), scale(확대/축소), rotate(회전), skew(기울기)가 가져옵니다. 그리고 save(), restore()에 대한 자세한 설명!

    공식 API 문서: Canvas

    또한 먼저 캔버스에서 X축과 Y축의 방향을 명확히 해야 합니다:

    1.png

1 번역(번역)

방법 : translate(float dx, float dy)

Analogy: 변환, 캔버스의 좌표 원점을 x만큼 왼쪽과 오른쪽으로, y만큼 위아래로 이동합니다. ,0)

Parameter: dx는 수평 방향의 이동 거리, dy는 수직 방향의 이동 거리

사용 예:

for(int i=0; i < 5; i++) {
    canvas.drawCircle(50, 50, 50, mPaint);
    canvas.translate(100, 100);
}
실행 효과:

2.png


2. 회전(회전)

method:rotate(부동 각도) / rotate(부동 각도, 부동 px, 부동 py)

Analytic: 좌표 원점을 기준으로 각도를 회전합니다. 값은 시계 방향으로 양수입니다.

Parameters: 도는 회전 각도, px 및 py가 지정됩니다. 회전 중심점 좌표(px, py)

사용 예:

Rect rect = new Rect(50,0,150,50);
canvas.translate(200, 200);
for(int i = 0; i < 36;i++){
    canvas.rotate(10);
    canvas.drawRect(rect, mPaint);
}

Running effect:

3.png

코드 분석:

여기서 먼저 변환(200, 200)을 호출하여 캔버스의 좌표 원점을 (200,200)으로 이동했습니다. 다시 그려, 그러니까 우리 그리기 결과를 캔버스에 완전히 표시할 수 있습니다. 회전을 (10,200,200)로 설정하면 다음과 같습니다. 결과:

4.png

질문이 있으신가요? 이것은 나중에 이야기할 여러 레이어의 캔버스 개념과 관련이 있습니다~


3.scale(zooming)

method: scale( float sx, float sy) / scale(float sx, float sy, float px, float py)

Analytic: 캔버스 크기 조정

Parameters: sx는 수평 크기 조정 비율, sy는 수직 크기 조정 비율, px, py도 모릅니다. Decimal은 축소를 의미하고integer는 확대를 의미합니다

사용 예:

canvas.drawBitmap(bmp,0,0,mPaint);
canvas.scale(0.8f, 0.8f);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.scale(0.8f, 0.8f);
canvas.drawBitmap(bmp,0,0,mPaint);

실행 효과:

5.png


4.skew( 틸트)

Method: skew(float sx, float sy)

Analytic: 틸트, 베벨, 트위스트로 번역될 수도 있음

매개변수: sx는 해당 틸트 각도입니다. x축 방향, sy는 해당 y축 방향의 기울기 각도이며, 두 값 모두 tan 값입니다! 그것들은 모두 황갈색 값입니다! 그것들은 모두 황갈색 값입니다! 예를 들어, x축 방향으로 60도 기울이려는 경우 소수점 값은 다음과 같습니다. tan 60 = 제곱근 3 = 1.732!

사용 예:

canvas.drawBitmap(bmp,0,0,mPaint);
canvas.translate(200, 200);
canvas.skew(0.2f,-0.8f);
canvas.drawBitmap(bmp,0,0,mPaint);

Running effect:

6.png

5. Canvas 레이어의 개념과 save() 및 Restore()에 대한 자세한 설명

캔버스 캔버스라고 불러요, 어린이 신발은 항상 캔버스를 단순한 도화지라고 생각하기 때문에 그런 생각이 듭니다. 캔버스를 이용하여 멀티레이어 애니메이션을 완성하는 방법이 궁금합니다. 위의 번역 예에서 이유는 무엇입니까? drawCircle(50, 50, 50, mPaint); 참조 좌표는 항상 (50,50)인데 왜 이런 효과가 발생합니까? 의구심이 있는 아이들은 화면의 개념과 캔버스의 개념을 혼동했을 수도 있습니다. 번역이 호출된 범죄 현장:

7.png

그림에 표시된 것처럼 캔버스 좌표의 원점은 x 및 y축에서 매번 100만큼 이동한 다음 (0,0)으로 돌아가고 싶습니다. 다른 지점에서 새로운 모양을 그리는 것은 어떻습니까? 그것을 깨뜨리는 방법, 번역(-100,-100)이 천천히 다시 번역됩니까? 설마 혼란스럽네요...8.jpg

알겠습니다. 얘기는 하지 마세요. 변환 변환을 수행하기 전에 현재 캔버스 상태를 저장할 수 있습니다. 레이어에 대한 지원을 제공하며 이러한 레이어는 "스택 구조"에 따라 관리됩니다

9.png

save() 메서드를 호출하면 현재 캔버스 상태가 저장되고 레이어(레이어)로 추가되어 추가됩니다. 캔버스 스택에, 게다가 이 레이어는 특정 클래스가 아니라 개념적인 것일 뿐입니다!

그리고 restore() 메소드를 호출하면 이전 Canvas 상태가 복원되고 이때 Canvas 레이어 스택이 스택 맨 위에 있는 레이어가 팝업되고, 다음 레이어가 스택 맨 위로 올라오게 됩니다. 이때 캔버스는 스택 맨 위에 저장된 캔버스 상태로 돌아갑니다.

간단히 말하면 : save()는 레이어를 스택에 푸시하고, Restore()는 스택 상단에 레이어를 팝업합니다. 상태! 즉, save()를 여러 번 또는 Restore()를 여러 번 수행할 수 있지만 복원 호출 횟수는 save보다 클 수 없습니다. 그렇지 않으면 오류가 발생합니다! 인터넷에서 대부분의 사람들이 하는 얘기인데, 복원을 해도 실제 테스트에서는 그런 문제가 발생하지 않았습니다. 횟수는 저장횟수 이상이고 오류는 없습니다~ 육안으로 확인해보니 시스템이 변경된 것 같네요~ 다음 테스트에서 여러분께 보여드리겠습니다~10.gif자, 저장 기능 확인을 위해 예제를 작성해 보세요. 복원하다!

예제 작성:

예제 코드:

canvas.save();  //保存当前canvas的状态

canvas.translate(100, 100);
canvas.drawCircle(50, 50, 50, mPaint);

canvas.restore();  //恢复保存的Canvas的状态
canvas.drawCircle(50, 50, 50, mPaint);

실행 결과:

11.png

물론 코드와 결과가 이미 모든 것을 설명했으니 좀 더 복잡하게 만들어 보겠습니다. 다중 저장() 및 복원()!

예제 코드:

canvas.save();

canvas.translate(300, 300);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.rotate(45);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.rotate(45);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.translate(0, 200);
canvas.drawBitmap(bmp, 0, 0, mPaint);

실행 결과:

12.png

결과 분석:

먼저 번역(300,300)하여 그린 다음 45도 회전하여 그린 다음 45도 회전하여 그리고 그런 다음 ( 0,200)을 번역하고, 이 기간 동안은 그리기 전에 매번 save()가 수행됩니다. 이것을 보면 마지막 번역이 200의 y 움직임이 아닙니다. 그런데 왜 왼쪽으로 바뀌었나요? 헤헤, 회전()이 전체 좌표축을 회전시킨다고 말씀드릴까요? 좌표축 변경사항:

13.png

회전()은 알겠죠? 괜찮습니다. 그럼 복원해 볼까요~ 최종 도면이 코앞입니다. 두 개의 복원()을 추가하세요!

canvas.restore();
canvas.restore();
canvas.translate(0, 200);
canvas.drawBitmap(bmp, 0, 0, mPaint);

작업 결과:

14.png

말할 것도 없고 직접 경험해보고 restore()를 더 추가하세요!

15.png

좀 흥미롭네요. 계속해서 restore()

17.png

를 추가해 보겠습니다. 이제 restore를 4번만 저장했기 때문에 더 이상 쓸 수 없는 것 같습니다. 인터넷에서 말하는 바에 따르면, 이렇게 하면 오류가 보고됩니다. 정말 그렇습니까? 여기서는 현재 스택을 가져오기 위해 Canvas에서 제공하는 것을 호출합니다. 몇 개의 레이어 메소드가 있습니까: getSaveCount(), save() 및 Restore() 전후; 스택의 레이어 수를 인쇄하려면 로그를 추가하세요.

18.png

결과는 정말 만족스럽습니다. 결국, 연습을 통해 진정한 지식을 얻게 되었을 수도 있고, 여기에서는 다른 이유가 있을 수도 있습니다. 알아내려면 소스 코드를 살펴봐야 합니다. 시간 제약으로 인해 여기서는 복원 횟수가 저장 횟수보다 많을 수 있다는 것을 알고 있습니다. 하지만 그래도 불필요한 문제를 피하기 위해 저장보다 복원 빈도를 줄이는 것이 좋습니다~ 스택에 들어가고 나가는 과정은 따로 설명하지 않겠습니다. 제가 직접 그려서 이해하기 매우 쉽습니다!


6.SaveLayer() 및 RestoreToCount() 설명

사실 이 두 가지 방법은 저장 및 복원과 유사하지만 후자를 기반으로 하는 것이 몇 가지 더 있습니다. 예를 들어 saveLayer()에는 다음과 같은 오버로드된 메서드가 있습니다.

19.png

save() 메서드는 전체 Canvas를 저장하는 반면, saveLayer()는 특정 영역을 선택적으로 저장할 수 있다는 것을 이해할 수 있습니다. 또한, 식사 및 숙박에 int saveFlags가 있는 것을 볼 수 있습니다. 이는 저장할 개체를 변경하는 설정입니다! 선택적 값은 다음과 같습니다:

태그 설명
ALL_SAVE_FLAG모든 상태 저장
CLIP_SAVE_FLAG 잘린 영역의 상태 저장
CLIP_TO_LAYER_SAVE_FLAG 상태 저장 사전 설정 범위에서
FULL_COLOR_LAYER_SAVE_FLAG컬러 코팅 저장
HAS_ALPHA_LAYER_SAVE_FLAG불투명 레이어 저장
MATRIX_SAVE_FLAG행렬 정보(변환, 회전, 크기 조정, 기울이기) 상태 저장

PS: 위 설명에 잘못된 내용이 있습니다. 작성자의 영어 수준이 낮아 틀린 내용이 있을 수 있으니 꼭 정정해 주시기 바랍니다. 확인 :

CLIP_TO_LAYER_SAVE_FLAG

모드를 선택하여 예제를 작성합니다

구현 코드

:

RectF bounds = new RectF(0, 0, 400, 400);
canvas.saveLayer(bounds, mPaint, Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.drawColor(getResources().getColor(R.color.moss_tide));
canvas.drawBitmap(bmp, 200, 200, mPaint);
canvas.restoreToCount(1);
canvas.drawBitmap(bmp, 300, 200, mPaint);

실행 결과

:

20.png나중에 saveLayer()를 사용하여 자세히 연구하겠습니다~여기는 대략적인 아이디어~

그런 다음

restoreToCount(int)

로 이동하세요. 이 방법은 더 간단합니다. 복원할 레이어 수를 직접 전달하면 됩니다. 해당 레이어로 직접 점프하고 동시에 해당 레이어 위의 모든 레이어를 스택에서 쫓아냅니다. 스택의 최고가 되어보세요~! 여러 개의 Restore()를 작성하는 것보다 훨씬 편리하고 빠릅니다~

7. 이 섹션에서 코드 샘플을 다운로드하세요.

글쎄, 코드는 테스트용으로 작성된 것이므로 여기에 오는 것은 별로 흥미롭지 않지만 아마도 독자들은 여전히 원하시면 링크만 올려주세요!

코드 다운로드

: CanvasDemo.zip아마 이것이 바로 당신이 원하는 사진일 것입니다! 하하~

21.jpg

이 섹션 요약:

이 섹션을 작성하는 데 며칠이 걸렸습니다. 왜냐하면 작성자가 처음에 이 캔버스 레이어에 대한 명확한 개념을 갖고 있지 않았기 때문입니다. 오늘 오후에 일을 마치고 생각을 하다가 저녁에 야근을 하게 되었는데, 드디어 도움이 될 것 같아 이 글을 쓰게 되었습니다. 누구나 Canvas를 더 명확하게 이해하고 고급 사용자 정의 컨트롤을 사용하면 헷갈리지 않을 것입니다 ~ 헤헤, 여기까지입니다. 틀린 부분이 있으면 지적해주시면 감사하겠습니다~

21.gif