json - 使用 javascript、d3 和来自 json 文件的数据在弧中制作径向渐变的问题
问题描述
我正在使用 javascript 和 d3 (v6) 并致力于制作一个旭日形图 或至少一个具有不同径向距离的弧的图,其中每个弧可能有自己的梯度(从中心到外围的径向梯度)。在这一点上,我已经遵循了一些示例(例如, here,here),其中我设置了一组radialGradient 元素,然后使用其中的 id 来生成我的实际弧线中的填充。但是我正在从 json 文件中的数据生成我的弧线和渐变,这使得它与以前的问题不同,因为 svg 元素生成在 d3.json 调用中(例如这里)。我有两个问题。(1) 渐变设置的线条如下:
grads.append("stop")
.attr("offset", "0%").style("stop-color", "white")
.attr("offset", "100%").style("stop-color", "green");
但这些似乎并没有真正添加到 grads 元素中(当我查看网页中的检查器时)。
(2) 弧的链接似乎不起作用,尽管这可能是因为第一个问题。
JAVASCRIPT(可以在这里找到)
var width = window.innerWidth,
height = window.innerHeight;
var body = d3.select('body')
// append svg to the DIV
chart = d3.select(".chart");
const svg = chart.append("svg:svg")
.attr("width", width)
.attr("height", height);
/////////////////////////////////////// Global variables controlling the arc appearance //////////////////
const arcMin = 30;
const arcWidth = 45.5;
const arcPad = 1;
///////////////////////////////////////////////////////////////////////////////////////////////
d3.json('dataExample.json')
.then(function (data) {
const grads = svg.append("defs").selectAll("radialGradient").data(data.sequences);
grads.enter().append("radialGradient")
.attr("gradientUnits", "objectBoundingBox")
.attr("cx", 0)
.attr("cy", 0)
.attr("fr", (d, i) => arcMin + (d.pulse-1) * (arcWidth))
.attr("r", (d, i) => arcMin + d.pulse * (arcWidth))
.attr("id", function (d) {
return "grad" + d.code;
});
grads.append("stop")
.attr("offset", "0%").style("stop-color", "white")
.attr("offset", "100%").style("stop-color", "green");//eventually this gradient will go between two colors that are functions of the data that is read in from the json file
console.log(grads);
var arc = svg.selectAll('path.arc-path')
.data(data.sequences);
arc.enter()
.append('svg:path')
.attr('d', d3.arc()
.innerRadius((d, i) => arcMin + (d.pulse - 1) * (arcWidth) + arcPad)
.outerRadius((d, i) => arcMin + d.pulse * (arcWidth))
.startAngle(function (d, i) {
ang = (i * 30) * Math.PI / 180;
return ang;
})
.endAngle(function (d, i) {
ang = ((i + 1) * 30) * Math.PI / 180;
return ang;
})
)
.attr("class", ".arc-path") // assigns a class for easier selecting
.attr("transform", "translate(600,300)")
//.style('fill',(d) => `rgb(${d.code * 10},${d.code*20},${255 -d.code * 7})`); this works - but doesn't use the gradients
.style("fill", function (d) {return "url(#grad" + d.code + ")";})
})
JSONFILE(上面称为 dataExample.json)可以在这里找到
{"type":"sequenceData","sequences":[{"pulse":1,"code":0},{"pulse":1,"code":1},{"pulse":1,"code":2},{"pulse":2,"code":3},{"pulse":2,"code":4},{"pulse":2,"code":5},{"pulse":2,"code":6},{"pulse":2,"code":7},{"pulse":2,"code":8},{"pulse":2,"code":9},{"pulse":2,"code":10},{"pulse":3,"code":12}]}
index.html(可以在这里找到)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Gradient arc test</title>
</style>
<script type="text/javascript" src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<div class="chart"></div>
<script src="arcExample.js"> </script>
</body>
</html>
如果您注意到其他问题或不良编码习惯,请告诉我,因为我是新手。谢谢。
(已编辑)
根据 Ruben Helsloot 的评论,我对各个部分做了一些 jsfiddles。有4个小提琴。它们在两个方面有所不同:(1)如何读取 json 文件和(2)如何生成填充。我会注意到,出于我的最终目的,我需要能够从文件中读取 json 文件 - 无论是本地文件还是 URL
(1) jsfiddle 版本 1尝试从 URL 读取 json 并尝试使用渐变进行填充. 我认为从 url 读取有问题,渐变填充也有问题。
(2) jsfiddle 版本 2尝试从 URL 读取 json,但不使用渐变填充。这在读取 URL 时存在问题。当我在本地机器上从本地文件中读取 json 时,这个版本会生成输出(尽管不是渐变)。
(3) jsfiddle 版本 3这会将 json 放入一个名为 data 的局部变量中,然后使用它。它还尝试使用渐变进行填充。
(4) jsfiddle 版本 4这将 json 放入一个名为 data 的局部变量中,然后使用它。它不使用渐变填充。这是 4 个在 jsfiddle 上提供输出的唯一一个。
解决方案
您应该先学习基本的 SVG 1.1 规范,然后再学习如何将元素(而不是属性)添加到正确的 SVG 结构中。
下面是固定代码,虽然我不知道你想要实现什么渐变。您可以尝试将gradientUnits属性更改回objectBoundingBox,但首先也要尝试使用r属性。
var width = window.innerWidth,
height = window.innerHeight;
var body = d3.select('body')
// append svg to the DIV
chart = d3.select(".chart");
const svg = chart.append("svg:svg")
.attr("width", width)
.attr("height", height)
.attr("xmlns", "http://www.w3.org/2000/svg")
.attr("xmlns:xlink", "http://www.w3.org/1999/xlink");
/////////////////////////////////////// Global variables controlling the arc appearance //////////////////
const arcMin = 30;
const arcWidth = 45.5;
const arcPad = 1;
///////////////////////////////////////////////////////////////////////////////////////////////
var data = {"type":"sequenceData","sequences":[{"pulse":1,"code":0},{"pulse":1,"code":1},{"pulse":1,"code":2},{"pulse":2,"code":3},{"pulse":2,"code":4},{"pulse":2,"code":5},{"pulse":2,"code":6},{"pulse":2,"code":7},{"pulse":2,"code":8},{"pulse":2,"code":9},{"pulse":2,"code":10},{"pulse":3,"code":12}]};
const grads = svg.append("defs").selectAll("radialGradient").data(data.sequences);
gradsWrap = grads.enter().append("radialGradient")
//.attr("gradientUnits", "objectBoundingBox")
.attr("gradientUnits", "userSpaceOnUse")
.attr("cx", 0)
.attr("cy", 0)
//.attr("fr", (d, i) => arcMin + (d.pulse-1) * (arcWidth))
//.attr("r", (d, i) => arcMin + (d.pulse-1) * (arcWidth))
.attr("fr", "0%")
.attr("r", "25%")
.attr("id", function (d) {
return "grad" + d.code;
})
gradsWrap.append("stop")
.attr("offset", "0%")
.attr("stop-color", "white");
gradsWrap.append("stop")
.attr("offset", "100%").attr("stop-color", "green");//eventually this gradient will go between two colors that are functions of the data that is read in from the json file
console.log(grads);
var arc = svg.selectAll('path.arc-path')
.data(data.sequences);
arc.enter()
.append('svg:path')
.attr('d', d3.arc()
.innerRadius((d, i) => arcMin + (d.pulse - 1) * (arcWidth) + arcPad)
.outerRadius((d, i) => arcMin + d.pulse * (arcWidth))
.startAngle(function (d, i) {
ang = (i * 30) * Math.PI / 180;
return ang;
})
.endAngle(function (d, i) {
ang = ((i + 1) * 30) * Math.PI / 180;
return ang;
})
)
.attr("class", ".arc-path") // assigns a class for easier selecting
.attr("transform", "translate(" + width/2 + "," + height/2 + ")")
.attr('stroke', 'white')
.style('stroke-width', '2px')
.attr("fill", function (d) {
//return "red";
return "url(#grad" + d.code + ")";
})
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Gradient arc test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
</head>
<body>
<div class="chart"></div>
</body>
推荐阅读
- python - 为什么应用于 TSP 的这种模拟退火算法不收敛?
- php - 图片上传 Laravel 和 Windows Server 2019 失败
- python - conda build 错误:找不到 pytest-runner 的匹配分布
- java - 重定向到另一个页面时如何保存数据
- r - 仅在下载时禁止数据表中的行名
- python - Numpy uint16 加法无溢出异常
- python - 可以monkeypatch numpy 数组切片行为吗?
- css - 为什么我的汉堡菜单上的转换不起作用?
- hibernate - JPA Hibernate - 如何从字符串数组“String []”创建表
- html - 当其余页面是用简单的 HTML5 编写时,是否可以通过 PUG 将一页添加到现有的父系项目中?