d3js 饼图,对于带有轻微圆角的部分具有特定的不太传统的不同模式

问题描述 投票:0回答:1

我正在尝试不同的图表样式 - 我想知道如何为不同的部分创建这些确切类型的图案纹理图表。

enter image description here

如果是像大/小点镶嵌这样不那么传统的图案,您如何开始创建其中一些特定图案。

enter image description here

或者如果有渐变而不是图案

enter image description here

在这种情况下,馅饼的边缘似乎有轻微的圆形,就好像它堆叠在彼此的顶部并覆盖得更多一样。 d3js 饼图,各个部分具有不同的模式

enter image description here

演示参考,左侧有图例 - 右侧有饼图/半饼图

enter image description here

https://codesandbox.io/p/sandbox/magical-wiles-forked-fvj79p

我当前的构建——普通馅饼

import React from 'react';
import * as d3 from 'd3';
import './PieChart1.scss';

class PieChart extends React.Component {
    constructor(props) {
        super(props);
        this.myRef = React.createRef();
        this.state = {
            data: [],
            theme: this.props.theme ? this.props.theme : ['#bde0fe', '#2698f9', '#71bcfd', '#f1f8fe']
        };
    }

    componentDidMount() {
        var $this = this.myRef.current;

        d3.select($this)
            .selectAll('svg')
            .remove();

        const data = this.props.data;

        const width = parseInt(this.props.width, 10),
            height = parseInt(this.props.height, 10),
            radius = parseInt(this.props.r, 10),
            innerradius = parseInt(this.props.ir, 10);

        var color = d3.scaleOrdinal().range(this.state.theme);

        var arc = d3
            .arc()
            .outerRadius(radius)
            .innerRadius(innerradius);

        data.forEach(function(d) {
            d.total = +d.value;
        });

        var pie = d3
            .pie()
            .sort(null)
            .value(function(d) {
                return d.total;
            });

        var svg = d3
            .select($this)
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .append('g')
            .attr('class', 'piechart')
            .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

        var segments = svg.append('g').attr('class', 'segments');

        var slices = segments
            .selectAll('.arc')
            .data(pie(data))
            .enter()
            .append('g')
            .attr('class', 'arc');

        slices
            .append('path')
            .attr('d', arc)
            .attr('fill', function(d, i) {
                return color(i);
            })
            .transition()
            .attrTween('d', function(d) {
                var i = d3.interpolate(d.startAngle+0.1, d.endAngle);
                return function(t) {
                    d.endAngle = i(t);
                    return arc(d);
                }
            });

    }

    render() {
        return <div ref={this.myRef} className="PieChart" />;
    }
}
export default PieChart;

我在制作图案时见过这个示例 - 如何制作这 4 种图案类型 - 其中一个似乎只是渐变

<!DOCTYPE html>
<html>
<head>
    <style>
        
    </style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="hook"></div>
<script type="text/javascript">
        // SVG injection:
var svg = d3.select("#hook").append("svg").attr("id", "d3svg")
    .attr("width", 120)
    .attr("height", 120);
//Pattern injection
var defs = svg.append("defs")
var pattern = defs.append("pattern")
        .attr({ id:"hash4_4", width:"8", height:"8", patternUnits:"userSpaceOnUse", patternTransform:"rotate(-45)"})
    .append("rect")
        .attr({ width:"4", height:"8", transform:"translate(0,0)", fill:"#88AAEE" });

//Shape design
svg.append("g").attr("id","shape")
    .append("circle")
.attr({cx:"60",cy:"60",r:"50", fill:"url(#hash4_4)" })
    </script>
</body>
</html>

找到这个作为参考 - 但不确定如何在演示中制作这些确切的图案

d3.js中如何使饼图的图案与扇区中心线平行?

