json 파일의 데이터와 함께 javascript, d3를 사용하여 호에서 방사형 그래디언트를 만드는 문제

Nov 18 2020

나는 자바 스크립트와 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) 채우기가 생성되는 방법의 두 가지 측면에서 다릅니다. 최종 목적을 위해 로컬 또는 URL에서 json 파일을 읽을 수 있어야합니다.
(1) jsfiddle 버전 1 URL에서 json을 읽고 채우기를 위해 그라디언트를 사용하려고합니다. . URL에서 읽는 데 문제가 있고 그라디언트 채우기 문제가 있다고 생각합니다.
(2) jsfiddle 버전 2 URL에서 json을 읽으려고 시도하지만 채우기에 그라디언트를 사용하지 않습니다. URL을 읽는 데 문제가 있습니다. 로컬 파일에서 json을 읽는 로컬 컴퓨터에서이 작업을 수행하면이 버전이 출력을 생성합니다 (그래디언트는 아님).
(3) jsfiddle Version 3 이것은 json을 data라는 지역 변수에 넣은 다음 그것을 사용합니다. 또한 채우기를 위해 그라디언트를 사용하려고합니다.
(4) jsfiddle 버전 4 이것은 json을 data라는 지역 변수에 넣은 다음 그것을 사용합니다. 채우기를 위해 그라디언트를 사용하지 않습니다. 이것은 jsfiddle에 출력을 제공하는 4 개 중 유일한 것입니다.

답변

MattSergejRinc Nov 19 2020 at 01:52

기본 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>