【问题标题】:How to apply gradient mask on dots如何在点上应用渐变蒙版
【发布时间】:2018-10-06 14:03:26
【问题描述】:

我想为我的绘图上的所有点应用渐变蒙版,但不是为每个点应用。该梯度应该从起点到最大点呈放射状变化。

我的意思的例子如下,我想实现与此完全相似的东西:

我尝试像这样对所有圈子进行分组:

 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)")

但它不起作用。你能帮帮我吗?

【问题讨论】:

标签: javascript d3.js svg


【解决方案1】:

这对我来说似乎是XY Problem。据我所知,您不需要<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>

【讨论】:

    【解决方案2】:

    你可以反过来做:

    1. 创建一个具有图表大小的渐变矩形。
    2. 用你的圆圈创建一个蒙版,并将这个蒙版应用于矩形。如果你为你的圆圈使用白色和填充不透明度

    更新:这是我的想法的插图

    【讨论】:

      【解决方案3】:

      您只需要调整线性渐变的定义,以便在画布上定义它而不是每个对象 - 类似于

      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 等是图表区域的坐标

      【讨论】:

        猜你喜欢
        • 2021-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多