레이블이 canvas인 게시물을 표시합니다. 모든 게시물 표시
레이블이 canvas인 게시물을 표시합니다. 모든 게시물 표시

2013년 4월 20일 토요일

[BigScatterChart] 대용량 스캐터 차트 개발 공유


1. 요구조건
 - 50만개 이상에도 끄떡없는 대용량 스케터 차트
 - 마우스 드래그시 해당 영역의 스캐터를 반환해야 함
 - 스캐터 점의 타입이 여러개가 될 수 있음
 - 특정 주기마다 차트가 업데이트 될 수 있음

2. 기존 스캐터 차트
 - d3.js visualization을 이용하여 개발되었음
 - SVG를 이용하고, d3.js에서 기본적으로 제공하는 마우스 이벤트나 xy축 자동 계산, formating등등이 용이함
 - 상단의 스캐터 차트는 약 8만개의 점을 그리고 있음
 - 8만개를 한번에 로딩해서 불러오지 않고, 5천개씩 끊어서 로딩 후 그림
 - 다 그린 후 약 8만개의 DOM Elements가 생성됨
 - 메모리가 여유가 없을 경우, 차트를 그리는 이외의 작업을 할 수가 없음
 - 마우스 드래그 검색시, 선택 영역이 커질 수록 반응 속도가 느림

