2014-09-17 6 views
11

तो मेरे पास ट्रैफ़िक बनाम दिनांक और दर बनाम तिथि का साजिश है। मैं क्षेत्र को दो लाइनों के बीच छाया करने की कोशिश कर रहा हूं। हालांकि, मैं इस रेखा के आधार पर एक अलग रंग छाया करना चाहता हूं। कि पिछले आवश्यकता के बिना निम्नलिखित काम करता है:दो लाइनों के बीच छाया क्षेत्र में डी 3 का उपयोग

var area = d3.svg.area() 
    .x0(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); }) 
    .x1(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); }) 
    .y0(function(d) { return y(parseInt(d.original.traffic)); }) 
    .y1(function(d) { return y(parseInt(d.original.rate)); }) 

हालांकि, कि पिछले शर्त का, मैंने कोशिश की परिभाषित का उपयोग करने():

.defined(function(d){ return parseInt(d.original.traffic) >= parseInt(d.original.rate); }) 

अब इस ज्यादातर काम करता है को छोड़कर जब लाइनों को पार। मैं बिंदुओं के बीच एक पंक्ति के नीचे क्षेत्र को कैसे छाया करूं? यह बिंदुओं के आधार पर छायांकन है और मैं इसे लाइन के आधार पर छाया करना चाहता हूं। यदि मेरे पास लाइन के एक तरफ लगातार दो अंक नहीं हैं, तो मुझे कोई भी छायांकन नहीं मिलता है।

उत्तर

13

चूंकि आपके पास चौराहे पर डेटापॉइंट्स नहीं हैं, इसलिए सबसे आसान समाधान शायद प्रत्येक पंक्ति के ऊपर और नीचे के क्षेत्रों को प्राप्त करने के लिए है और अंतर को फसल करने के लिए clipPath एस का उपयोग करें।

मुझे लगता है कि आप d3.svg.line का उपयोग कर रहे हैं ताकि वे लाइनों को आकर्षित कर सकें। इस तरह से हम बाद में क्षेत्रों पर .x() और .y() एक्सेसर कार्यों को फिर से उपयोग करने के लिए सक्षम हो जाएगा:

var trafficLine = d3.svg.line() 
    .x(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); }) 
    .y(function(d) { return y(parseInt(d.original.traffic)); }); 

var rateLine = d3.svg.line() 
    .x(trafficLine.x()) // reuse the traffic line's x 
    .y(function(d) { return y(parseInt(d.original.rate)); }) 

आप दोनों के ऊपर और अपने दो पंक्तियों नीचे क्षेत्रों की गणना के लिए अलग क्षेत्र कार्यों बना सकते हैं। प्रत्येक पंक्ति के नीचे का क्षेत्र वास्तविक पथ को चित्रित करने के लिए उपयोग किया जाएगा, और ऊपर दिया गया क्षेत्र क्लिपिंग पथ के रूप में उपयोग किया जाएगा। अब हम लाइनों से accessors का फिर से उपयोग कर सकते हैं:

var areaAboveTrafficLine = d3.svg.area() 
    .x(trafficLine.x()) 
    .y0(trafficLine.y()) 
    .y1(0); 
var areaBelowTrafficLine = d3.svg.area() 
    .x(trafficLine.x()) 
    .y0(trafficLine.y()) 
    .y1(height); 
var areaAboveRateLine = d3.svg.area() 
    .x(rateLine.x()) 
    .y0(rateLine.y()) 
    .y1(0); 
var areaBelowRateLine = d3.svg.area() 
    .x(rateLine.x()) 
    .y0(rateLine.y()) 
    .y1(height); 

... जहां height अपने चार्ट की ऊंचाई है, और यह सोचते हैं 0 चार्ट के शीर्ष के y- निर्देशांक है, अन्यथा उन मूल्यों को समायोजित तदनुसार।

अब आप इस तरह कतरन पथ बनाने के लिए क्षेत्र के ऊपर कार्यों का उपयोग कर सकते हैं:

var defs = svg.append('defs'); 

defs.append('clipPath') 
    .attr('id', 'clip-traffic') 
    .append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaAboveTrafficLine); 

defs.append('clipPath') 
    .attr('id', 'clip-rate') 
    .append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaAboveRateLine); 

id गुण जरूरी हैं क्योंकि हम उन परिभाषाओं का उल्लेख करने के लिए जब वास्तव में पथ कतरन की जरूरत है।

अंत में, svg पर पथ खींचने के लिए क्षेत्र-नीचे फ़ंक्शंस का उपयोग करें।

// TRAFFIC IS ABOVE RATE 
svg.append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaBelowTrafficLine) 
    .attr('clip-path', 'url(#clip-rate)') 

// RATE IS ABOVE TRAFFIC 
svg.append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaBelowRateLine) 
    .attr('clip-path', 'url(#clip-traffic)') 

उसके बाद: महत्वपूर्ण बात यहाँ याद करने के लिए कि प्रत्येक क्षेत्र-नीचे के लिए, हम करने के लिए विपरीत क्षेत्र-ऊपर क्लिप, तो दर क्षेत्र काटा गया हो जाएगा पर #clip-traffic और इसके विपरीत आधारित की जरूरत है आपको केवल दो क्षेत्रों को अलग-अलग रंगों को भरने की आवश्यकता होगी या जो भी आप उन्हें एक-दूसरे से अलग करने के लिए करना चाहते हैं। उम्मीद है की वो मदद करदे!

संबंधित मुद्दे