2014-10-11 2 views
2

D3.js 힘 그래프를 사용하고 있지만 요소 위치에서 요소 ID를 찾을 수 없습니다.).D3.js의 요소 위치에서 웹 요소 (id)를 얻는 방법 force graph

나는 도약 동작을 사용 중입니다. 마우스를 사용하지 않고 마우스 이벤트 (클릭, 이동, 드래그 등)를 시뮬레이트해야합니다. 그리고 내가 옳다면, 이것을 할 수 있기 위해서, 좌표 x와 y (나는 Leap motion pointer에서 알 수있는 좌표)에서 요소 id가 무엇인지 찾아야합니다. 그래서 위에서 쓴 것에서부터 ('. 노드')를 찾아야합니다. 여기 은 이미 시도했지만 작동하지 않았다 무엇 :

Is it possible to use non-mouse, non-touch events to interact with a D3.js graph? If so, what is the most efficient way to go about it?

그래서 나는이 기능 (아래 참조)를 사용하지만, 나는 그것이 제대로 작동 할 요소 ID를 알아야합니다

//graph.simulate(document.getElementById("r_1"), 'dblclick', {pointerX: posX, pointerY: posY}); 
//here id r_1 is hardcoded, but I need to find out id from x and y coordinates. 

this.simulate = function (element, eventName) { 
    function extend(destination, source) { 
     for (var property in source) 
      destination[property] = source[property]; 
     return destination; 
    } 

    var eventMatchers = { 
     'HTMLEvents': /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/, 
     'MouseEvents': /^(?:click|dblclick|mouse(?:down|up|over|move|out))$/ 
    }; 

    var defaultOptions = { 
     pointerX: 0, 
     pointerY: 0, 
     button: 0, 
     ctrlKey: false, 
     altKey: false, 
     shiftKey: false, 
     metaKey: false, 
     bubbles: true, 
     cancelable: true 
    }; 

    var options = extend(defaultOptions, arguments[2] || {}); 
    var oEvent, eventType = null; 

    for (var name in eventMatchers) { 
     if (eventMatchers[name].test(eventName)) { 
      eventType = name; 
      break; 
     } 
    } 

    if (!eventType) 
     throw new SyntaxError('Only HTMLEvents and MouseEvents interfaces are supported'); 

    if (document.createEvent) { 
     oEvent = document.createEvent(eventType); 
     if (eventType == 'HTMLEvents') { 
      oEvent.initEvent(eventName, options.bubbles, options.cancelable); 
     } 
     else { 
      oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView, 
       options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
       options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element); 
     } 
    element.dispatchEvent(oEvent); 
    } 
    else { 
     options.clientX = options.pointerX; 
     options.clientY = options.pointerY; 
     var evt = document.createEventObject(); 
     oEvent = extend(evt, options); 
     element.fireEvent('on' + eventName, oEvent); 
    } 
    return element; 
} 

많은 도움과 아이디어에 감사드립니다. 더 많은 정보를 들어

아웃이를 확인

+0

다른 해결책으로 내 대답을 편집했습니다. 봐. –

답변

2

, 그것은 this를 통해 D3의 반복자 암시입니다. 당신이 정말로 ID에 액세스해야하는 경우

d3.selectAll('.node').each(function(d) { 
    console.log(this); // Logs the element attached to d. 
}); 

, 당신은()를 selection.attr 그것을 얻을 수 있습니다 :

d3.selectAll('.node').each(function() { 
    console.log(d3.select(this).attr('id')); // Logs the id attribute. 
}); 

당신은 each를 사용할 필요가 없습니다. 등 attr 또는 style, 같은 반복자의 어떤은,이 '이'바운드 요소로 : 당신은 x와 노드의 y 좌표를 원하는 경우에

d3.selectAll('.node').style('opacity', function(d) { 
    console.log(this);// Logs the element attached to d. 
}); 

,이 데이터의 일부 :

d3.selectAll('.node').each(function(d) { 
    console.log(d.x, d.y); // Logs the x and y position of the datum. 
}); 

실제로 노드 속성 자체가 필요한 경우 attr 접근자를 사용할 수 있습니다.

d3.selectAll('.node').each(function(d) { 
    // Logs the cx and cy attributes of a node. 
    console.log(d3.select(this).attr('cx'), d3.select(this).attr('cy')); 
}); 

EDIT : 요소 참조가 필요해 보이지만 컨텍스트에서 노드에 대해 알고있는 유일한 것은 위치입니다. 한 가지 해결책은 모든 노드를 통해 일치하는 좌표가있는 노드를 검색하는 것입니다.

// Brute force search of all nodes. 
function search(root, x, y) { 
    var found; 
    function recurse(node) { 
    if (node.x === x && node.y === y) 
     found = node; 
    !found && node.children && node.children.forEach(function(child) { 
     recurse(child); 
    }); 
    } 
    recurse(root); 
    return found; 
} 

그러나 노드 개체 만 제공하며 요소 자체는 제공하지 않습니다. 당신은 가능성이 노드에 요소 참조를 저장해야합니다 그와

// Give each node a reference to its dom element. 
d3.selectAll('.node').each(function(d) { 
    d.element = this; 
}); 

을 장소에서, 당신은 요소에 액세스하고 ID를 얻을 수 있어야합니다.

var id, node = search(root, x, y); 
if (node) { 
    id = node.element.getAttribute('id'); 
} 

무차별 검색 노드의 작은 숫자에 대한 괜찮지 만, 당신은 많은 수의 노드를 밀어하는 경우 당신은 D3의 quadtree(example) 검색 속도를 사용할 수도 있습니다.

+0

좀 더 구체적으로 질문을 편집했습니다. 감사합니다 – Jirka

+0

많은 사람에게 고마워요 :-) 그것은 작동하지만, 마지막 솔루션을 사용하지 않았더라도 성능 문제가 있습니다. 아마도 도약 장치와 관련이있을 것입니다. – Jirka

2

사용 d3.select ('#의 yourElementId이') : 해당 요소에 액세스하려면 https://github.com/mbostock/d3/wiki/Selections

+0

저는 정확히 x와 y 좌표에서 찾으려는 elementId를 모르겠습니다. – Jirka

+0

죄송합니다. 질문을 잘 이해하지 못했습니다. 어쩌면 모든 요소를 ​​반복하고 좌표가 요소 내부에 있는지 확인해야합니다. – slotomo