<script src="https://unpkg.com/[email protected]/dist/d3.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<svg id="pie" width="300" height="200"> </svg>
<svg id="legend">
    
        <rect x="0" y="0" width="100" height="100"
        style="stroke: #000000; fill: url(#pattern0);" />   
    <rect x="100" y="0" width="100" height="100"
        style="stroke: #000000; fill: url(#pattern1);" />   
        <rect x="200" y="0" width="100" height="100"
        style="stroke: #000000; fill: url(#pattern2);" />   
</svg>

<script>
    var data = [{ year: '2001', value:10 },
            { year: '2002', value:30 },
            { year: '2003', value:60 },
           ]

    var svg = d3.select("svg#pie"),
        width = svg.attr("width"),
        height = svg.attr("height"),
        radius = Math.min(width, height) / 2,
        g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    var color = d3.scaleOrdinal(['#4daf4a','#377eb8','#ff7f00','#984ea3','#e41a1c']);

    // Generate the pie
    var pie = d3.pie().value(function(d) { 
    return d.value;})(data);

    // Generate the patterns
    var legend = d3.select("svg#legend"),
        defs = legend.append("defs");
    defs.selectAll("pattern")
        .data(pie)
        .enter()
        .append("pattern")
        .attr("id", (d, i) => "pattern" + i)
        .attr("patternUnits", "userSpaceOnUse")
        .attr("width", 20)
        .attr("height", 20)
        .attr("patternTransform", (d) => `rotate(${(d.startAngle + d.endAngle) * 90 / Math.PI})`)
        .style("fill", (d, i) => color(i))
             .append("rect")
             .attr("x", 5)
             .attr("y", 5)
             .attr("width", 10)
             .attr("height", 10)

    // Generate the arcs
    var arc = d3.arc()
                .innerRadius(0)
                .outerRadius(radius);

    //Generate groups
    var arcs = g.selectAll("arc")
                .data(pie)
                .enter()
                .append("g")
                .attr("class", "arc")

    //Draw arc paths
    arcs.append("path")
        .attr("d", arc)
  .attr('stroke', "black")
            .attr('stroke-width', '1')
            .attr("fill", function(d,i) { return  "url(#pattern" + i +")"});
</script>
</script>

9 月 19 日 - 最新版本 - 具有一般模式 - 但不是我们需要的模式或在正确位置的图例。

enter image description here

https://codesandbox.io/p/sandbox/magical-wiles-forked-pmdgrs

import React from "react";
import * as d3 from "d3";
import "./PieChart1.scss";

class PieChart extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    this.state = {
      data: [],
      theme: this.props.theme
        ? this.props.theme
        : ["#bde0fe", "#2698f9", "#71bcfd", "#f1f8fe"],
    };
  }

  componentDidMount() {
    var $this = this.myRef.current;

    d3.select($this).selectAll("svg").remove();

    const data = this.props.data;

    const width = parseInt(this.props.width, 10),
      height = parseInt(this.props.height, 10),
      radius = parseInt(this.props.r, 10),
      innerradius = parseInt(this.props.ir, 10);

    var color = d3.scaleOrdinal().range(this.state.theme);

    var arc = d3.arc().outerRadius(radius).innerRadius(innerradius);

    data.forEach(function (d) {
      d.total = +d.value;
    });

    var pie = d3
      .pie()
      .sort(null)
      .value(function (d) {
        return d.total;
      });

    var svg = d3
      .select($this)
      .append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("class", "piechart")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    // Generate the patterns
    var legend = d3.select("svg#legend"),
      defs = legend.append("defs");
    defs
      .selectAll("pattern")
      .data(pie(data))
      .enter()
      .append("pattern")
      .attr("id", (d, i) => "pattern" + i)
      .attr("patternUnits", "userSpaceOnUse")
      .attr("width", 20)
      .attr("height", 20)
      .attr(
        "patternTransform",
        (d) => `rotate(${((d.startAngle + d.endAngle) * 90) / Math.PI})`
      )
      .style("fill", (d, i) => color(i))
      .append("rect")
      .attr("x", 5)
      .attr("y", 5)
      .attr("width", 10)
      .attr("height", 10);

    var segments = svg.append("g").attr("class", "segments");

    var slices = segments
      .selectAll(".arc")
      .data(pie(data))
      .enter()
      .append("g")
      .attr("class", "arc");

    slices
      .append("path")
      .attr("d", arc)
      //.attr("fill", function (d, i) {
      //  return color(i);
      //})
      .attr("stroke", "black")
      .attr("stroke-width", "1")
      .attr("fill", function (d, i) {
        return "url(#pattern" + i + ")";
      })
      .transition()
      .attrTween("d", function (d) {
        var i = d3.interpolate(d.startAngle + 0.1, d.endAngle);
        return function (t) {
          d.endAngle = i(t);
          return arc(d);
        };
      });
  }

  render() {
    return (
      <>
        <svg id="legend">
          <rect
            x="0"
            y="0"
            width="100"
            height="100"
            style={{ stroke: "#000000", fill: "url(#pattern0)" }}
          />
          <rect
            x="100"
            y="0"
            width="100"
            height="100"
            style={{ stroke: "#000000", fill: "url(#pattern1)" }}
          />
          <rect
            x="200"
            y="0"
            width="100"
            height="100"
            style={{ stroke: "#000000", fill: "url(#pattern2)" }}
          />
        </svg>

        <div ref={this.myRef} className="PieChart" />
      </>
    );
  }
}
export default PieChart;
javascript d3.js
1个回答
0
投票

