радиальные градиенты для нескольких дуг в d3 - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть следующая диаграмма дуг:

enter image description here

Я хотел бы добавить градиент к каждой из отдельных дуг, которая вытекает из внешний радиус до внутренний радиус каждой отдельной дуги.

Я предполагаю, что мне нужно будет создать отдельный градиент для каждой дуги?

let radius = 100;

for(let i = 0; i < 5; i ++) {

  let grad = defs.append('radialGradient')
       .attr('id', 'mygrad' + i)
    .attr('gradientUnits', 'userSpaceOnUse')
          .attr('cx', '0')
    .attr('cy', '0')
    .attr('r', radius)

  grad.append('stop')
       .attr('offset', '0%')
    .attr('stop-color', 'white');

  grad.append('stop')
       .attr('offset', '100%')
    .attr('stop-color', 'blue');

  let arc = d3.arc()
    .outerRadius( radius )
    .innerRadius( radius - 50)
    .startAngle( degToRad(-90) )
    .endAngle( degToRad(90) );

  g.append('path')
    .attr('d', arc)
    .attr('fill', `url(#${'mygrad' + i })`)
    .attr('stroke', 'lightgrey');

  radius += 50;
}

enter image description here


let grad = defs.append('radialGradient')
       .attr('id', 'mygrad' + i)
    .attr('r', '80%')

  grad.append('stop')
       .attr('offset', '0%')
    .attr('stop-color', 'white');

grad.append('stop')
   .attr('offset', '100%')
  .attr('stop-color', 'blue');

enter image description here

Codepen

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

SVG 2 добавляет атрибут fr.Это позволяет определить внутренний начальный радиус для градиента.В сочетании с возможностью цитировать определения градиента в другие определения, ваш код может быть переписан как

let width = 800;
let height = 800;

let svg = d3.select('svg')
    .attr('width', width)
    .attr('height', height);

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

let g = svg.append('g')
	  .attr('transform', `translate(${width/2}, ${height/2})`);

let radius = 100;
    
let gradcolors = defs.append('radialGradient')
    .attr('id', 'gradcolors')
    .attr('gradientUnits', 'userSpaceOnUse')
    .attr('cx', '0')
    .attr('cy', '0')

gradcolors.append('stop')
    .attr('offset', '0%')
    .attr('stop-color', 'white');

gradcolors.append('stop')
    .attr('offset', '100%')
    .attr('stop-color', 'blue');

for(let i = 0; i < 5; i++) {

    let grad = defs.append('radialGradient')
        .attr('id', 'mygrad' + i)
        .attr('href', '#gradcolors')
        .attr('fr', radius - 50)
        .attr('r', radius)

    let arc = d3.arc()
        .outerRadius( radius )
        .innerRadius( radius - 50)
        .startAngle( -90 * (Math.PI / 180) )
        .endAngle( 90 * (Math.PI / 180) );

    g.append('path')
        .attr('d', arc)
        .attr('fill', `url(#${'mygrad' + i })`)
        .attr('stroke', 'lightgrey');

    radius += 50;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg> </svg>

Или вы используете атрибут spreadMethod="repeat" для определения только одного градиента с бесконечно повторяющимися цветами.

let width = 800;
let height = 800;

let svg = d3.select('svg')
    .attr('width', width)
    .attr('height', height);

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

let g = svg.append('g')
	  .attr('transform', `translate(${width/2}, ${height/2})`);

let radius = 100;
let radiusWidth = 50;
    
let grad = defs.append('radialGradient')
    .attr('id', 'mygrad')
    .attr('gradientUnits', 'userSpaceOnUse')
    .attr('spreadMethod', 'repeat')
    .attr('cx', '0')
    .attr('cy', '0')
    .attr('r', radiusWidth)

grad.append('stop')
    .attr('offset', '0%')
    .attr('stop-color', 'white');

grad.append('stop')
    .attr('offset', '100%')
    .attr('stop-color', 'blue');

for(let i = 0; i < 5; i++) {

    let arc = d3.arc()
        .outerRadius( radius )
        .innerRadius( radius - 50)
        .startAngle( -90 * (Math.PI / 180) )
        .endAngle( 90 * (Math.PI / 180) );

    g.append('path')
        .attr('d', arc)
        .attr('fill', 'url(#mygrad')
        .attr('stroke', 'lightgrey');

    radius += radiusWidth;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg> </svg>
0 голосов
/ 19 декабря 2018

Вам нужно работать в UserSpace Coordinates, потому что ограничивающий прямоугольник объекта не является хорошим квадратом, вы получите искаженный градиент.Укажите end-radius градиента (r).

Укажите уровень белого в процентах относительно end-radius градиента (параметр r)

  grad.append('stop')
    .attr('offset', `${100*(radius-50)/radius}%`)
    .attr('stop-color', 'white');

let width = 800;
let height = 800;

let svg = d3.select('svg')
  .attr('width', width)
  .attr('height', height);

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

let g = svg.append('g')
   .attr('transform', `translate(${width/2}, ${height/2})`);

let radius = 100;

for(let i = 0; i < 5; i ++) {

  let grad = defs.append('radialGradient')
    .attr('id', 'mygrad' + i)
    .attr('gradientUnits', 'userSpaceOnUse')
    .attr('cx', 0)
    .attr('cy', 0)
    .attr('r', radius);

  grad.append('stop')
    .attr('offset', `${100*(radius-50)/radius}%`)
    .attr('stop-color', 'white');

  grad.append('stop')
    .attr('offset', '100%')
    .attr('stop-color', 'blue');

  let arc = d3.arc()
    .outerRadius( radius )
    .innerRadius( radius - 50)
    .startAngle( degToRad(-90) )
    .endAngle( degToRad(90) );

  g.append('path')
    .attr('d', arc)
    .attr('fill', `url(#${'mygrad' + i })`)
    .attr('stroke', 'lightgrey');
  radius += 50;
}

//helpers
function degToRad( deg ) {
  return deg * (Math.PI / 180);
}
<svg></svg>

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
...