填充不使用areaRadial()生成的形状

时间:2018-04-10 12:21:52

标签: d3.js svg

我正在研究一种看起来像熔岩灯的东西。不幸的是,我在开始时已经失败了:
我设法创建随机生成的blob,但我无法应用填充。中风工作得很好。

这是创建blob的相关代码:

var ctx = this; // context

this.path = d3.areaRadial()
    .angle(function(d) {return d.theta})
    .radius(function(d) {return d.r})
    .curve(d3.curveCatmullRomClosed.alpha(1));

// create the blob
this.create = function() {
    var anchors = [];
    for (var i = 0; i < ctx.options.anchors; i++) {
        var currTheta = i * (360 / ctx.options.anchors) + rand(ctx.options.spread.theta);
        var currRadians = Math.radians(currTheta);
        var currRadius = ctx.options.radius + rand(ctx.options.spread.r);

        anchors.push({theta: currRadians, r: currRadius});
    }

    var pathData = ctx.path(anchors);
    d3.select(ctx.options.target).append('path')
        .attr('d', pathData)
        .attr('class', 'blob')
        .style('opacity', ctx.options.opacity)
        .style('transform', 'translate(' + ctx.x + 'px, ' + ctx.y + 'px)')
        .attr('transform', 'translate(' + ctx.x + 'px, ' + ctx.y + 'px)');

    console.log(pathData);
}

function rand(x) // creates a random number between -0.5 * x and 0.5 * x

完整代码:https://codepen.io/normanwink/pen/BrMVrE

谢谢!

2 个答案:

答案 0 :(得分:2)

这是预期的行为,因为您正在使用radius,即:

  

等同于area.y,除了访问者返回半径:距原点的距离⟨0,0⟩。

对于area.y

  

如果指定y,将y0设置为y,将y1设置为null 并返回此区域生成器。如果未指定y,则返回当前的y0访问器。 (强调我的)

因此,您可能需要outerRadius

this.path = d3.areaRadial()
    .angle(function(d) {
        return d.theta
    })
    .outerRadius(function(d) {
        return d.r
    })
    .curve(d3.curveCatmullRomClosed.alpha(1));

这是您的代码仅包含该更改:

(function() {
	"use strict";
	
	// window size
	var windowX = window.innerWidth;
	var windowY = window.innerHeight;
	
	var svgX = windowX;
	var svgY = windowY;
	
	var blobCount = 1;
	
	function init() {
		// console.log(new Blob());
		
		var svg = d3.select('#svg')
			.attr('viewBox', '0 0 ' + svgX + ' ' + svgY)
			.attr('preserveAspectRatio', 'xMinYMin meet');
    
		for (var i = 0; i < blobCount; i++) {
			var newBlob = new Blob(svgX * 0.5, svgY * 0.5);
		}
	}
	
	function Blob(x, y) {
		var ctx = this; // context
		
		this.options = {
			anchors: 8,
			breathe: 30,
			fill: '#ffffff',
			opacity: 0.5,
			radius: 150,
			spread: {
				theta: 10, // angle
				r: 300 // radius
			},
			target: '#svg',
		};
		
		this.x = x || 0;
		this.y = y || 0;
		
		this.path = d3.areaRadial()
			.angle(function(d) {return d.theta})
			.outerRadius(function(d) {return d.r})
			.curve(d3.curveCatmullRomClosed.alpha(1));
		
		// create the blob
		this.create = function() {
			var anchors = [];
			for (var i = 0; i < ctx.options.anchors; i++) {
				var currTheta = i * (360 / ctx.options.anchors) + rand(ctx.options.spread.theta);
				var currRadians = Math.radians(currTheta);
				var currRadius = ctx.options.radius + rand(ctx.options.spread.r);
				
				anchors.push({theta: currRadians, r: currRadius});
			}
			
			var pathData = ctx.path(anchors);
			d3.select(ctx.options.target).append('path')
				.attr('d', pathData)
				.attr('class', 'blob')
				.style('opacity', ctx.options.opacity)
				.style('transform', 'translate(' + ctx.x + 'px, ' + ctx.y + 'px)')
				.attr('transform', 'translate(' + ctx.x + 'px, ' + ctx.y + 'px)');
				
		}
		
		// update position and anchor movement
		this.update = function() {
			
		}
		
		// apply changes
		this.render = function() {
			
		}
		
		this.create();
	}
	
	function rand(i) {
		return (Math.random()-0.5) * (i || 1);
	}
	
	Math.radians = function(degrees) {
		return degrees * Math.PI / 180;
	};
	
	// init when ready
	init();

})();
#svg {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 1;
}

.blob {
	fill: blue; /* why is this not working? */
	stroke: red;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg id="svg"></svg>

答案 1 :(得分:1)

您的问题是pathData,因为如果您将.attr('d', pathData)替换为有效路径.attr('d', 'M37,17v15H14V17z M50,0H0v50h50z'),那么您的填充工作正常。

我会继续搜索这个问题,只是想给你一个提示,也许你会发现问题比我更快。 :)