2010-11-17 12 views
14

मेरे पास एक ऐसा एप्लिकेशन है जो बहुत "कनेक्शन-आधारित" है, यानी एकाधिक इनपुट/आउटपुट।मैं डब्ल्यूपीएफ में एक लटकते केबल का अनुकरण कैसे कर सकता हूं?

"केबल" की यूआई अवधारणा बिल्कुल वही है जो मैं उपयोगकर्ता को अवधारणा को स्पष्ट करने के लिए देख रहा हूं। प्रोपेलरहेड ने this YouTube video (fast forward to 2m:50s) में चित्रित ऑडियो घटकों के लिए अपने कारण सॉफ्टवेयर में एक समान दृष्टिकोण लिया।

मैं इस अवधारणा को बिंदु ए से बिंदु बी तक एक स्पलीन चित्रित करके जीडीआई में काम कर सकता हूं, इसके लिए पथ या कुछ का उपयोग करने के लिए एक और शानदार तरीका होना चाहिए, लेकिन आप कहां से शुरू करते हैं? जब आप इसे पकड़ते हैं और इसे हिलाते हैं तो केबल स्विंग की एनीमेशन अनुकरण करने का कोई अच्छा तरीका है?

यदि पुस्तकालयों (वाणिज्यिक या ओपन सोर्स) को नियंत्रित करने के लिए मैं भी खुला हूं तो इस व्हील का पहले से ही WPF के लिए आविष्कार किया गया है।

अद्यतन: अब तक उत्तर में दिए गए लिंक के लिए धन्यवाद, मैं लगभग वहां हूं।

alt text

मैं प्वाइंट 1 जा रहा है (0, 0), प्वाइंट 2 जा रहा है नीचे "लटका" बिंदु के साथ एक BezierCurve प्रोग्राम के रूप में बना लिया है, और प्वाइंट 3 किया जा रहा है जहाँ भी माउस कर्सर है। मैंने को ElasticEase के साथ PointAnimation बनाया है, जो "स्विंगिंग" प्रभाव देने के लिए लागू किया गया है (यानी, थोड़ा सा बीच बिंदु को उछालते हुए)।

केवल समस्या यह है कि एनीमेशन थोड़ा देर से चल रहा है। जब भी माउस चलता है, मैं स्टोरीबोर्ड शुरू कर रहा हूं, क्या इस एनीमेशन को करने का एक बेहतर तरीका है? मेरे समाधान अब तक यहाँ स्थित है:

Bezier Curve Playground

कोड:

private Path _path = null; 
private BezierSegment _bs = null; 
private PathFigure _pFigure = null; 
private Storyboard _sb = null; 
private PointAnimation _paPoint2 = null; 
ElasticEase _eEase = null; 

private void cvCanvas_MouseMove(object sender, MouseEventArgs e) 
{ 
    var position = e.GetPosition(cvCanvas); 
    AdjustPath(position.X, position.Y); 
} 

// basic idea: when mouse moves, call AdjustPath and draw line from (0,0) to mouse position with a "hang" in the middle 
private void AdjustPath(double x, double y) 
{ 
    if (_path == null) 
    { 
     _path = new Path(); 
     _path.Stroke = new SolidColorBrush(Colors.Blue); 
     _path.StrokeThickness = 2; 
     cvCanvas.Children.Add(_path); 

     _bs = new BezierSegment(new Point(0, 0), new Point(0, 0), new Point(0, 0), true); 

     PathSegmentCollection psCollection = new PathSegmentCollection(); 
     psCollection.Add(_bs); 

     _pFigure = new PathFigure(); 
     _pFigure.Segments = psCollection; 
     _pFigure.StartPoint = new Point(0, 0); 


     PathFigureCollection pfCollection = new PathFigureCollection(); 
     pfCollection.Add(_pFigure); 

     PathGeometry pathGeometry = new PathGeometry(); 
     pathGeometry.Figures = pfCollection; 

     _path.Data = pathGeometry; 
    } 

    double bottomOfCurveX = ((x/2)); 
    double bottomOfCurveY = (y + (x * 1.25)); 

    _bs.Point3 = new Point(x, y); 

    if (_sb == null) 
    { 
     _paPoint2 = new PointAnimation(); 

     _paPoint2.From = _bs.Point2; 
     _paPoint2.To = new Point(bottomOfCurveX, bottomOfCurveY); 
     _paPoint2.Duration = new Duration(TimeSpan.FromMilliseconds(1000)); 
     _eEase = new ElasticEase(); 

     _paPoint2.EasingFunction = _eEase; 
     _sb = new Storyboard(); 

     Storyboard.SetTarget(_paPoint2, _path); 
     Storyboard.SetTargetProperty(_paPoint2, new PropertyPath("Data.Figures[0].Segments[0].Point2")); 

     _sb.Children.Add(_paPoint2); 
     _sb.Begin(this);     
    } 

    _paPoint2.From = _bs.Point2; 
    _paPoint2.To = new Point(bottomOfCurveX, bottomOfCurveY); 

    _sb.Begin(this); 
} 
+1

