You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
npm에 올라간 패키지를 받아서 씁니다. 같은 저장소 안의 packages/webcanvas/dist/가 아니었습니다.
웹 1주차 때 webcanvas를 빌드하느라 한참 걸렸는데, 그 결과물이 이 두 앱이랑은 상관이 없었던 셈입니다. 개발 가이드에 "로컬 빌드를 다른 프로젝트에서 테스트하려면 npm install /path/to/packages/webcanvas로 교체한다"는 문장이 있었는데, 왜 그런 안내가 있는지 이제 알 것 같습니다. 그냥 두면 npm 버전을 보니까 코어를 고쳐도 반영이 안 되는 거였습니다.
Playground 화면 아래에 ThorVG v1.1.0 · GL이 뜨는데 이것도 npm에서 받은 버전인 것 같습니다.
즉 예제에 적힌 초기화 코드는 보여주기용이고, 실제로는 Playground가 들고 있는 TVG랑 Canvas가 들어갑니다. 화면 위에서 렌더러를 SW/GL/WG로 바꿀 수 있는 것도 이 구조 때문인 것 같습니다. 예제가 렌더러를 직접 고르는 게 아니라 값만 뽑아서 공용 초기화에 넘기는 식으로 보입니다.
예제를 복사해서 다른 데 붙여도 돌아가게 초기화 코드는 남겨두고, 실행은 공용 환경에서 하는 절충 아닐까 싶습니다.
화면을 갱신하는 두 가지 방식
예제를 둘러보다가 이름이 비슷한 두 개가 서로 다른 방식을 쓰는 걸 봤습니다.
update.ts는 매 프레임 캔버스를 비우고 Shape를 새로 만듭니다.
canvas.clear();constshape=newTVG.Shape();// ... 모양과 색을 다시 지정canvas.add(shape);canvas.render();
direct-update.ts 쪽에 //fill property will be retained라는 주석이 있습니다. 한 번 정한 색은 그대로 두고 바뀌는 것만 갱신한다는 뜻인 것 같습니다.
같은 걸 만드는 두 가지 길이 예제로 나란히 들어 있는 게 재밌었습니다.
커스텀 예제: Polygon Slicing
도형을 드래그로 그은 직선을 따라 두 조각으로 나누는 예제를 만들었습니다. 잘린 조각은 사라지지 않고 남아서 다시 자를 수 있고, 잘릴 때마다 절단선의 수직 방향으로 밀려나면서 감속해 멈춥니다.
공통 2주차 과제에서 비슷한 걸 C++로 만들었어서, 이번엔 알고리즘만 TypeScript로 옮기고 WebCanvas API에 맞췄습니다. 해커톤에서 쓸 부분이라 웹에서도 되는지 확인해보고 싶기도 했습니다.
자르는 방법
반평면 클리핑(Sutherland-Hodgman)을 씁니다. 자르는 직선을 기준으로 평면이 둘로 나뉘는데, 도형의 꼭짓점을 순서대로 돌면서 남길 쪽 점만 모읍니다. 한 점은 남기는 쪽인데 다음 점은 버리는 쪽이면 그 변이 선을 넘어간 거라서 교차점을 계산해 끼워넣습니다.
네이티브랑 다른 게 하나 있었습니다. C++에서는 strokeFill()과 strokeWidth()가 따로였는데 WebCanvas에서는 stroke({ width, color }) 하나로 합쳐져 있습니다. 그냥 이름만 바꾸면 되는 줄 알고 썼다가 안 돼서 stroke.ts 예제를 열어보고 알았습니다.
배열에 "alphabetically sorted by title"이라는 주석이 있어서 어디 넣어야 하나 좀 봤는데, 변수명이 아니라 title 기준이었습니다. basicShapesExample이 S 자리에 있는 게 title이 "Shapes"라서였습니다.
thumbnail은 types.ts에서 선택 항목이길래 처음엔 안 넣었습니다. 그런데 목록에서 제 것만 이미지 없이 기본 아이콘으로 나와서 결국 만들었습니다. 기존 썸네일을 하나 열어보니 1050×1050이라 크기를 맞췄습니다.
아직 모르는 것
조각이 수백 개가 됐을 때도 괜찮은지 확인 못 했습니다. 지금은 매 프레임 모든 Shape를 새로 만들고 있어서 정지한 조각까지 다시 만드는 낭비가 있습니다. direct-update.ts 방식이 나을 것 같은데 시간이 없어서 못 해봤습니다.
perf-test의 yarn bench를 못 돌려봤습니다.
perf-test에서 애니메이션 개수를 늘렸을 때 그 개수가 매 프레임 다 그려지는 건지, 화면에 보이는 것만 그려지는 건지 확인 못 했습니다.
WebGL이랑 Software가 FPS가 얼마나 차이나는지 비교 안 해봤습니다.
new Function으로 예제 코드를 실행하는 부분은 대충 무슨 일이 일어나는지만 알겠고, 왜 굳이 이렇게 했는지는 잘 모르겠습니다.
마치며
두 앱이 npm 패키지를 쓴다는 걸 안 게 이번에 제일 도움이 됐습니다. 웹 1주차에 빌드한 결과물이랑 이어져 있는 줄 알았는데 아니었습니다.
예제를 추가하는 것 자체는 파일 하나에 등록 두 줄이라 생각보다 간단했습니다. 다만 어떤 API가 있는지는 기존 예제를 하나씩 열어보면서 확인해야 했습니다. canvas.remove()가 있을 줄 알고 썼다가 안 돼서 찾아보니 예제 어디에도 안 쓰이고 있었고, canvas.clear()를 쓰더군요.
돌아가게 만드는 거랑 저장소에 맞게 넣는 게 다른 일이라는 것도 느꼈습니다. 들여쓰기가 2칸인지 4칸인지, 파일 끝에 개행이 있는지 같은 건 동작에는 상관없는데 다른 예제들이랑 나란히 놓이면 티가 납니다. 커밋 전에 git diff를 한 번 보고 넘어가야겠습니다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
웹 트랙 2주차 과제로 perf-test와 playground를 로컬에서 빌드해 구동해보고, Playground에 다각형 자르기 예제를 하나 추가했습니다.
빌드와 구동
두 앱 모두
thorvg.web저장소 안에 있는데, 루트의 pnpm 워크스페이스와 따로 yarn을 씁니다. 각 디렉터리에서 따로 설치해야 했습니다.둘 다 Next.js 기반이고 별 문제 없이 떴습니다.
perf-test
상단에서 렌더러(Software / WebGL / WebGPU), 애니메이션 개수, 크기를 고르고 Apply를 누르면 그 조건으로 Lottie를 한 화면에 깔아줍니다. 좌하단에 FPS, MS, 메모리가 실시간으로 찍힙니다.
WebGL로 20개, 150px에서 60 FPS, 49 MB가 나왔습니다.
URL에
?seed=...가 붙는 게 눈에 띄었습니다. 어떤 Lottie 조합이 뽑혔는지를 URL에 넣어두는 것 같습니다. 같은 seed로 다시 열면 같은 조합이 나올 테니 렌더러를 바꿔가며 비교할 때 쓰라는 것 아닐까 싶습니다.package.json에yarn bench가 있고 playwright가 들어 있는 걸 보면 브라우저를 자동으로 띄워서 벤치마크를 돌리는 것도 되는 모양인데, 이번엔 못 돌려봤습니다.playground
WebCanvas 예제들이 카드로 쭉 나열되고, 카드를 누르면 왼쪽에 캔버스 오른쪽에 코드 편집기가 있는 화면이 열립니다. 코드를 고치면 바로 반영됩니다.
WebCanvas와 어떻게 연결되어 있나
과제에서 물어본 부분이라 여기를 좀 봤습니다.
두 앱의
package.json에 이렇게 되어 있습니다.그리고
playground/components/CanvasPreview.tsx의 첫 줄이 이렇습니다.npm에 올라간 패키지를 받아서 씁니다. 같은 저장소 안의
packages/webcanvas/dist/가 아니었습니다.웹 1주차 때 webcanvas를 빌드하느라 한참 걸렸는데, 그 결과물이 이 두 앱이랑은 상관이 없었던 셈입니다. 개발 가이드에 "로컬 빌드를 다른 프로젝트에서 테스트하려면
npm install /path/to/packages/webcanvas로 교체한다"는 문장이 있었는데, 왜 그런 안내가 있는지 이제 알 것 같습니다. 그냥 두면 npm 버전을 보니까 코어를 고쳐도 반영이 안 되는 거였습니다.Playground 화면 아래에
ThorVG v1.1.0 · GL이 뜨는데 이것도 npm에서 받은 버전인 것 같습니다.Playground가 예제 코드를 실행하는 방식
여기가 생각했던 거랑 달랐습니다.
예제 파일을 열어보면 초기화 코드가 들어 있습니다.
그래서 예제마다 각자 초기화를 하는 줄 알았는데,
lib/code-transformer.ts가 실행 전에 이 부분을 지웁니다. 그리고CanvasPreview가 미리 만들어둔 걸 넣어줍니다.즉 예제에 적힌 초기화 코드는 보여주기용이고, 실제로는 Playground가 들고 있는 TVG랑 Canvas가 들어갑니다. 화면 위에서 렌더러를 SW/GL/WG로 바꿀 수 있는 것도 이 구조 때문인 것 같습니다. 예제가 렌더러를 직접 고르는 게 아니라 값만 뽑아서 공용 초기화에 넘기는 식으로 보입니다.
예제를 복사해서 다른 데 붙여도 돌아가게 초기화 코드는 남겨두고, 실행은 공용 환경에서 하는 절충 아닐까 싶습니다.
화면을 갱신하는 두 가지 방식
예제를 둘러보다가 이름이 비슷한 두 개가 서로 다른 방식을 쓰는 걸 봤습니다.
update.ts는 매 프레임 캔버스를 비우고 Shape를 새로 만듭니다.direct-update.ts는 Shape를 계속 들고 있으면서 경로만 다시 그립니다.direct-update.ts쪽에//fill property will be retained라는 주석이 있습니다. 한 번 정한 색은 그대로 두고 바뀌는 것만 갱신한다는 뜻인 것 같습니다.같은 걸 만드는 두 가지 길이 예제로 나란히 들어 있는 게 재밌었습니다.
커스텀 예제: Polygon Slicing
도형을 드래그로 그은 직선을 따라 두 조각으로 나누는 예제를 만들었습니다. 잘린 조각은 사라지지 않고 남아서 다시 자를 수 있고, 잘릴 때마다 절단선의 수직 방향으로 밀려나면서 감속해 멈춥니다.
공통 2주차 과제에서 비슷한 걸 C++로 만들었어서, 이번엔 알고리즘만 TypeScript로 옮기고 WebCanvas API에 맞췄습니다. 해커톤에서 쓸 부분이라 웹에서도 되는지 확인해보고 싶기도 했습니다.
자르는 방법
반평면 클리핑(Sutherland-Hodgman)을 씁니다. 자르는 직선을 기준으로 평면이 둘로 나뉘는데, 도형의 꼭짓점을 순서대로 돌면서 남길 쪽 점만 모읍니다. 한 점은 남기는 쪽인데 다음 점은 버리는 쪽이면 그 변이 선을 넘어간 거라서 교차점을 계산해 끼워넣습니다.
어느 쪽인지는 외적 부호로 봅니다.
한쪽 부호로 한 번, 반대로 한 번 돌리면 조각 두 개가 나옵니다.
볼록 도형을 직선으로 자르면 두 조각도 볼록이라, 오각형으로 시작하면 여러 번 잘라도 이 방법의 전제가 안 깨집니다.
WebCanvas 쪽
계산은 전부 그냥 자바스크립트고, WebCanvas는 결과를 그리는 데만 씁니다.
네이티브랑 다른 게 하나 있었습니다. C++에서는
strokeFill()과strokeWidth()가 따로였는데 WebCanvas에서는stroke({ width, color })하나로 합쳐져 있습니다. 그냥 이름만 바꾸면 되는 줄 알고 썼다가 안 돼서stroke.ts예제를 열어보고 알았습니다.마우스 입력은
lottie-interaction.ts를 참고했습니다. 캔버스 요소에pointerdown/pointermove/pointerup을 붙이고, 이벤트 좌표를 캔버스 좌표로 바꿔서 씁니다.캔버스가 화면에서 확대·축소될 수 있으니
rect.width로 비율을 맞춰야 좌표가 안 어긋난다고 합니다.갱신은
update.ts쪽 방식으로 갔습니다. 매 프레임canvas.clear()하고 조각들을 다시 그립니다.예제 등록
lib/examples/에 파일을 만들고lib/examples/index.ts에 두 줄을 추가하면 목록에 나타납니다.배열에 "alphabetically sorted by title"이라는 주석이 있어서 어디 넣어야 하나 좀 봤는데, 변수명이 아니라 title 기준이었습니다.
basicShapesExample이 S 자리에 있는 게 title이 "Shapes"라서였습니다.thumbnail은types.ts에서 선택 항목이길래 처음엔 안 넣었습니다. 그런데 목록에서 제 것만 이미지 없이 기본 아이콘으로 나와서 결국 만들었습니다. 기존 썸네일을 하나 열어보니 1050×1050이라 크기를 맞췄습니다.아직 모르는 것
direct-update.ts방식이 나을 것 같은데 시간이 없어서 못 해봤습니다.yarn bench를 못 돌려봤습니다.new Function으로 예제 코드를 실행하는 부분은 대충 무슨 일이 일어나는지만 알겠고, 왜 굳이 이렇게 했는지는 잘 모르겠습니다.마치며
두 앱이 npm 패키지를 쓴다는 걸 안 게 이번에 제일 도움이 됐습니다. 웹 1주차에 빌드한 결과물이랑 이어져 있는 줄 알았는데 아니었습니다.
예제를 추가하는 것 자체는 파일 하나에 등록 두 줄이라 생각보다 간단했습니다. 다만 어떤 API가 있는지는 기존 예제를 하나씩 열어보면서 확인해야 했습니다.
canvas.remove()가 있을 줄 알고 썼다가 안 돼서 찾아보니 예제 어디에도 안 쓰이고 있었고,canvas.clear()를 쓰더군요.돌아가게 만드는 거랑 저장소에 맞게 넣는 게 다른 일이라는 것도 느꼈습니다. 들여쓰기가 2칸인지 4칸인지, 파일 끝에 개행이 있는지 같은 건 동작에는 상관없는데 다른 예제들이랑 나란히 놓이면 티가 납니다. 커밋 전에
git diff를 한 번 보고 넘어가야겠습니다.All reactions