Как нанести градиентную маску на точки - PullRequest
0 голосов
/ 05 октября 2018

Я хотел бы применить маску с градиентом для всех точек на моем графике, но не для каждой точки.Этот градиент должен меняться радиально от начальной точки к максимальной точке.

Пример того, что я имею в виду, приведен ниже, я хотел бы добиться чего-то подобного:

image

Я попытался сгруппировать все круги следующим образом:

 this.svg.append("g").attr('class', 'items-container')
  .selectAll('circle')
  .data(this.data.suppliers)
  .enter()
  .append('circle')
  .attr(..) //added proper cx,cy,r so got circles in proper point

Затем я попытался создать градиент:

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

    var gradient = defs
      .append('linearGradient')
      .attr('id', 'svgGradient')
      .attr('x1', '0%')
      .attr('x2', '100%')
      .attr('y1', '0%')
      .attr('y2', '100%');

    gradient
      .append('stop')
      .attr('class', 'start')
      .attr('offset', '0%')
      .attr('stop-color', 'red')
      .attr('stop-opacity', 1);

    gradient
      .append('stop')
      .attr('class', 'end')
      .attr('offset', '100%')
      .attr('stop-color', 'blue')
      .attr('stop-opacity', 1);

И применить его к группе:

this.svg
  .select('.items-container')
  .style("fill","url(#svgGradient)")

Но это не работает.Не могли бы вы помочь мне здесь?

Ответы [ 3 ]

0 голосов
/ 05 октября 2018

Вы можете сделать это наоборот:

  1. Создать прямоугольник с градиентом, который имеет размер вашей диаграммы.
  2. Создайте маску из ваших кругов и примените эту маску к прямоугольнику.Если вы используете белый цвет и непрозрачность заливки <1 для своих кругов, это должно дать именно отображаемый эффект. </li>

Обновление: Вот иллюстрация моей идеи

enter image description here

0 голосов
/ 06 октября 2018

Вам просто нужно настроить определение вашего линейного градиента, чтобы оно определялось по холсту, а не по каждому объекту - что-то вроде

var gradient = defs
      .append('linearGradient')
      .attr('id', 'svgGradient')
      .attr('gradientUnits', 'userSpaceOnUse')
      .attr('x1', '100')
      .attr('x2', '600')
      .attr('y1', '100')
      .attr('y2', '600');

, где x1, x2 и т. Д. - это координаты области диаграммы.

0 голосов
/ 05 октября 2018

Мне кажется, это проблема XY .Насколько я могу сказать, вам не нужно <mask> или что-то подобное.Все, что вам нужно, это заполнить кружки в соответствии со значением в каратах, которое идет от 0 до 3.

При этом, и, поскольку ваша цветовая последовательность, вероятно, interpolateViridis , я предлагаю вам просто использоватьпоследовательная шкала ...

const colorScale = d3.scaleSequential(d3.interpolateViridis)
    .domain([0, 3]);

... и заполните свои круги согласно значению в каратах (здесь, свойство x):

circleSelection.style("fill", d => colorScale(d.x))

Вот демонстрационная версия:

const svg = d3.select("svg");
const data = d3.range(120).map(function(d, i) {
  return {
    y: 14*d3.easeCubic(i/120) + (Math.random()*(6*i/120)),
    x: i / 40
  }
});
const yScale = d3.scaleLinear()
  .range([280, 20])
  .domain([0, 20]);
const xScale = d3.scaleLinear()
  .range([30, 480])
  .domain([0, 3]);
const colorScale = d3.scaleSequential(d3.interpolateViridis)
  .domain([0, 3]);
const circles = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("r", 6)
  .attr("cx", d => xScale(d.x))
  .attr("cy", d => yScale(d.y))
  .style("stroke", "dimgray")
  .style("fill", d => colorScale(d.x));
svg.append("g")
  .attr("transform", "translate(30,0)")
  .call(d3.axisLeft(yScale))
svg.append("g")
  .attr("transform", "translate(0,280)")
  .call(d3.axisBottom(xScale))
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="300"></svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...