क्या आप एक कैटेनरी वक्र खींचने की कोशिश कर रहे हैं? http://en.wikipedia.org/wiki/Catenary – Gabe

+0

@Gabe, हाँ, ऐसा लगता है कि वक्र का प्रकार मैं – Brandon

+0

देख रहा हूं क्या आपने http://www.tinaja.com/glib/bezcat देखा है। पीडीएफ? – Gabe

उत्तर

9

आप सच गतिशील गति चाहते हैं (यानी, जब आप "हिला" माउस आप सूचक कॉर्ड के साथ यात्रा करने वाली लहरें बना सकते हैं), आपको परिमित तत्व तकनीकों का उपयोग करने की आवश्यकता होगी। हालांकि यदि आप स्थिर व्यवहार के साथ ठीक हैं तो आप बस बेजियर वक्र का उपयोग कर सकते हैं।

सबसे पहले मैं संक्षेप में परिमित तत्व दृष्टिकोण का वर्णन करूंगा, फिर स्थिर दृष्टिकोण पर अधिक जानकारी प्राप्त करूंगा।

गतिशील दृष्टिकोण

एक बड़ी संख्या (1000 या तो) "तत्वों", प्रत्येक की स्थिति और वेग वेक्टर के साथ अपने "गर्भनाल" विभाजित करें। प्रत्येक तत्व स्थिति की गणना करने के रूप में निम्न प्रकार CompositionTarget.Rendering घटना का उपयोग करें:

  • कंप्यूट आसन्न तत्वों से "की हड्डी" है, जो तत्वों के बीच की दूरी के लिए आनुपातिक है साथ प्रत्येक तत्व पर पुल। मान लें कि कॉर्ड खुद ही द्रव्यमान है।

  • प्रत्येक "तत्व" पर शुद्ध बल वेक्टर की गणना करें जिसमें कॉर्ड के साथ प्रत्येक आसन्न तत्व से खींचें, साथ ही गुरुत्वाकर्षण की निरंतर शक्ति भी शामिल है।

  • बल वेक्टर को त्वरण में बदलने के लिए एक द्रव्यमान स्थिरता का उपयोग करें, और गति के समीकरणों का उपयोग करके स्थिति और वेग को अद्यतन करें।

  • एक StreamGeometry का उपयोग करके लाइन को ड्राइफफिगर के साथ एक पॉलीलाइन टो के साथ बनाएं। इतने सारे बिंदुओं के साथ एक घन बेजियर सन्निकटन बनाने के लिए अतिरिक्त गणना करने का कोई कारण नहीं है।

स्टेटिक दृष्टिकोण

शायद 30 खंडों, झूलना y = एक सोंटा (एक्स/एक) के लिए एक घन बेज़ियर अनुमान होता है, जिनमें से प्रत्येक में अपने कॉर्ड विभाजित करें। आपका अंतिम नियंत्रण बिंदु कैटेनरी वक्र पर होना चाहिए, समांतरों को कैटेनरी के लिए स्पर्श करना चाहिए, और नियंत्रण रेखा लंबाई कैटेनरी के दूसरे व्युत्पन्न के आधार पर सेट की जानी चाहिए।

