2011-09-13 3 views
12

몇 가지 테스트를 수행하는 데 사용하는이 간단한 더미 파일이 있습니다. 의도 한 결과는 경로를 따라 빨간색 원을 드래그하는 것입니다. 것은 두 모양을 연결하는 방법을 알아낼 수 없다는 것입니다.주어진 경로를 따라 셰이프를 끌는 방법

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8" />  
    <script src="raphael-min.js"></script>  
</head> 
<body>  
<script type="text/javascript">  
// Creates canvas 320 × 200 at 10, 50 
var r = Raphael(10, 50, 320, 200); 

var p = r.path("M100,100c0,50 100-50 100,0c0,50 -100-50 -100,0z").attr({stroke: "#ddd"}), 
    e = r.ellipse(104, 100, 4, 4).attr({stroke: "none", fill: "#f00"}), 


/*var c = r.circle(100, 100, 50).attr({ 
    fill: "hsb(.8, 1, 1)", 
    stroke: "none", 
    opacity: .5 
});*/ 


var start = function() { 
    // storing original coordinates 
    this.ox = this.attr("cx"); 
    this.oy = this.attr("cy"); 
    this.attr({opacity: 1}); 
}, 
move = function (dx, dy) { 
    // move will be called with dx and dy 
    this.attr({cx: this.ox + dx, cy: this.oy + dy}); 
}, 
up = function() { 
    // restoring state 
    this.attr({opacity: 1}); 
}; 
e.drag(move, start, up);  
</script> 
</body> 
</html> 
+0

주요 아이디어는 animateAlong과 유사하지만, 대신에 애니메이션 끌어 뭔가를 얻을 수 있습니다 : 여기

http://jsfiddle.net/fuzic/kKLtH/

는 코드입니다. – Guillermo

+2

다음은 사람들이 사용할 jsFiddle입니다. http://jsfiddle.net/8T9NQ/ – Joe

+0

일반적으로 커서 위치를 경로에 투영하여 경로에서 가장 가까운 점을 찾아야합니다. 커서에 가장 가까운 경로에 2 개 (또는 그 이상 또는 무한)의 점이있을 가능성이 매우 높으므로 가장 명확한 점을 선택해야합니다. – Phrogz

답변

1

circle 객체의 가운데와 반경에 대한 x, y 좌표가 있습니다. 원이 선에 남아 있는지 확인하려면 간단히 원 중심과 선 자체의 교차점을 찾으십시오.

이렇게하려면 선의 시작 및 끝 좌표를 저장해야합니다. 그런 다음 y = mx + b의 선 방정식을 사용하여 기울기와 y 절편을 찾을 수 있습니다. 선에 대한 함수가 있으면 x의 다른 값을 연결하여 원에 대한 새 좌표를 생성 할 수 있습니다.

또한 원의 x, y 좌표를 함수에 연결하여 원이 선에 있는지 확인할 수 있습니다.

27

상호 작용을 원하는 방식을 정확히 지정하지 않았으므로 가장 자연스러운 느낌을 사용했습니다.

우리는 그 위치가 약간 l에 대한

p.getPointAtLength(l); 

에 의해 부여해야합니다 있도록 점이 경로에 남아 있어야 가정 할 수 있습니다. l을 찾으려면 로컬 최소 곡선과 커서 위치 사이의 거리를 검색 할 수 있습니다. l0으로 검색을 초기화합니다. l0l의 값인 현재의 위치를 ​​정의합니다.

는 작업, 예를 들어 여기에 JSfiddle를 참조하십시오

var searchDl = 1; 
var l = 0; 

// Creates canvas 320 × 200 at 10, 50 
var r = Raphael(10, 50, 320, 200); 

var p = r.path("M100,100c0,50 100-50 100,0c0,50 -100-50 -100,0z").attr({stroke: "#ddd"}), 
    pt = p.getPointAtLength(l); 
    e = r.ellipse(pt.x, pt.y, 4, 4).attr({stroke: "none", fill: "#f00"}), 
    totLen = p.getTotalLength(), 


start = function() { 
    // storing original coordinates 
    this.ox = this.attr("cx"); 
    this.oy = this.attr("cy"); 
    this.attr({opacity: 1}); 
}, 
move = function (dx, dy) { 
    var tmpPt = { 
     x : this.ox + dx, 
     y : this.oy + dy 
    }; 
    l = gradSearch(l, tmpPt); 
    pt = p.getPointAtLength(l); 
    this.attr({cx: pt.x, cy: pt.y}); 
}, 
up = function() { 
    this.attr({opacity: 1}); 
}, 
gradSearch = function (l0, pt) { 
    l0 = l0 + totLen; 
    var l1 = l0, 
     dist0 = dist(p.getPointAtLength(l0 % totLen), pt), 
     dist1, 
     searchDir; 

    if (dist(p.getPointAtLength((l0 - searchDl) % totLen), pt) > 
     dist(p.getPointAtLength((l0 + searchDl) % totLen), pt)) { 
     searchDir = searchDl; 
    } else { 
     searchDir = -searchDl; 
    } 

    l1 += searchDir; 
    dist1 = dist(p.getPointAtLength(l1 % totLen), pt); 
    while (dist1 < dist0) { 
     dist0 = dist1; 
     l1 += searchDir; 
     dist1 = dist(p.getPointAtLength(l1 % totLen), pt); 
    } 
    l1 -= searchDir; 

    return (l1 % totLen); 
}, 
dist = function (pt1, pt2) { 
    var dx = pt1.x - pt2.x; 
    var dy = pt1.y - pt2.y; 
    return Math.sqrt(dx * dx + dy * dy); 
}; 
e.drag(move, start, up);​ 
+0

아주 잘 했어. 이것은 정답으로 받아 들여야합니다 !! –

+0

Fuzic [링크] http://www.shodor.org/interactivate/activities/PieChart/ [링크]와 같은 원형 차트를 만들려는 경우, [그래프] js 라이브러리를 사용하여 가능합니까? –

+0

@fuzic - gradSearch가 어떻게 작동하는지 설명해 주시겠습니까? 참조 : http://stackoverflow.com/questions/23812322/snap-svg-determine-drag-distance-along-a-path – Inator

관련 문제