3. 리서치한 다른 스캐터 차트
  - SVG를 이용하며, 기능이 d3.js에 비해 많이 부족함, 이럴바엔 d3.js를 사용하는게 나음

 3.2 NVD3.js Scatter Chart (http://nvd3.org/ghpages/scatter.html)
  - d3.js를 이용하여 개발되었음
  - 마우스 오버시, 가이드 라인기능
  - Magnify 기능을 이용하여 해당 부분을 마우스를 이용하여 돋보기 할 수 있음
  - UI에서 드래그선택 기능을 제외하고 필요한 기능은 이미 개발 되어 있음
  - 하지만, 50만개 점을 그릴때 여전히 SVG는 50만개의 DOM Elements를 만들어서 느림
  - BSD License

 3.3 canvasXpress Scatter Chart (http://canvasxpress.org/scatter2d.html)
  - Canvas를 이용함, DOM Element가 거의 필요 없음
  - 마우스 영역 선택시, 해당 부분 확대 기능
  - 스캐터 점에 따라 회귀선 또는 분포선이 자동으로 그려짐
  - 3D 스케터도 지원함 (http://canvasxpress.org/scatter3d.html
  - LGPL 3.0 License.

 3.4 moochart (http://moochart.coneri.se/)
  - Canvas를 이용함
  - 너무 심플하여 기능 개발이 많이 필요함
  - MooTools javascript framework에 종속적임
  - MIT License

 3.5 결론
  - 이외에도 여러가지 차트가 많이 있다. svg를 이용하여 개발할 경우 DOM을 이용하여 각종 이벤트를 제어 가능하기에 사용자를 만족시킬 수 있는 인터렉션을 쉽게 개발 할 수 있다. 하지만 Bubble(스캐터 점)이 늘어 날 수록 DOM의 갯수가 늘어나 브라우저가 느려진다.
그래서 많은 양의 데이터는 2D 캔버스를 이용하여 그리는 것이 성능에는 좋다. 왜냐하면 필요한 DOM만 가지고 있기 때문이다. 리서치 한 결과 canvasXpress의 Scatter Chart가 Mash up 개발을 하기에 적합하였으나, 라이선스문제와 불필요한 기능들로 인한 성능 저하 예상으로 포기하였다. 대안으로 moochart를 이용하여 필요한 기능들만 추가 개발하려고 하였으나, jQuery가 아닌 MooTools을 이용하여 개발되었기에 moochart의 컨셉만을 가지고 새로 개발하기로 한다.

4. BigScatterChart

 4.1 주요 피처
  - 50만개 이상의 점을 찍더라도 느려지지 않음
  - 상단 Type 클릭시 보기, 감추기
  - 상단 Type 드래그&드랍 시, 스캐터 차트 Layer 순서 변경
  - 차트 영역에서 드래그 & 드랍시 셀렉트박스로 해당 부분 선택
  - 드래그 셀렉팅 후 스캐터 차트 영역에 맞게 맞추기
  - 드래그 설렉팅 후 해당 영역 검색
  - 특정 주기로 차트 업데이트시, 드래그 셀렉팅 영역도 같이 이동
  - 특정 주기로 차트 업데이트시, 약0.004s 시간 소요(50만개 전체 업데이트시, 약4초 소요)
  - 각종 커스텀 이벤트 제공
 4.2 성능개선
  - SVG에서 Canvas로 변경하여, 성능저하 요인인 DOM Elements를 최소화
  - 특정 주기 업데이트시, 한번 Canvas에 그린 스캐터 버블은 다시 그리지 않고, 해당 영역을 이동 후 추가분만 그리기
  - 가이드라인 Canvas와 스캐터 Canvas를 분리하여, 불필요한 작업을 줄이고, Type별로 Canvas를 또 분리하여 Type별로 제어가 가능함
  - 스캐터 테이터를 1차원 배열에 저장하지 않고, 2차원 배열에 저장함으로써, array[들어온 순서][데이터] 로 분리하고, arrayInfo[들어온 순서] 에서 최소, 최대값등등의 정보를 캐싱 함
  - 드래그 셀렉팅 검색시, x, y, width, height를 x-from, x-to, y-from, y-to로 파싱하고, 스캐터 데이터에서 보다 효율적으로 검색하기 위해 arrayInfo에 캐싱된 정보이용하여 1차 판별 후,  2차 검색을 실시하여 결과를 리턴
  - 특정 주기로 업데이트시, 사라지는 영역의 데이터 버림
  - 상단 Type 드래그 소팅시 Canvas Layer의 순서를 변경할 때, jQuery의 before, after 메소드를 이용하지 않고, z-index 값으로만 조정. 이유 : jQuery before, after는 해당 DOM Element를 Clone 하여 복사하고, 기존 값은 지우는데, 이때 Canvas의 Context는 복제하지 않음. Canvas용 before, after를 만들 수도 있지만, z-index 변경이 더 심플하고, 강력함.

5. 성능 비교
비교
기존(D3.js)
8만개 실데이터
신규(BigScatterChart)
50만개 랜덤데이터
렌더링 속도
약 33초
약 6초
렌더링 메모리
150 ~ 250M
50 ~ 80M
드래그 셀렉팅 속도
3초이상
0.2초 이내
드래그 셀렉팅 메모리
80M 이내
20M 이내
(위 성능 비교 자료는 iMac 10.8.3, 2.7Ghz, 16G, 크롬 26.0 버전에서 '활성 상태 보기' 유틸리티를 이용하여 이루어짐)

6. Feedback
 - 이밖에 BigScatterChart 성능 개선 관련하여 좋은 아이디어를 가지고 계시면 공유 부탁드립니다.

감사합니다.

2012년 7월 10일 화요일

모바일 이벤트 프로토타입

모바일에서 터치로 할 수 있는 이벤트 3가지를 제작해 보았습니다. http://dev.iamdenny.com/Mobile-Events/index.html

  1. 복권 긁기 이벤트
Canvas, jQuery Mobile을 사용하였습니다. 이미지가 하단에 배치되어 있고, 그 위에 Canvas가 겹쳐져 있도록 하였습니다. 그리고 터치가 시작될 때(vmousedown), Canvas에서 Line을 그리기를 시작하고, 터치가 이동할 때(vmousemove)마다 Line을 그리도록 하였습니다. 다만 Line의 색은 투명하도록 Canvas 설정하였습니다(oCtx.globalCompositeOperation = 'destination-out', 참고 : https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html). 터치가 끝났을 때(vmouseup)에는 지워진 픽셀 수를 계산하여, 70% 이상이 지워졌을 때, 당첨 또는 꽝을 알리도록 하였습니다.








2. 화분 물주기 이벤트


 CSS3 Animation과 Jindo Mobile Component를 이용하여 개발하였습니다. 구름과 화분 사이를 손으로 수차례 긁으면 비가오고, 화분이 자라는 이벤트 입니다. JMC의 Touch 모듈을 사용하였고, 터치가 위/아래로 70px 이상일때만 'touchmove' 발생하도록 하였습니다. 'touchmove'가 발생하는 횟수에 따라 -webkit-animation을 이용하여 비의 속도를 점점 빠르게 하였습니다.

3. 프리킥 이벤트
 CSS3 Animation + Jindo Mobile Component를 이용하여 개발하였습니다. CSS3를 이용하여 왼쪽, 가운데, 오른쪽으로 공이 움직일 수 있는 것과 선수가 공을 찬 후의 상태를 적절히 class로 만들어 놓았고, JMC의 DragArea & DropArea 모듈을 이용하여, 축구공은 Draggable, 골대 이미지 위의 떠 있는 왼쪽, 가운데, 오른쪽의 투명 레이어를 Droppable로 하였습니다. 그래서 Drop이 발생할 때, 축구 선수와 공의 class 이름을 변경 하였습니다.

Gracias.