-
Notifications
You must be signed in to change notification settings - Fork 459
FAQ
엔트리 웹서비스는 기본적으로 entryjs와 아래의 주요 웹서비스 컴포넌트들로 구성되어 있습니다.
- Entry : expressjs 기반 웹 프로젝트
- entry-lms : React 기반 웹 컴포넌트
- EntryMaker : React 기반 웹 컴포넌트
- literallycanvas : React 기반 컨버스 라이브러리
literallycanvas 를 제외하고 모두 사내 Private GIT 에서 관리되고 있으므로 코드는 공개가 불가합니다만, angularjs나 그외 엔트리가 사용하는 라이브러리들과 마챦가지로 반드시 필요한 요소가 아니므로 entryjs를 중심으로 자주하는 질문들에 대해 기술 하도록 하겠습니다.
엔트리에 오브젝트를 추가하기에 앞서 엔트리 프로젝트의 구조(Scheme)에 대해서 숙지할 필요가 있습니다. entryjs github에 상세한 설명이 있으니 참고하시기 바랍니다.
최초, 엔트리 만들기 워크스페이스 진입시 Inject 되는 프로젝트는 Entry.getStartProject 함수의 리턴값입니다. 그중, 최상위의 "objects" 배열요소에 추가되는 객체가 "엔트리봇" 오브젝트 입니다. 각 오브젝트는 selector로 사용할 "id"와 이름등의 메타정보와 스크립트, 스테이지에서 보여질 엔티티, 스프라이트등으로 구성됩니다.
여기에서, 사용자에게 노출되는 오브젝트란 스프라이트를 지칭하며, 스프라이트는 소리(sounds)와 모양(pircutres)으로 구성됩니다. 최소 하나의 모양이 필요하며 소리는 optional 입니다. 각각의 요소는 selector("id")와 메타정보를 가지며 "fileurl" 또는 "filename" 요소가 실제 이미지 또는 사운드 파일의 위치를 가르킵니다.
즉, 오브젝트를 추가하려면 이미지와 소리들로 미리 구성된 스프라이트라는 set 이 필요합니다. 엔트리가 제공하는 기본 오브젝트란 이런 모양과 소리의 데이터베이스 set 입니다. 모양과 소리 또한 기본적으로 제공되는 asset들이 있으며, 사용자가 업로드한 이미지 파일 하나로도 스프라이트를 구성할 수 있습니다.
아래 코드는 엔트리에서 업로드한 모양을 스프라라이트로 추가하는 코드의 일부 입니다.
// item 은 업로드한 파일의 정보 입니다.
const object = {
id: Entry.generateHash(),
objectType: 'sprite',
sprite: {
name: item.name,
pictures: [item],
sounds: [],
category: {}
}
};
Entry.container.addObject(object, 0);
위와 같이 object를 생성하고 container 에 추가해 주면 됩니다.
위 코드에서 item변수는 업로드한 이미지의 메타정보로서 이미지 경로, 표시할 이름, 크기(배율), 비트맵 pixel 크기(width, height)와 같은 정보가 포함됩니다.
소리(sound)의 경우에도 확장자(.mp3, .wav등)와 이름, 재생시간(초단위)과 같은 정보가 포함됩니다.
이런 메타정보는 직접 입력하거나, 업로드시 서버에서 또는 프론트에서등 다양한 방법으로 추출하실 수 있습니다.
그림판의 상단 메뉴는 Entry.Painter의 p.initTopBar 함수에서 DOM을 직접 생성하고 있습니다. 각 메뉴 Dom에서 click 이벤트를 바인딩하고 있으며, 해당 바인딩 함수내에서 저장, 자르기등의 기능을 수행합니다.
각 기능은 크게 서버사이드 api를 호출하는 부분과 literallycanvas의 함수를 호출하는 기능으로 나눌수 있으며, 서버사이드 api호출은 Entry.dispatchEvent 함수로 이벤트를 발생시키고 웹페이지에서 해당 이벤트가 발생할 경우 api를 호출하는 형태로 구현되어 있습니다.
p.file_save = function (taskParam) {
this.lc.trigger("dispose"); // 캔버스 정리
var dataURL = this.lc.getImage().toDataURL(); // 캔버스에서 비트맵 추출
this.file_ = JSON.parse(JSON.stringify(this.file)); // 이미지 정보
Entry.dispatchEvent(
'saveCanvasImage',
{ file: this.file_, image: dataURL, task: taskParam }
); // 캔버스 이미지를 저장하기위해 이벤트 발생
this.file.modified = false; // 저장후 현재상태 변경
};
위와 같이 Painter에서 저장하기 버튼 클릭시 literallycanvas 기능을 호출하고, 이벤트를 발생시키면 현재 워크스페이스내 웹페이지에서 이벤트를 받아 실제 저장하기 위한 서버 api를 호출 합니다.
// 웹페이지 js
addEventListener('saveCanvasImage', $scope.saveCanvasData); // 이벤트 수신
$scope.saveCanvasData = function(data) {
var upload = $.ajax({
url: '/api/picture/canvas',
data: formData,
...});
}
그외, literallycanvas에서 삭제, 수정등의 이벤트가 발생할 경우 entryjs 의 undo/redo stack에 해당 기능을 추가하고 파일이 수정되었음(this.file.modified)을 추적하고 있습니다.
오브젝트 추가하기 참고
워크스페이스에서 힌트영역은 Entry.PropertyPanel 컴포넌트로, 엔진하단에 "propertyPanel" class요소로 추가됩니다. properyPanel은 좌측에 peropertyTab 영역과 propertyContent 영역으로 구분되며, p.addMode 함수로 컨텐츠를 추가할 수 있습니다.
예를들어, 힌트영상 같은경우 init.js 에서 Dom 생성시 아래와 같이 addMode를 호출 합니다.
var youtube = new Entry.Youtube($scope.lecture.youtubeHash);
Entry.propertyPanel.addMode('youtube' , youtube);
현재, youtube와 tvcast 영상을 추가할 수 있도록 Entry.Youtube와 Entry.TvCast가 제공되고 있으며 필요에 따라 추가도 가능합니다.
작품 스냅샷은 단순히 현재 워크스페이스 스테이지(캔버스)의 비트맵을 DataURL로 추출하여 리사이징해 png로 저장하고 있습니다. 아래, 코드를 참조 하시기 바랍니다.
function getResizedImageData() {
var entryCanvas = document.getElementById('entryCanvas');
var tmpCanvas = document.getElementById('tmpCanvas');
if (!tmpCanvas)
tmpCanvas = document.createElement('canvas'); //리사이징을 위한 숨은 캔버스
var ctx = tmpCanvas.getContext('2d');
ctx.width = 313;
ctx.height = 176;
ctx.drawImage(entryCanvas, 0, 0, entryCanvas.width, entryCanvas.height, 0, 0, tmpCanvas.width, tmpCanvas.height);
return tmpCanvas.toDataURL('image/png').replace(/^data:image\/\w+;base64,/, "")
}
위와 같이 생성된 DataURL을 서버측에 업로드하여 png로 저장하고 있습니다.
엔트리 워크스페이스에서 사용자의 모든 block 관련 interaction은 Entry.ActivityReporter를 이용해 Entry.Activity 객체로 저장되고 있습니다. 해당 로그정보는 Entry.activityReporter.get(); 함수로 원하는 시점에 가져올 수 있습니다.
엔트리에서는 코딩파티 스테이지에서 아래와 같이 로그를 수집하고 있습니다.
var activities = Entry.activityReporter.get();
if (activities && activities.length > 0) {
payload.actions = activities;
}
this.post(payload);
Entry.activityReporter.clear();
위 코드는 activity 배열을 가져와 서버로 전송하고, 중복을 막기위해 저장된 데이터는 전송후 비우고 있습니다.
Entry.container.objects_.reduce((count, object) => {
return object.script.getBlockList(true).length + count;
}, 0);
위 코드와 같이 Entry.container의 objects_는 해당 작품의 전체 오브젝트를 가리킵니다. 해당 오브젝트를 전체 돌면서 블록의 개수를 세서 결과값으로 추출가능합니다.
블록, 이미지, 소리 데이터는 오브젝트에 속해 있습니다.
오브젝트에 포함된 요소 ["id", "name", "text", "objectType", "script", "pictures", "sounds", "lock", "isEditing", "selectedPicture", "scene", "rotateMethod", "entity", "clonedEntities", "_isContextMenuEnabled"]
- script
- 블록 소스
- script.getBlockList() 함수로 블록 Object추출 가능
- pictures
- 이미지 리스트
- sounds
- 사운드 리스트
Entry.container에서 전체 object접근이 가능하므로 전체 object를 돌면서 블록, 이미지, 사운드를 확인하면 사용 내용을 가져올수 있습니다.
entryjs의 모든 컴포넌트는 직접 DOM을 생성하지만, 해당 DOM이 사용하는 css는 웹페이지에서 제공됩니다. 또한, entryjs는 다국어 지원을 위해 모든 텍스트는 Lang.xxx 라는 형태의 Javascript 변수를 이용해 치환되고 있으나 이부분이 entryjs에 포함되어 있지는 않습니다.