2016-12-07 13 views
2

Я нарисовал arc, используя D3.js, который по умолчанию имеет квадратные формы.D3 Дуга с закругленным концом Chevron

var arc = d3.arc() 
    .innerRadius(0) 
    .outerRadius(100) 
    .startAngle(0) 
    .endAngle(Math.PI); 
d3.selectAll('svg') 
    .append('path') 
    .attr('d', function() { 
     return arc(); 
    }); 

Как нарисовать дугу с формой шеврона на одном конце.

Chevron shape

+0

SVG путь может быть. Вы просите что-то вроде силовых направленных дуг, направляясь в одно направление вокруг круга? И концы не имеют квадратную форму, они просто плоские. – Vlad

+1

Что вы подразумеваете под * «... дугой с шевронной формой на одном конце» *? Что такое * дуга * должна выглядеть? Где * конец * этой дуги, где должен быть нарисован шеврон. Не могли бы вы нарисовать визуальный результат, который вы после? – altocumulus

+0

Можете ли вы разместить точную форму, которую хотите. Или определите, как должен выглядеть ваш объект. –

ответ

3

Я бы просто использовал генератор путей d3 с маркером SVG. Добавьте любую фигуру в любой путь. Отредактируйте «концы», отредактировав определение маркера. Используйте генератор путей D3 для определения вашей дуги (или любого пути).

Следует отметить, что если вы примете такой подход, вы должны использовать генератор пути d3, а не генератор дуги d3, потому что генератор дуги неявно закрывает путь (помещая маркер конца в начало пути) ,

В моем примере я добавил шеврон начала, а просто чтобы показать, что это так тривиально, как добавление .attr("marker-start","url(#chevron)") и .attr("marker-end","url(#chevron)")

D3 Путь Генератор | https://github.com/d3/d3-path/blob/master/README.md#path

SVG Markers | https://developer.mozilla.org/en-US/docs/Web/SVG/Element/marker


редактировать: и теперь, когда я думаю об этом, вероятно, можно использовать d3.symbols для генерации маркеров/заканчивается для вас вместо того, чтобы вручную задающего пути формы. Шеврон должен быть обычным, но вы, вероятно, можете использовать символ треугольника.

D3 Символы | https://github.com/d3/d3-shape#symbols


console.clear() 
 

 
var path = d3.path() 
 
path.arc(225,80,70,1,-.5) 
 

 
var path2 = d3.path() 
 
path2.moveTo(20,20) 
 
path2.bezierCurveTo(150,300,200,0,450,100) 
 

 
d3.select("svg").append("path") 
 
    .attr("d", path2.toString()) 
 
    .attr("stroke","steelblue") 
 
    .attr("fill","none") 
 
    .attr("stroke-width","20") 
 
    .attr("marker-start","url(#chevron)") 
 
    .attr("marker-end","url(#chevron)") 
 

 
d3.select("svg").append("path") 
 
    .attr("d", path.toString()) 
 
    .attr("stroke","#43A2CA") 
 
    .attr("fill","none") 
 
    .attr("stroke-width","20") 
 
    .attr("marker-start","url(#chevron)") 
 
    .attr("marker-end","url(#chevron)")
<script src="https://unpkg.com/[email protected]"></script> 
 
<?xml version="1.0"?> 
 
<svg width="500" height="200" viewBox="0 0 500 200"> 
 

 
    <defs> 
 
    <marker id="chevron" 
 
     viewBox="0 0 20 20" refX="10" refY="10" 
 
     markerUnits="userSpaceOnUse" 
 
     markerWidth="20" markerHeight="20" 
 
     orient="auto" fill="black"> 
 
     <path d="M0 0 10 0 20 10 10 20 0 20 10 10Z" /> 
 
    </marker> 
 
    </defs> 
 

 
</svg>

+0

После второго взгляда, я действительно должен был наградить вас щедростью, извинения. Маркеры - действительно классная функция, о которой я не знал.Теперь единственная проблема, с которой я сталкиваюсь, заключается в том, что анимация пути, так что она выглядит так, будто она нарисована, не также анимирует расположение маркера. –

+0

