mxGraph Animation 적용記

Dzeko·2023년 10월 20일
0

개발일지

목록 보기
102/112

일반 html 및 SPA 환경에서는 element에 애니메이션을 적용하기가 쉽다.
하지만 mxGraph에는 cell의 스타일 변화에 애니메이션을 적용하기가 쉽지 않다.

왜냐하면 mxGraph 스스로 렌더링하고 redraw 때려버리기 때문이다.
그래서 PM측에서 Workbench 에디터에서 타일의 애니메이션을 문의할 때마다 적용하기 어렵다고 대답해왔다.
그나마 구현했던 것이 지난 번에 발행했던 타일과는 직접적 연관이 없는 작업인 타일 위에 html 요소를 만들어 애니메이션을 띄우고 제거하는 방식이었다.

그러던 중 정말 뜬금없이 머릿속을 스치는 생각으로 테스트를 해보았는데 성공을 했다. 바로 구현을 해서 PM에 전달해 적용을 시켰다.

send message 타일은 말 그대로 사용자가 고객에게 메세지를 보내는 타일이다. 이 타일의 display text에는 message 내용이 담기는데, 1,120자 제한이라 display text에는 160자를 자른 후 '...' 처리를 했었다.
때문에 사용자가 전체 내용을 보려면 타일을 클릭한 후 패널의 내용을 확인해야 했다.

그래서 이번에 구현된 기능이 see more/less 인데, 이 버튼을 누르면 타일이 펼쳐져 전체 내용이 보이도록 하는 것이였다.

구현 후에 타일이 너무 갑자기 길어지니 보기 안좋다하셔서 펼쳐지는 애니메이션 어떻게 안되냐고 했었는데, 단칼에 위에 적었던 내용대로 어렵다고 했었다.
이 후, 내 스스로도 너무 구현하고 싶어 오랜 시간 짱구를 엄청 굴렸다.

처음에는 가상의 element를 만들어 높이를 측정하고 그 높이에 따라 타일의 rect를 강제로 조정하면서 css animation을 먹이는 방법을 생각했다.
하지만 element의 높이를 정확히 구할 수 없었다.

그래서 mxGraph가 그려주는 높이를 적용하는 방법을 생각했다.
하지만 이미 다 그려주고 나서 구할 수 있었으므로 의미가 없었다.

타일(cell)의 스타일(width, height)가 변경이 되면, mxGraph는 이를 감지하고, cell을 revalidate 하면서 변경된 view를 redraw 한다. 이는 eventListener로 작동을 한다.
이 과정에서 개발자가 뭘 할 수 있을지 생각해봤다.

먼저 data를 등록했다. redrawInhibitor(Boolean) - redraw 억제기 라는 뜻이다.

cell.redrawInhibitor = true;
graph.model.setValue(cell, displayValue, true);

setValue를 하면 cell 의 value를 설정하며 결국 cellRenderer.redraw()까지 타게 되는데, 이 함수에서 cell의 높이를 구하고 repaint 하기 직전에 억제기를 걸어 중단시켰다.

redraw = function() {
	if (state.cell?.redrawInhibitor) {
		graph.model.heightValueBeforeRedraw = {
			id: state.cell.propertyId,
			height: state.cell.geometry.height,
		}
		return;
	}
}

그리고 그 높이를 전달받아서 적용하고, 애니메이션을 작동시켰다.
그리고 repaint동작은 애니메이션이 끝나고 동작되도록 애니메이션 시간동안 setTimeout을 걸었다.

cell.redrawInhibitor = true;
graph.model.setValue(cell, displayValue, true);

const height = graph.model.heightValueBeforeRedraw.height;
const rect = graph.view.getState(cell).shape.node.childNodes[0];

rect.setAttribute('height', height);

setTimeout(() => {
  cell.redrawInhibitor = false;
  
  if (!cellProperty.setting.seeMore) {
    graph.model.setValue(cell, displayValue, true);
  }
}, 200);
rect {
  /* 높이 변경에 대한 애니메이션*/
  transition: height 0.2s ease; 
}


Before

After

profile
Hound on the Code

0개의 댓글