如何正确地将颜色渐变应用于圆弧?

时间:2018-10-09 13:25:11

标签: javascript css d3.js svg

我正在构建外观如下的视觉效果:enter image description here

到目前为止,我已经设法创建了这个:enter image description here

这个想法是将一个值映射到一个角度,这样我就知道了箭头的指向,然后我将用与箭头所指向的弧上的点相同的颜色对箭头进行着色。

我本质上有两个问题:

首先,我该怎么做才能使颜色更好地排列。我使用了像这样的线性渐变:

 let defs = this.gaugeEl
                .append("defs")
                .classed("definitions",true);
        let gradient = defs
            .append("linearGradient")
            .classed("linearGradient",true);

        gradient
            .attr({
                id: 'gradient',
                x1: '0%',
                y1: '0%',
                x2: '100%',
                y2: '100%',
                spreadMethod: "pad"
            });

        gradient
            .append("stop")
            .classed('start',true)
            .attr({
                offset: '0%',
                'stop-color': 'lawngreen',
                'stop-opacity': 1
            });

        gradient.append("stop")
            .classed('end',true)
            .attr({
                offset: '100%',
                'stop-color': 'red',
                'stop-opacity': 1
            });

效果不是我想要的,可以做什么?

关于梯度如何工作的下一个问题,我需要能够将角度与颜色相关联,以便可以为箭头和刻度线正确着色,而在当前设置中,我不知道该怎么做。甚至有可能吗?

2 个答案:

答案 0 :(得分:1)

我不知道这对您有多大用处。但是我遵循以下实现

  1. 将弧形分割成细小的弧形
  2. 使用scaleLinear关联颜色和角度并将圆弧分为四个部分

忽略错误的数学和代码!

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  
  #chart {
    width: 960px;
    height: 350px;
  }

</style>

<body>

  <svg id="chart">  
  </svg>



  <script src="http://d3js.org/d3.v5.min.js"></script>

  <script>
var vis = d3.select("#chart").append("g")
var pi = Math.PI;

var line = d3.line()
    .x(function (d) { return d.x; })
    .y(function (d) { return d.y; });

var lines = []



var breakPoints = 100;
var angleArr = [];
var arcArr = [];

//angleArr[0] = -pi/2; 

var colorScale = d3.scaleLinear()
    .domain([-pi/2, -pi/3,30*pi/180,pi/2])
    .range(['lightgreen', 'lightgreen', 'yellow','red']);
    
	
var angleScale = d3.scaleLinear()
    .range([-pi/2,pi/2])
    .domain([0,breakPoints - 1]);	
	

var prevAngle = -pi/2;	
for(var i = 0; i < breakPoints; i++) {
	angleArr[i] = angleScale(i);
	var singleArrow = [{"x":(150*Math.sin(angleArr[i])), "y":-(150*Math.cos(angleArr[i]))},{ "y":-(170*Math.cos(angleArr[i])), "x":(170*Math.sin(angleArr[i]))}];
	//var subArc = {"start": prev, "end":0};
	var subArc = {};
	lines.push(singleArrow);
	subArc["start"] = prevAngle;
	subArc["end"] = angleArr[i];
	prevAngle = angleArr[i];
	arcArr.push(subArc);
}

	
var arc = d3.arc()
    .innerRadius(160)
    .outerRadius(170)
    .startAngle(-(pi/2)) //converting from degs to radians
    .endAngle(pi/2) //just radians
    
vis.attr("width", "400").attr("height", "400") // Added height and width so arc is visible
    .append("g")
    .attr("transform", "translate(200,200)");

vis.selectAll("line")
   .data(lines)
   .enter()
   .append("path").attr("class","arrow").attr("d", line).attr("stroke",function(d,i) { 
	return colorScale(angleArr[i])}).attr("transform", "translate(200,200)");	

vis.selectAll("arcs")
   .data(arcArr)
   .enter()
   .append("path").attr("class","arc").attr("d", function(d,i) {
   return d3.arc()
    .innerRadius(160)
    .outerRadius(170)
    .startAngle(d.end)
    .endAngle(d.start)()}).attr("fill",function(d,i) { 
	return colorScale(angleArr[i])}).attr("transform", "translate(200,200)");	
	  
  </script>

</body>

答案 1 :(得分:0)

现在有一个更简单的方法可以通过名为conic-gradient的css属性来做到这一点

https://css-tricks.com/snippets/css/css-conic-gradient/

根据给定中心点的角度设置颜色。也许您可以通过单击事件来确定角度,从中心计算角度,然后以这种方式设置颜色。

这里有更多有关圆锥渐变的信息,包括如何计算:https://wiki.inkscape.org/wiki/index.php/Advanced_Gradients#Conical_gradient