2012-09-14 4 views
21

मेरे पास एक ग्राफ है, और मैं svg क्षेत्र के शीर्ष पर होवर करते समय एक्स समन्वय पर एक वृत्त दिखाने के लिए ग्राफ का प्रतिनिधित्व करना चाहता हूं। इस सर्कल को वक्र का प्रतिनिधित्व करने वाली रेखा के पथ का पालन करना चाहिए। समस्या यह है कि मुझे नहीं पता कि यह कैसे करें।मैं d3.js में पथ के y समन्वय को कैसे वापस कर सकता हूं?

नीचे दिया गया कोड दिखाता है कि मैंने कितनी दूर तक सफलता प्राप्त की है, और यह वास्तव में दाएं एक्स समन्वय पर दस्तावेज़ में एक सर्कल जोड़ता है। अब, मैं प्रश्न चिह्न को किस स्थान से बदलूं?

svg.on("mousemove", function() { 
     d3.select("path.line") 
      .style("stroke-width", "2.5px"); 

     svg.append("svg:circle") 
      .attr("cx", Math.floor(event.offsetX-m[1])) 
      .attr("cy", ?) 
      .attr("r", "10") 
      .attr("fill", "red"); 
    }); 

उत्तर

25

एसवीजी एक देशी समारोह .getPointAtLength() कहा जाता है जो किसी भी लम्बाई आप इसे पारित पर एक एक्स और एक पथ के y मान देता है प्रदान करता है।

आपको लाइन की लंबाई के माध्यम से फिर से शुरू करने की आवश्यकता होगी जब तक आपको संबंधित वाई स्थिति न मिल जाए।

var svg = d3.select("#line").append("svg") 
var path = 
    svg.append("path") 
     .attr("d", "M0,168L28,95.99999999999997L56,192L84,71.99999999999997L112,120L140,192L168,240L196,168L224,48L252,24L280,192L308,120L336,24L364,168L392,95.99999999999997L420,168L448,95.99999999999997L476,192L504,71.99999999999997L532,120L560,192L588,216L616,168L644,48L672,24L700,192L728,120L756,24L784,192L812,71.99999999999997") 
     .attr("fill", "none") 
     .attr("stroke", "black"); 

var circle = 
    svg.append("circle") 
     .attr("cx", 100) 
     .attr("cy", 350) 
     .attr("r", 3) 
     .attr("fill", "red"); 

var pathEl = path.node(); 
var pathLength = pathEl.getTotalLength(); 
var BBox = pathEl.getBBox(); 
var scale = pathLength/BBox.width; 
var offsetLeft = document.getElementById("line").offsetLeft; 
var randomizeButton = d3.select("button"); 

svg.on("mousemove", function() { 
    var x = d3.event.pageX - offsetLeft; 
    var beginning = x, end = pathLength, target; 
    while (true) { 
    target = Math.floor((beginning + end)/2); 
    pos = pathEl.getPointAtLength(target); 
    if ((target === end || target === beginning) && pos.x !== x) { 
     break; 
    } 
    if (pos.x > x)  end = target; 
    else if (pos.x < x) beginning = target; 
    else    break; //position found 
    } 
    circle 
    .attr("opacity", 1) 
    .attr("cx", x) 
    .attr("cy", pos.y); 
}); 

आप एक डेमो यहाँ देख सकते हैं: http://bl.ocks.org/3824661

+0

मैं बहुत यकीन है कि यह मनमाना समय शैली पथ आकार, उदा लिए काम नहीं करेगा हूँ यहाँ कैसे आप डी 3 में ऐसा होता है एक बिंदु पर एक बहुत तेज स्पाइक वाली एक रेखा पथ की लंबाई और एक्स-स्थिति के बीच एक रैखिक इंटरपोलेशन की अनुमति नहीं देगी। – nrabinowitz

+0

@nrabinowitz जो http://jsfiddle.net/FPfFJ/ और हाँ का परीक्षण करने के लिए काफी आसान है, यह काफी नहीं है। – Duopixel

+0

हाँ, मुझे लगता है कि इस मामले में एक सटीक बिंदु प्राप्त करने के लिए '.getPointAtLength()' का उपयोग करने का एकमात्र तरीका लाइन के साथ खोज करना है जब तक कि आपको 'd3.event.pageX' के करीब 'x' मान वाला कोई बिंदु न मिल जाए। । – nrabinowitz