@MuhammadRehanSaeed, не беспокоит человек. Иногда есть несколько хороших ответов на вопрос, и это действительно здорово, что Эндрю Рид сделал обычай d3-chevronArc, чтобы он соответствовал вашему конкретному варианту использования. Дайте мне знать, если вы опубликуете новый вопрос об анимационной проблеме. –

5

Я думаю, что я понимаю, что вы ищете, так что я дам ему идти:

Как вы, наверное, догадались из документации d3.js, d3.arc() не имеют методы, необходимые для создания точки на одном конце. На обоих концах накладываются прокладки и закругленные углы, и я не вижу, как они будут работать, чтобы сформировать точку на обоих концах, не говоря уже о одном.

Два решения приходят на ум (и есть, вероятно, много, что я даже не могу представить)

  1. отсечь конце каждой дуги, на основе его конечного угла, и добавить треугольник или другой (альтернативно, примените какую-то маску для обрезки конца в точку)
  2. Попытка переделать d3.arc() в соответствии с вашими потребностями, принимая приглашение разработать/уточнить d3 модульным способом.

Лично я считаю, что вариант один, вероятно, гораздо менее чист и, вероятно, сложнее его проектировать. Вариант второй должен быть выполнимым, и с этим поощрением погружаться и создавать модули:

Маленькие файлы приятные, но модульность также делает D3 более увлекательной. Микролисты легче понять, развить и протестировать. Они облегчают участие и содействие новым людям. Они уменьшают различие между «основным модулем» и «плагином» и увеличивают темпы разработки в функциях D3. (https://github.com/d3/d3/blob/master/CHANGES.md)

Я думал, что отдам это.


Я соединил попытку, которая может стать началом для шеврон наконечниками дуговой модуль на основе функции d3.arc().

Округленная угловая часть функции d3.arc() в модуле d3-shape.js, вероятно, является лучшим местом для просмотра, поскольку она показывает модификации концов дуги. Части модуля, которые изменяют дугу, в случае закругленными углами, выглядит следующим образом:

 context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); 
     context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); 
     context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); 

Наружный край обрабатывается первым (и показано выше). Первая строка - округление на заднем внешнем углу, третья - округление на переднем внешнем углу. Простое удаление третьей линии позволяет заостренную дугу (если вы также удалите ее из внутреннего края). Тогда оставшаяся задача - сделать другой конец дуги плоским, что я сделал, используя начальный угол и внутренние внешние радиусы, чтобы найти углы дуги, чтобы создать плоский конец.

Конечный результат был что-то вроде:

// get tail coordinate (outer) 
    var tailOuter = {}; 
    tailOuter.x = Math.cos(a0) * r1; // a0 = starting angle 
    tailOuter.y = Math.sin(a0) * r1; // r1 = outer radius 

    context.moveTo(tailOuter.x, tailOuter.y); 
    context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); 

Я соединил быстрый и грязный module, который принимает функцию d3.arc() и создает функцию d3.cheveronArc() вместо этого.Это измененная версия d3.arc() и имеет только четыре метода (inner/outerRadius(), start/endAngle()). У него нет средств для проверки параметров, которые могут вызвать неправильное поведение (например: шеврон длиннее дуги). Это просто доказательство концепции, хотя я доволен тем, как он выглядит для довольно быстрой попытки:

enter image description here

Как вы могли заметить, внутренний самый круг имеет странную форму вблизи ее хвоста, небольшой внутренний радиусы, похоже, вызывают такие проблемы.

Код можно посмотреть на сайте: http://bl.ocks.org/andrew-reid/3375e602cc6c00c4e3ea4799d171ee27

Глядя на него, я чувствую, что я хочу, чтобы добавить возможность добавить обратную шеврона к заднему концу дуги для лучшего визуального эффекта, но это другая проблема.

+0

Хороший ответ. Единственное изменение, которое, как мне кажется, должно быть сделано, - это не центрировать точку, а скорее обеспечить создание равнобедренного треугольника. Выполняя поиск изображения для «круглой стрелки», все изображения используют равнобедренные стрелки в качестве их точки. –

 Смежные вопросы

  • Нет связанных вопросов^_^