d3.js 使用D3,如何迭代一个非均匀的矩阵(类别),并根据类别颜色图绘制矩形?

8yoxcaq7  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(135)

我刚刚开始与D3和React,也许这就是为什么我一直无法解决这个简单的问题,因为几天。
我有一个CSV文件,我从其中读取列,其中一列是我需要绘制的数组。因为我是D3和React的新手,所以我想先绘制一个1D数组,然后再绘制2D数组。我已经成功地绘制了1D数组,但无论我怎么尝试,我都无法让2D数组工作。
为了简单起见,我们现在对这两个数据进行硬编码。
最初的一维数组是-

const emotions = ['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'];

它后来变成了2D,如下所示-

const emotions = [
['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'],
['sadness', 'sadness', 'joy', 'joy', 'joy']
];

我做了一个比例来Map类别与颜色如下-

const emoScale = d3.scaleOrdinal()
        .range(['red', 'green', 'purple', 'yellow', 'white', 'gray', 'orange'])
        .domain(['anger', 'disgust', 'fear', 'joy', 'neutral', 'sadness', 'surprise']);

之后我试着成功地显示了一维数组,比如-

const emotion1D = ['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'];

    const emoScale = d3.scaleOrdinal()
        .range(['red', 'green', 'purple', 'yellow', 'white', 'gray', 'orange'])
        .domain(['anger', 'disgust', 'fear', 'joy', 'neutral', 'sadness', 'surprise']);
    console.log(emoScale("anger"));
          
    const d3Chart = useRef();
   
    const svg = d3.select(d3Chart.current);
        var selection = svg.selectAll("rect").data(emotion1D);
        // var yScale = emoScale;
        selection
            .enter()
            .append("rect")
            .attr("x", (d, i) => 0)
            .attr("y", (d, i) => i*11)
            .attr("width", 10)
            .attr("height", 10)
            .attr("fill", function(d) { return emoScale(d); })

输出是一个不同颜色的矩形的堆叠条--这正是我所需要的。现在我需要在矩阵中显示尽可能多的行。因此,如果我在二维矩阵上工作,那么我的问题就解决了。
最后,我应该能够看到另一个由不同颜色和不同总大小的堆叠矩形组成的条形图,就在第一个条形图的旁边......依此类推,具体取决于我有多少行以及其中有多少元素。
在搜索如何渲染2D数组时,我遇到了嵌套选择。这就是我尝试解决这个问题的方法。想法是,对于矩阵中的1D数组,Y位置保持不变,Xx+10变化。对于1D数组中的数据,Yy*rect_height变化,X保持不变。
我试过对svg的groupxy位置做了很多修改,但是没有一个能满足我的要求。在某个时候我得到了一个对角线,但是那不是我想要的。我现在的代码如下...我不知道为什么显示不一致...当我修改一些东西的时候,它似乎显示了很少的对角线。但是刷新它总是给我一个空白的屏幕。

const emotion2D = [['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'],['sadness', 'sadness', 'joy', 'joy', 'joy']];

    const emotion1D = ['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'];

    const emoScale = d3.scaleOrdinal()
        .range(['red', 'green', 'purple', 'yellow', 'white', 'gray', 'orange'])
        .domain(['anger', 'disgust', 'fear', 'joy', 'neutral', 'sadness', 'surprise']);
    console.log(emoScale("anger"));

    const d3Chart = useRef();

    const svg = d3.select(d3Chart.current);
        var selection = svg.selectAll("rect").data(emotion2D);

        selection
        .enter()
        .append("g")
        .attr("x", (d, i) => i+10)
        .attr("y", (d, i) => 0)
        .selectAll("rect")
        .data(function(d,i){
            return d[i];
          })
        .enter()
        .append("rect")
        .attr("x", (d, i) => 0)
        .attr("y", (d, i) => i*11)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill", function(d) { return emoScale(d); })

完整的React文件如下-

Chart.jsx

import React, { Component } from 'react';
import * as d3 from 'd3';
import { useRef } from 'react';

const Chart = function() {      
    const emotion2D = [['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'],['sadness', 'sadness', 'joy', 'joy', 'joy']];

    const emotion1D = ['neutral', 'surprise', 'disgust', 'fear', 'sadness', 'fear', 'joy', 'sadness', 'joy'];

    const emoScale = d3.scaleOrdinal()
        .range(['red', 'green', 'purple', 'yellow', 'white', 'gray', 'orange'])
        .domain(['anger', 'disgust', 'fear', 'joy', 'neutral', 'sadness', 'surprise']);
    console.log(emoScale("anger"));
          
    const d3Chart = useRef();
 
    const svg = d3.select(d3Chart.current);
        var selection = svg.selectAll("rect").data(emotion2D);
        // var yScale = emoScale;

        selection
        .enter()
        .append("g")
        .attr("x", (d, i) => i+10)
        .attr("y", (d, i) => 0)
        .selectAll("rect")
        .data(function(d,i){
            return d[i];
          })
        .enter()
        .append("rect")
        .attr("x", (d, i) => 0)
        .attr("y", (d, i) => i*11)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill", function(d) { return emoScale(d); })

    return(
        <div>
            <svg style={{border: "1px solid black"}} ref={d3Chart}>
            </svg>
        </div>
    )
}
export default Chart;

应用程序js

import './App.css';
import Chart from './Chart';

function App() {

  return (
     <Chart />
  );
}

export default App;
h79rfbju

h79rfbju1#

我没有正确分组。下面的代码似乎可以使它工作-

var groups = svg.selectAll("g")
                    .data(emotion2D)
                    .join('g')
                    .attr("transform", (d, i) => 'translate(' + (11 * i) + ',0)');
       
    groups
        .selectAll("rect")
        .enter()
        .data(function(d,i){
            return d;
          })
        .join('rect')
        .attr("x", (d, i) => 0)
        .attr("y", (d, i) => 140-(i*11))
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill", function(d) { return emoScale(d); })

相关问题