एक चाप के लिए एसवीजी पथ की गणना कैसे करें (एक वृत्त की)


191

(२००,२००), त्रिज्या २५ पर केन्द्रित वृत्त को देखते हुए, मैं २ degree० डिग्री से १३५ डिग्री तक आर्क कैसे आकर्षित कर सकता हूं और एक जो २ one० से ४५ डिग्री तक जाता है?

0 डिग्री का मतलब है कि यह एक्स-एक्सिस (राइट साइड) पर सही है (इसका अर्थ 3 o 'क्लॉक पोजिशन है) 270 डिग्री का मतलब है कि यह 12 बजे की स्थिति है, और 90 का मतलब है कि यह 6 बजे की स्थिति है

अधिक सामान्यतः, एक सर्कल के भाग के लिए एक चाप के लिए एक रास्ता क्या है

x, y, r, d1, d2, direction

अर्थ

center (x,y), radius r, degree_start, degree_end, direction

जवाबों:


379

@ Wdebeaum के शानदार उत्तर पर विस्तार करते हुए, यहां बताया गया है कि एक मार्ग बनाने के लिए एक विधि है:

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;

  return {
    x: centerX + (radius * Math.cos(angleInRadians)),
    y: centerY + (radius * Math.sin(angleInRadians))
  };
}

function describeArc(x, y, radius, startAngle, endAngle){

    var start = polarToCartesian(x, y, radius, endAngle);
    var end = polarToCartesian(x, y, radius, startAngle);

    var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

    var d = [
        "M", start.x, start.y, 
        "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
    ].join(" ");

    return d;       
}

उपयोग करने के लिए

document.getElementById("arc1").setAttribute("d", describeArc(200, 400, 100, 0, 180));

और आपके html में

<path id="arc1" fill="none" stroke="#446688" stroke-width="20" />

लाइव डेमो


9
यह सुपर है! ध्यान दें कि arcSweepचर वास्तव में large-arc-flagsvg A पैरामीटर को नियंत्रित कर रहा है । उपरोक्त कोड में, sweep-flagपैरामीटर के लिए मान हमेशा शून्य होता है। arcSweepशायद कुछ नाम बदला जाना चाहिए longArc
स्टीवन ग्रोसमार्क

धन्यवाद @PocketLogic, आपके सुझाव के अनुसार (अंत में) अपडेट किया गया है।
opsb

2
वास्तव में उपयोगी, धन्यवाद। केवल एक चीज मुझे मिली है कि अगर आप नकारात्मक कोणों का उपयोग करते हैं तो बड़े एएके तर्क काम नहीं करता है। यह -360 से +360 तक काम करता है: jsbin.com/kopisonewi/2/edit?html,js,output
Xcodo

मुझे याद है कि मानक क्यों समान तरीके से आर्क्स को परिभाषित नहीं करता है।
polkovnikov.ph

4
और चाप लंबाई की छोटी मात्रा में कटौती करना न भूलें: endAngle - 0.0001यदि नहीं, तो पूर्ण चाप प्रदान नहीं किया जाएगा।
साकई

128

आप अण्डाकार Aआरसी कमांड का उपयोग करना चाहते हैं । दुर्भाग्य से आपके लिए, आपको ध्रुवीय निर्देशांक (त्रिज्या, कोण) के बजाय प्रारंभ और अंत बिंदुओं के कार्टेशियन निर्देशांक (x, y) को निर्दिष्ट करने की आवश्यकता है, इसलिए आपको कुछ गणित करना होगा। यहां एक जावास्क्रिप्ट फ़ंक्शन है, जिसे काम करना चाहिए (हालांकि मैंने इसका परीक्षण नहीं किया है), और जो मुझे आशा है कि काफी आत्म-व्याख्यात्मक है:

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = angleInDegrees * Math.PI / 180.0;
  var x = centerX + radius * Math.cos(angleInRadians);
  var y = centerY + radius * Math.sin(angleInRadians);
  return [x,y];
}

कौन सा कोण किन घड़ी स्थितियों के अनुरूप है, यह समन्वय प्रणाली पर निर्भर करेगा; बस स्वैप और / या पाप / कोस शब्दों को आवश्यक रूप से नकार दें।

चाप कमांड में ये पैरामीटर हैं:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y

अपने पहले उदाहरण के लिए:

