svj.js를 활용한 interaction 예제 구현

1.초기 Frame영역 설정, rect형태로 Frame size 선언

var SVG = require('svg.js');
var svgdraw = SVG("drawing").size(300, 300);
var rectFrame = {
    left:   0,
    top:    0,
    right:  svgdraw.width(),
    bottom: svgdraw.height()
};

2.svg line 객체로 frame 그리기, 추후 line svg를 통해 intersecion 검사 수행

var frameLines = []
frameLines.push(svgdraw.line(rectFrame.left, rectFrame.top, rectFrame.left, rectFrame.bottom).attr({stroke:"black"}));
frameLines.push(svgdraw.line(rectFrame.left, rectFrame.bottom, rectFrame.right, rectFrame.bottom).attr({stroke:"black"}));
frameLines.push(svgdraw.line(rectFrame.right, rectFrame.bottom, rectFrame.right, rectFrame.top).attr({stroke:"black"}));
frameLines.push(svgdraw.line(rectFrame.right, rectFrame.top, rectFrame.left, rectFrame.top).attr({stroke:"black"}));

3. browser의 refresh에 맞춰 draw 추가

function OnDraw() {
    window.requestAnimationFrame(OnDraw);
    // svgdrawing code goes here
    frameCount++;
}
OnDraw();

4. 1초 단위로 frame rate 출력

///Frame Rate
var textFrameRate = svgdraw.text('Frame Rate: 0 f/s');
textFrameRate.move(svgdraw.width()-150, svgdraw.height()-25);

//Frame rate
setInterval(function(){ 
    frameRate = frameCount;
    frameCount = 0;
    textFrameRate.text("Frame Rate: " + frameRate + " f/s");
}, 1000);

5. Random하게 circle svg 객체 생성 하기

circleSize = 20;
circleCount = 6;
colors = ["red", "blue", "yellow", "black","#F80","#80F"]
for(var i=0; i<circleCount; i++)
{
    posX[i] = Math.floor((Math.random() * svgdraw.width()) - circleSize);
    posY[i] = Math.floor((Math.random() * svgdraw.height()) - circleSize);
    if(posX[i] < 0) posX[i]=0;
    if(posY[i] < 0) posY[i]=0;
    circles[i] = svgdraw.circle(circleSize).attr({fill: colors[i]}).move(posX[i], posY[i]);
}

6. source circle객체 마다 다른 cicle객체 충돌 검사, frame 외벽 검사 수행

for(var src=0; src<circles.length; src++)
{
    var isIntersect = false;
    var srcObj, destObj;
    srcObj = circles[src];

    ///Circle
    for(var dest=0; dest<circles.length; dest++)
    {
        if(src == dest) continue;
        if(intersectRect(circles[src], circles[dest]))
        {
            isIntersect = true;
            destObj = circles[dest];
            break;
        }
    }
    
    ///Frame
    if(!isIntersect)
    {
        for(var f=0; f<frameLines.length; f++)
        {
            if(intersectRect(circles[src], frameLines[f]))
            {
                isIntersect = true;
                destObj = frameLines[f];
                break;
            }
        }
    }
}

7. 충돌이라고 판단되면, 방향 전환
원래는 충돌 면에 따라 움직이는 방향을 정해야 하지만, 임시 테스트 이기에 충돌 없을때까지 무작위로 수행

if(isIntersect)
{   
    var tryCount = 0;
    while(intersectRect(srcObj, destObj))
    {
        if(tryCount++ > 10)
            break;
        changeDirection(src);
        moveCircle(src);
    }
}

8.초기 생성시에 random위치 생성시 서로 충돌 나는 예외처리 추가
반복적으로 생성 하면서 충돌시 재생성

for(var i=0; i<circleCount; i++)
{
    var cir = createCircle(i);
    for(var dest=0; dest<circles.length; dest++)
    {
        if(!intersectRect(cir.circle, circles[dest]))
            break;
        cir.circle.remove();
        dest--;
        cir = createCircle(i);
    }
    posX[i] = cir.posX;
    posY[i] = cir.posY;
    circles[i] = cir.circle;

    dirs[i] = Math.floor((Math.random() * 4));
    changeDelta(i, dirs[i]);
}

9.전체 source는 github에 (https://github.com/scanhand/test_svgjs)

10.결과 화면