포트에서 Edge 를 뽑을 때, 포트를 Mouse Move 하는 동작에 mxConnectionHandler 의 mouseMove 메소드가 작동된다.
이 때 Edge가 연결될 수 없는 포트에 투명도(opacity)를 50% 먹임으로써 연결할 수 없는 포트라는 사용자 경험을 선사한다.
또한 다른 Edge에 마우스가 닿았을 때, 마우스가 not-allowed 상태가 되는 사용자 경험도 선사한다.
이 포트의 style을 변경하는 작업을 마우스가 한 픽셀 한 픽셀 움직일 때 마다 하고 있었다.
타일 수가 적을 땐 문제가 없지만, 타일이 많아지고 그에 따라 포트도 늘어나면 굉장히 버벅이고 렉이 걸렸다.
(연결할 수 없는 포트엔 투명도가 적용된다)
mouse down 때 화면에 보이는 포트/Edge 들을 적용시키고,
mouse move 하면서 화면이 옮겨지며 새로 발견되는 포트/Edge를 적용시키기로 했다.
cellsInViewPort(cells, part) {
const cellsInView = [];
const cellsOutOfView = [];
const {scrollLeft, scrollTop, offsetWidth, offsetHeight} = this.container;
cells.forEach(cell => {
const cellBounds = this.view.getState(cell)?.shape.bounds;
const boundXY = [cellBounds?.x, cellBounds?.y];
if (boundXY[0] > scrollLeft && boundXY[1] > scrollTop && boundXY[0] < scrollLeft + offsetWidth && boundXY[1] < scrollTop + offsetHeight) {
cellsInView.push(cell);
} else {
cellsOutOfView.push(cell);
}
});
const extractedCells = {
in: cellsInView,
out: cellsOutOfView,
}
if (part === 'in') {
return extractedCells.in;
} else if (part === 'out') {
return extractedCells.out;
} else {
return extractedCells;
}
}
const portsInView = cellsInViewPort(allPorts, 'in');
클릭한 포트는 제외되어야 하기에 제외시켜 준다.
그리고 연결되서는 안되는 포트와 그 id를 추출한다. getInvalidPortsInViewPort라는 메소드를 만들어 추출했다.
const idx = portsInView.findIndex(port => port.id === cell.id);
portsInView.splice(idx, 1);
this.invalidPorts = this.graph.model.getInvalidPortsInViewPort(cell, portsInView);
this.invalidPortsId = new Set(this.invalidPorts.map(port => port.id));
투명도를 적용시키는 메소드는 drawGetOpacityInvalidPorts 이다.
이제 mouse move로 화면을 옮길 때마다 새로운 포트들이 발견되면 넣어줘야 한다.
connectionHandler의 mouseMove 메소드안의 drawPreview라는 메소드에 포트의 id를 체크해서,
invalidPortsId에 없는 포트면 새로 넣어주면서 투명도를 적용시켜줬다.
const cell = this.grabbingPort;
const allPorts = Object.values(this.graph.model.cells).filter(cell => cell?.portType);
const portsInView = this.graph.cellsInViewPort(allPorts, 'in');
const idx = portsInView.findIndex(port => port.id === cell.id);
// 해당 포트 제외;
portsInView.splice(idx, 1);
// 일단 opacity 먹여야하는 포트 구해준다;
const tempInvalidPorts = this.graph.model.getInvalidPortsInViewPort(cell, portsInView);
// 이미 먹여진 애들 제외하고 새로 탐색된 애들;
const toDrawingPorts = [];
tempInvalidPorts.forEach(port => {
if (!this.invalidPortsId.has(port.id)) {
toDrawingPorts.push(port);
}
})
toDrawingPorts?.forEach(port => {
const portState = this.graph.view.getState(port);
portState.style.opacity = 50;
if (portState?.text) {
portState.style.textOpacity = 50;
this.graph.cellRenderer.redrawLabel(portState, true);
}
portState.shape?.apply(portState);
portState.shape?.redraw();
// opacity 먹여주고 invalidPorts에 추가;
this.invalidPorts.push(port);
this.invalidPortsId.add(port.id);
})
Edge도 똑같은 방식으로 적용 시켜줬다.