rx= ry= 25 और x-axis-rotation= 0, क्योंकि आप एक वृत्त चाहते हैं और एक दीर्घवृत्त नहीं। आप Mऊपर दिए गए फ़ंक्शन, क्रमशः उपज (200, 175) और के बारे में (182.322, 217.678) का उपयोग करके, दोनों शुरुआती निर्देशांक (जो आपको ove चाहिए ) और निर्देशांक (x, y) को समाप्त कर सकते हैं। अब तक इन बाधाओं को देखते हुए, वास्तव में चार चाप हैं जिन्हें खींचा जा सकता है, इसलिए दो झंडे उनमें से एक का चयन करते हैं। मैं अनुमान लगा रहा हूं कि आप शायद एक छोटा चाप (अर्थ large-arc-flag= 0) खींचना चाहते हैं , कोण की कमी (अर्थ sweep-flag= 0) की दिशा में । सभी एक साथ, एसवीजी पथ है:

M 200 175 A 25 25 0 0 0 182.322 217.678

दूसरे उदाहरण के लिए (मान लें कि आप एक ही दिशा में जा रहे हैं, और इस तरह एक बड़ा चाप), एसवीजी पथ है:

M 200 175 A 25 25 0 1 0 217.678 217.678

दोबारा, मैंने इनका परीक्षण नहीं किया है।

(2016-06-01 को संपादित करें), @clocksmith की तरह, यदि आप सोच रहे हैं कि उन्होंने इस API को क्यों चुना है, तो कार्यान्वयन नोट्स पर एक नज़र डालें । वे दो संभावित आर्क मापदंडों का वर्णन करते हैं, "एंडपॉइंट पैरामीटराइजेशन" (जो उन्होंने चुना था), और "सेंटर पैरामीटराइजेशन" (जो कि प्रश्न का उपयोग करता है जैसा है)। "एंडपॉइंट पैरामीटराइजेशन" के वर्णन में वे कहते हैं:

समापन बिंदु परिमाणीकरण के लाभों में से एक यह है कि यह एक सुसंगत पथ सिंटैक्स की अनुमति देता है जिसमें सभी पथ कमांड नए "वर्तमान बिंदु" के निर्देशांक में समाप्त होते हैं।

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

कार्यान्वयन नोट्स मूल प्रश्न के लिए भी उपयोगी हैं, क्योंकि उनके पास दो मापदंडों के बीच परिवर्तित करने के लिए अधिक गणितीय छद्मकोड है (जो मुझे पता नहीं था जब मैंने पहली बार यह उत्तर लिखा था)।


1
अच्छा लग रहा है, अगले प्रयास करेंगे। तथ्य यह है कि अगर यह आर्क का "अधिक" है (जब आर्क सर्कल के आधे से अधिक है) और large-arc-flag0 से 1 तक टॉगल किया जाना है तो कुछ बग का परिचय दे सकता है।
२०:१२

उह, यह svg आर्क्स के लिए एपीआई क्यों है?
घड़ी में

16

मैंने opsb के उत्तर को थोड़ा संशोधित किया और सर्कल सेक्टर के लिए समर्थन भरण में बनाया। http://codepen.io/anon/pen/AkoGx

जे एस

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;

  return {
    x: centerX + (radius * Math.cos(angleInRadians)),
    y: centerY + (radius * Math.sin(angleInRadians))
  };
}

function describeArc(x, y, radius, startAngle, endAngle){

    var start = polarToCartesian(x, y, radius, endAngle);
    var end = polarToCartesian(x, y, radius, startAngle);

    var arcSweep = endAngle - startAngle <= 180 ? "0" : "1";

    var d = [
        "M", start.x, start.y, 
        "A", radius, radius, 0, arcSweep, 0, end.x, end.y,
        "L", x,y,
        "L", start.x, start.y
    ].join(" ");

    return d;       
}

document.getElementById("arc1").setAttribute("d", describeArc(200, 400, 100, 0, 220));

एचटीएमएल

<svg>
  <path id="arc1" fill="orange" stroke="#446688" stroke-width="0" />
</svg>

5
कोडपेन लिंक मेरे लिए काम नहीं करता (क्रोम)
रे हुलहा

चाप को एसवीजी सीमाओं के बाहर खींचा जाता है। उदाहरण के लिए centerX, एसवीजी की ऊंचाई और परिवर्तन को centerYबढ़ाकर 100 कर दें।
ए। अकरम