इस मामले में आप शायद इसे बनाने के लिए BeginFigure और PolyBezierTo का उपयोग करके स्ट्रीमगोमेट्री प्रस्तुत करना चाहेंगे।

मैं इसे एक कस्टम आकार उपclass "कैटेनरी" के रूप में आयताकार और एलिप्स के समान लागू करता हूं। उस स्थिति में, आपको DefiningGeometry प्रॉपर्टी को ओवरराइड करना होगा। दक्षता के लिए मैं कैशडिफिनिंग जीमेट्री, GetDefiningGeometryBounds, और GetNaturalSize को ओवरराइड भी करूँगा।

आप पहले निर्णय लेंगे कि कैटिनरी को पैरामीटर कैसे करें, फिर अपने सभी पैरामीटर के लिए निर्भरताप्रॉपर्टी जोड़ें। सुनिश्चित करें कि आप अपने फ्रेमवर्कप्रॉपर्टी मेटाडेटा में AffectMeasure और EffectsRender ध्वज सेट करते हैं।

एक संभावित पैरामीटरकरण XOffset, YOffset, लंबाई होगी। एक और XOffset, Yofset, SagRelativeToWidth हो सकता है। यह इस बात पर निर्भर करेगा कि क्या बांधना सबसे आसान होगा।

एक बार आपकी निर्भरता प्रॉपर्टी परिभाषित हो जाने के बाद, क्यूबिक बेजियर नियंत्रण बिंदुओं की गणना करने, स्ट्रीमजीमेट्री बनाने और इसे वापस करने के लिए अपनी परिभाषा जीमेट्री संपत्ति को कार्यान्वित करें।

यदि आप ऐसा करते हैं, तो आप कहीं भी कैटेनरी नियंत्रण छोड़ सकते हैं और एक कैटेनरी वक्र प्राप्त कर सकते हैं।

1

एक पथ में उपयोगकर्ता बेज़ियर वक्र खंडों। प्रयोज्य से अधिक दिखता है के पक्ष में -

http://www.c-sharpcorner.com/UploadFile/dbeniwal321/WPFBezier01302009015211AM/WPFBezier.aspx

+0

गाय: वह किसी भी प्रकार की वक्र नहीं चाहता, केवल वक्र नहीं। – Gabe

+0

@Gabe, @Guy, यह एक ऐसी तकनीक की तरह दिखता है जो काम कर सकता है (मैं मूल पथ के बाद वक्र के साथ खेल सकता हूं), अब एक्सएएमएल के बजाए प्रोग्रामेटिक रूप से ऐसा उदाहरण कैसे बना सकता है .. – Brandon

1

IMHO 'फांसी' (शारीरिक रूप से नकली) केबलों इस पर कर का मामला है।

क्या आप वाकई उपयोगकर्ता अनुभव को छेड़छाड़ नहीं कर रहे हैं?

एक नोड/कनेक्शन आधारित UI में मैं स्पष्ट कनेक्शन (क्वार्ट्ज संगीतकार की तरह: http://ellington.tvu.ac.uk/ma/wp-content/uploads/2006/05/images/Quartz%20Composer_screenshot_011.png) को खोजने के झूलते तारों कि एक अलग दिशा में जहां से (गुरुत्वाकर्षण के कारण नीचे) सिर की तरह आंख कैंडी से ज्यादा महत्वपूर्ण तरीका वास्तव में कनेक्शन बिंदु है। (और मतलब समय में अनुकरण कि कहीं अधिक उपयोगी हो सकता है के लिए सीपीयू चक्र खा)

बस मेरे $ 0.02

+0

मैं देखता हूं आप क्या कह रहे हैं, लेकिन आईएमओ हमेशा यूआई पर जोखिम लेने के लायक है जो आपकी अवधारणा के साथ पूरी तरह से संरेखित होता है। केबल्स तुरंत अवधारणा को संवाद करते हैं; शायद एक क्वार्ट्ज-जैसा दृश्य एक अच्छा वैकल्पिक दृश्य बना देगा। – Brandon

+0

लिंक मर चुका है। –

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