可以从生成图案制作器开始

首先是基本模式


仅限圆圈

enter image description here

https://codepen.io/geoffgraham/pen/aWZdXP——只是标记

我们需要用 js 重新制作 svg

<svg width="100%" height="100%">
  
  <!-- Create mask that we'll use to define a slight gradient -->
  <mask maskUnits="userSpaceOnUse" id="fade">
    <!-- Here's that slight gradient -->
    <linearGradient id="gradient" x1="0" y1="0" x2="0" y2="100%">
      <stop offset ="0" style="stop-color: #FFFFFF" />
      <stop offset ="1" style="stop-color: #000000" />
    </linearGradient>
    <!-- The canvas for our mask -->
    <rect fill="url(#gradient)" width="100%" height="100%" />
  </mask>
    
  <!-- Let's define the pattern -->
  <!-- The width and height should be double the circle radius we plan to use -->
  <pattern id="pattern-circles" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse">
    <!-- Now let's draw the circle -->
    <!-- We're going to define the `fill` in the CSS for flexible use -->
    <circle mask="url(#fade)" cx="20" cy="20" r="20" />
  </pattern>
  <!-- The canvas with our applied pattern -->
  <rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-circles)" />
  
</svg>

// create svg element:
var svg = d3.select("#circle").append("svg").attr("width", 200).attr("height", 200)

// Add the path using this helper function
svg.append('circle')
  .attr('cx', 100)
  .attr('cy', 100)
  .attr('r', 50)
  .attr('stroke', 'black')
  .attr('fill', '#69a3b2');
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>

<div id="circle"></div>


仅限正方形

enter image description here

https://codepen.io/geoffgraham/pen/KmgxxN——只是标记

// create svg element:
var svg = d3.select("#rect").append("svg").attr("width", 800).attr("height", 200)

// Add the path using this helper function
svg.append('rect')
  .attr('x', 10)
  .attr('y', 120)
  .attr('width', 40)
  .attr('height', 40)
  .attr('stroke', 'black')
  .attr('fill', '#69a3b2');
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>


<div id="rect"></div>


仅限蜂窝

enter image description here

https://codepen.io/geoffgraham/pen/oWLLvZ——只是标记


仅限立方体

enter image description here

https://codepen.io/geoffgraham/pen/YVWqxG——只是标记


摆动线

enter image description here

https://codepen.io/geoffgraham/pen/xdOVjG——只是标记


打点器

enter image description here

https://codepen.io/chriscoyier/pen/MYmbwv

© www.soinside.com 2019 - 2024. All rights reserved.