आप मूल रूप से svg तत्व में एक दृश्य बॉक्स भी सेट कर सकते हैं। उदाहरण के लिएviewBox="0 0 500 500"
Håken Lid

7

यह एक पुराना प्रश्न है, लेकिन मैंने कोड को उपयोगी पाया और मुझे तीन मिनट की सोच को बचाया :) इसलिए मैं @opsb के उत्तर में एक छोटा सा विस्तार जोड़ रहा हूं ।

यदि आप इस आर्क को एक स्लाइस में बदलना चाहते हैं (भरने के लिए अनुमति देने के लिए) तो हम कोड को थोड़ा संशोधित कर सकते हैं:

function describeArc(x, y, radius, spread, startAngle, endAngle){
    var innerStart = polarToCartesian(x, y, radius, endAngle);
  	var innerEnd = polarToCartesian(x, y, radius, startAngle);
    var outerStart = polarToCartesian(x, y, radius + spread, endAngle);
    var outerEnd = polarToCartesian(x, y, radius + spread, startAngle);

    var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

    var d = [
        "M", outerStart.x, outerStart.y,
        "A", radius + spread, radius + spread, 0, largeArcFlag, 0, outerEnd.x, outerEnd.y,
        "L", innerEnd.x, innerEnd.y, 
        "A", radius, radius, 0, largeArcFlag, 1, innerStart.x, innerStart.y, 
        "L", outerStart.x, outerStart.y, "Z"
    ].join(" ");

    return d;
}

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;

  return {
    x: centerX + (radius * Math.cos(angleInRadians)),
    y: centerY + (radius * Math.sin(angleInRadians))
  };
}

var path = describeArc(150, 150, 50, 30, 0, 50)
document.getElementById("p").innerHTML = path
document.getElementById("path").setAttribute('d',path)
<p id="p">
</p>
<svg width="300" height="300" style="border:1px gray solid">
  <path id="path" fill="blue" stroke="cyan"></path>
</svg>

और तुम जाओ!


5

@ ऑप्सब के उत्तर साफ-सुथरे हैं, लेकिन केंद्र बिंदु सटीक नहीं है, इसके अलावा, @ जेथिन ने कहा, यदि कोण 360 है, तो कुछ भी नहीं खींचा जाता है।

@ जितिन ने 360 अंक तय किए, लेकिन अगर आपने 360 डिग्री से कम का चयन किया है, तो आपको आर्क लूप को बंद करने वाली एक लाइन मिल जाएगी, जिसकी आवश्यकता नहीं है।

मैंने तय किया है, और नीचे दिए गए कोड में कुछ एनीमेशन जोड़े हैं:

function myArc(cx, cy, radius, max){       
       var circle = document.getElementById("arc");
        var e = circle.getAttribute("d");
        var d = " M "+ (cx + radius) + " " + cy;
        var angle=0;
        window.timer = window.setInterval(
        function() {
            var radians= angle * (Math.PI / 180);  // convert degree to radians
            var x = cx + Math.cos(radians) * radius;  
            var y = cy + Math.sin(radians) * radius;
           
            d += " L "+x + " " + y;
            circle.setAttribute("d", d)
            if(angle==max)window.clearInterval(window.timer);
            angle++;
        }
      ,5)
 }     

  myArc(110, 110, 100, 360);
    
<svg xmlns="http://www.w3.org/2000/svg" style="width:220; height:220;"> 
    <path d="" id="arc" fill="none" stroke="red" stroke-width="2" />
</svg>


4

मैं @Ahtenus के उत्तर पर टिप्पणी करना चाहता था, विशेष रूप से रे हुल्हा टिप्पणी पर, जिसमें कहा गया था कि कोडपेन में कोई चाप नहीं है, लेकिन मेरी प्रतिष्ठा बहुत अधिक नहीं है।

इस कोडपेन के काम न करने का कारण यह है कि इसका html दोषपूर्ण है, जो शून्य की स्ट्रोक-चौड़ाई है।

मैंने इसे ठीक किया और यहां एक दूसरा उदाहरण जोड़ा: http://codepen.io/AnotherLinuxUser/pen/QEJmnN

HTML:

<svg>
    <path id="theSvgArc"/>
    <path id="theSvgArc2"/>
</svg>

प्रासंगिक सीएसएस:

svg {
    width  : 500px;
    height : 500px;
}

path {
    stroke-width : 5;
    stroke       : lime;
    fill         : #151515;
}

जावास्क्रिप्ट:

document.getElementById("theSvgArc").setAttribute("d", describeArc(150, 150, 100, 0, 180));
document.getElementById("theSvgArc2").setAttribute("d", describeArc(300, 150, 100, 45, 190));

3

एक छवि और कुछ पायथन

बस बेहतर स्पष्ट करने के लिए और एक और समाधान प्रदान करते हैं। Arc[ A] कमांड वर्तमान स्थिति को एक शुरुआती बिंदु के रूप में उपयोग करता है इसलिए आपको पहले Moveto[एम] कमांड का उपयोग करना होगा ।

फिर Arcनिम्नलिखित पैरामीटर हैं:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, xf, yf

यदि हम उदाहरण के लिए निम्नलिखित svg फ़ाइल को परिभाषित करते हैं:

<svg viewBox="0 0 500 500">
    <path fill="red" d="
    M 250 250
    A 100 100 0 0 0 450 250
    Z"/> 
</svg>

यहां छवि विवरण दर्ज करें

आप प्रारंभिक बिंदु Mको पैरामीटर xfऔर yfके साथ समाप्ति बिंदु के साथ सेट करेंगे A

हम हलकों की तलाश कर रहे हैं, इसलिए हम ऐसा करने के लिए rxसमान रूप से सेट करते ryहैं मूल रूप से अब यह त्रिज्या के सभी सर्कल को खोजने की कोशिश करेगा rxजो शुरुआती और अंत बिंदु को काटते हैं।

import numpy as np

def write_svgarc(xcenter,ycenter,r,startangle,endangle,output='arc.svg'):
    if startangle > endangle: 
        raise ValueError("startangle must be smaller than endangle")

    if endangle - startangle < 360:
        large_arc_flag = 0
        radiansconversion = np.pi/180.
        xstartpoint = xcenter + r*np.cos(startangle*radiansconversion)
        ystartpoint = ycenter - r*np.sin(startangle*radiansconversion)
        xendpoint = xcenter + r*np.cos(endangle*radiansconversion)
        yendpoint = ycenter - r*np.sin(endangle*radiansconversion)
        #If we want to plot angles larger than 180 degrees we need this
        if endangle - startangle > 180: large_arc_flag = 1
        with open(output,'a') as f:
            f.write(r"""<path d=" """)
            f.write("M %s %s" %(xstartpoint,ystartpoint))
            f.write("A %s %s 0 %s 0 %s %s" 
                    %(r,r,large_arc_flag,xendpoint,yendpoint))
            f.write("L %s %s" %(xcenter,ycenter))
            f.write(r"""Z"/>""" )

    else:
        with open(output,'a') as f:
            f.write(r"""<circle cx="%s" cy="%s" r="%s"/>"""
                    %(xcenter,ycenter,r))

मेरे द्वारा लिखी गई इस पोस्ट में आपकी अधिक विस्तृत व्याख्या हो सकती है ।


3

उत्तर-चाहने वालों (जो मैं भी था) के लिए ध्यान दें - यदि चाप का उपयोग करना अनिवार्य नहीं है , तो stroke-dasharrayएसवीजी का उपयोग करने के लिए एक दूर-वृत्त खींचने का एक सरल उपाय है <circle>

डैश एरे को दो तत्वों में विभाजित करें, और उनकी सीमा को वांछित कोण पर स्केल करें। प्रारंभिक कोण का उपयोग करके समायोजित किया जा सकता है stroke-dashoffset

दृष्टि में एक भी कोसाइन नहीं।

स्पष्टीकरण के साथ पूर्ण उदाहरण: https://codepen.io/mjurczyk/pen/wvBKOvP


2

Wdebeaum द्वारा मूल ध्रुवीय टार्टकार्टेशियन फ़ंक्शन सही है:

var angleInRadians = angleInDegrees * Math.PI / 180.0;

उपयोग करके प्रारंभ और अंतिम बिंदुओं को उलटना:

var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);

भ्रामक है (मेरे लिए) क्योंकि यह स्वीप-ध्वज को उलट देगा। का उपयोग करते हुए:

var start = polarToCartesian(x, y, radius, startAngle);
var end = polarToCartesian(x, y, radius, endAngle);

झाडू-झंडे के साथ = "0" सामान्य "काउंटर-क्लॉक-वार आर्क्स" खींचता है, जो मुझे लगता है कि आगे सीधे है। Https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths देखें


2

@ ऑप्सब के उत्तर के लिए एक मामूली संशोधन। हम इस विधि के साथ एक पूर्ण वृत्त खींच सकते हैं। यानी यदि हम देते हैं (0, 360) तो यह कुछ भी आकर्षित नहीं करेगा। तो इसे ठीक करने के लिए एक मामूली संशोधन किया गया है। यह स्कोर प्रदर्शित करने के लिए उपयोगी हो सकता है जो कभी-कभी 100% तक पहुंच जाता है।

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;

  return {
    x: centerX + (radius * Math.cos(angleInRadians)),
    y: centerY + (radius * Math.sin(angleInRadians))
  };
}

function describeArc(x, y, radius, startAngle, endAngle){

    var endAngleOriginal = endAngle;
    if(endAngleOriginal - startAngle === 360){
        endAngle = 359;
    }

    var start = polarToCartesian(x, y, radius, endAngle);
    var end = polarToCartesian(x, y, radius, startAngle);

    var arcSweep = endAngle - startAngle <= 180 ? "0" : "1";

    if(endAngleOriginal - startAngle === 360){
        var d = [
              "M", start.x, start.y, 
              "A", radius, radius, 0, arcSweep, 0, end.x, end.y, "z"
        ].join(" ");
    }
    else{
      var d = [
          "M", start.x, start.y, 
          "A", radius, radius, 0, arcSweep, 0, end.x, end.y
      ].join(" ");
    }

    return d;       
}

document.getElementById("arc1").setAttribute("d", describeArc(120, 120, 100, 0, 359));

2

ES6 संस्करण:

const angleInRadians = angleInDegrees => (angleInDegrees - 90) * (Math.PI / 180.0);

const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
    const a = angleInRadians(angleInDegrees);
    return {
        x: centerX + (radius * Math.cos(a)),
        y: centerY + (radius * Math.sin(a)),
    };
};

const arc = (x, y, radius, startAngle, endAngle) => {
    const fullCircle = endAngle - startAngle === 360;
    const start = polarToCartesian(x, y, radius, endAngle - 0.01);
    const end = polarToCartesian(x, y, radius, startAngle);
    const arcSweep = endAngle - startAngle <= 180 ? '0' : '1';

    const d = [
        'M', start.x, start.y,
        'A', radius, radius, 0, arcSweep, 0, end.x, end.y,
    ].join(' ');

    if (fullCircle) d.push('z');
    return d;
};

2
आप यकीनन ES6 टेम्पलेट शाब्दिक का उपयोग करके उदाहरण को स्पष्ट कर सकते हैं:const d = `M ${start.x} ${start.y} A ${radius} ${radius} 0 ${largeArc} 0 ${end.x} ${end.y}`
रॉय

0

चयनित उत्तर के आधार पर ReactJS घटक:

import React from 'react';

const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
    const angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;

    return {
        x: centerX + (radius * Math.cos(angleInRadians)),
        y: centerY + (radius * Math.sin(angleInRadians))
    };
};

const describeSlice = (x, y, radius, startAngle, endAngle) => {

    const start = polarToCartesian(x, y, radius, endAngle);
    const end = polarToCartesian(x, y, radius, startAngle);

    const largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

    const d = [
        "M", 0, 0, start.x, start.y,
        "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
    ].join(" ");

    return d;
};

const path = (degrees = 90, radius = 10) => {
    return describeSlice(0, 0, radius, 0, degrees) + 'Z';
};

export const Arc = (props) => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
    <g transform="translate(150,150)" stroke="#000" strokeWidth="2">
        <path d={path(props.degrees, props.radius)} fill="#333"/>
    </g>

</svg>;

export default Arc;

0

आप ऊपर दिए गए उत्तर के लिए JSFiddle कोड का उपयोग कर सकते हैं:

https://jsfiddle.net/tyw6nfee/

आपको केवल अंतिम पंक्ति कंसोल.लॉग कोड को बदलना होगा और इसे अपना स्वयं का पैरामीटर देना होगा:

  console.log(describeArc(255,255,220,30,180));
  console.log(describeArc(CenterX,CenterY,Radius,startAngle,EndAngle))

1
मैंने आपके स्निपेट में कुछ बदलाव किए हैं बस एक दृश्य परिणाम का उत्पादन करने के लिए। देखिए: jsfiddle.net/ed1nh0/96c203wj/3
ed1nh0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.