D3js-如何使可视化响应?

时间:2020-09-09 15:42:45

标签: javascript html css d3.js

注意:请原谅,我删除了各种元素,例如工具提示和字体,因此您可以在我的工作示例中找到一个简单的例子。请让我知道,除了我介绍的内容以外,您是否认为还有其他其他东西正在打破这一要求。对于所有密集用途,都有一个左侧的径向图和一个右侧的条形图。

我要实现的目标是使这些图表响应不同的浏览器窗口大小。我已经尝试将径向图上的viewBox的width和height属性编辑为0 0 800 800,在#radial-chart容器上的宽度为100%,但是当我将窗口从xL中移出时,输出太小了显示器(22英寸)显示到笔记本电脑(15英寸)上

我也尝试通过媒体查询尝试使用css zoom(0.6),但是我有一些工具提示,这些提示使我们可以通过d3.event定位来针对光标跟踪工具提示的位置,但这将其弄乱了。

由于大量资源将我指向视图框,我感到非常困惑,但是这种方法对我不起作用。

谢谢。

var h = 800
var w = 800
const arc = d3.arc();

const svg = d3
  .select("#radial-chart")
  .append("svg")
  .attr("width", w)
  .attr("height", h);


var arcData = [{
    domain: "1",
    innerRadius: 0,
    outerRadius: h / 1.75,
    startAngle: (Math.PI * -20) / 180,
    endAngle: (Math.PI * 20) / 180,
  },
  {
    domain: "2",
    innerRadius: 0,
    outerRadius: 300,
    startAngle: (Math.PI * 20) / 180,
    endAngle: (Math.PI * 60) / 180,
  },
  {
    domain: "3",
    innerRadius: 0,
    outerRadius: 280,
    startAngle: (Math.PI * 60) / 180,
    endAngle: (Math.PI * 100) / 180,
  },
  {
    domain: "4",
    innerRadius: 0,
    outerRadius: 260,
    startAngle: (Math.PI * 100) / 180,
    endAngle: (Math.PI * 140) / 180,
  },
  {
    domain: "5",
    innerRadius: 0,
    outerRadius: 240,
    startAngle: (Math.PI * 140) / 180,
    endAngle: (Math.PI * 180) / 180,
  },
  {
    domain: "6",
    innerRadius: 0,
    outerRadius: 220,
    startAngle: (Math.PI * 180) / 180,
    endAngle: (Math.PI * 220) / 180,
  },
  {
    domain: "7",
    innerRadius: 0,
    outerRadius: 200,
    startAngle: (Math.PI * 220) / 180,
    endAngle: (Math.PI * 260) / 180,
  },
  {
    domain: "8",
    innerRadius: 0,
    outerRadius: 150,
    startAngle: (Math.PI * 300) / 180,
    endAngle: (Math.PI * 340) / 180,
  },
  {
    domain: "9",
    innerRadius: 0,
    outerRadius: 100,
    startAngle: (Math.PI * 260) / 180,
    endAngle: (Math.PI * 300) / 180,
  },
];
// Order needs to be from JSON
var colorScale = d3
  .scaleOrdinal()
  .domain([
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
  ])
  .range([
    "#f7941e",
    "#233f92",
    "#14385c",
    "#007ac1",
    "#4c3b2d",
    "#94c83d",
    "#0000a0",
    "#440099",
    "#e7253d",
  ]);
const slices = arcData.map((d) => arc(d));

svg
  .selectAll("path")
  .data(slices)
  .enter()
  .append("path")
  .attr("d", (d) => d)
  .attr("id", (d, i) => "arc" + i)
  .style("fill", (d, i) => colorScale(i))
  .style("z-index", 100)
  .style("opacity", 0.5)
  .attr("class", "arc selected")
  .attr('transform', 'translate(325,550) scale(0,0)')
  .transition().transition()
  .delay(400)
  .duration(function(d, i) {
    return 70 * i
  })
  .attr('transform', 'translate(325,550) scale(1,1)')

var width = 1000

const bar1 = d3
  .select("#bar1")
  .append("svg")
  .attr("width", width)
  .attr("height", 175);

var colorScale1 = d3
  .scaleOrdinal()
  .range(["#02029D", "#223AAF", "#446FBD", "#669CCB"]);

var x = d3.scaleLinear().range([0, width]);

var y = d3.scaleLinear().rangeRound([200]);

var bar1Data = [{
    position: 1,
    label: "A",
    value: 25
  },
  {
    position: 2,
    label: "B",
    value: 25,
    value2: 0
  },
  {
    position: 3,
    label: "C",
    value: 25
  },
  {
    position: 4,
    label: "D",
    value: 22
  },
];

bar1
  .append("text")
  .attr("x", width / 2)
  .attr("y", 60)
  .attr("text-anchor", "middle")
  .style("font-family", "marsBook")
  .style("font-size", "24px")
  .style("user-select", "none")
  .text("Household Income");

//Join data to rects

const rects = bar1.selectAll("rect").data(bar1Data);

rects
  .attr("width", (d) => {
    return x(d.value);
  })
  .attr("height", 80)
  .attr("class", (d, i) => {
    return "bar" + i;
  })
  .attr("x", function(d, i) {
    // Note that I use `.map` here to take only the `.value` attribute
    // from the data and create an array of numbers. Then I pass it to `x`
    // to be transformed (could also be the other way around if you'd like,
    // so sum(bar1Data.map((e) => x(e.value)), 0, i)
    return x(
      sum(
        bar1Data.map((e) => e.value),
        0,
        i
      )
    );
  })
  .attr("y", 80);

rects
  .enter()
  .append("rect")
  .attr("width", (d) => {
    return x(d.value);
  })
  .attr("height", 80)
  .attr("x", (d, i) => {
    // Note that I use `.map` here to take only the `.value` attribute
    // from the data and create an array of numbers. Then I pass it to `x`
    // to be transformed (could also be the other way around if you'd like,
    // so sum(bar1Data.map((e) => x(e.value)), 0, i)
    return x(
      sum(
        bar1Data.map((e) => e.value),
        0,
        i
      )
    );
  })
  .attr("y", 80)
  .style("fill", (d, i) => colorScale1(i))

function sum(array, start, end) {
  var total = 0;
  for (var i = start; i < end; i++) total += array[i];
  return total;
}
html {
  font-family: Arial, Helvetica, sans-serif;
}

body {
  margin: 0;
  padding: 0;
  max-width: 100vw;
}

* {
  box-sizing: border-box;
}

header {
  width: 100%;
  top: 0;
  margin: 0;
  padding-top: 0;
  padding: 0.781vw 0;
  padding-bottom: 0;
  background-color: transparent;
}

p {
  font-family: MarsBook;
  margin: 0;
}

ul {
  display: flex;
  flex-direction: row;
  align-items: center;
  list-style: none;
  width: 90%;
  padding: 0;
  margin: 0;
  z-index: 0;
  background-color: transparent;
}

header h1 {
  color: #0000a0;
  margin-left: 2vw;
  margin-right: 0.5vw;
  font-family: marsBold;
  flex-wrap: nowrap;
  white-space: nowrap;
  font-size: 2vw;
}

header p {
  font-size: 2.5vw;
  color: #00dcfa;
}

header .subtitle {
  margin-left: 0.5vw;
  font-family: marsBold;
  font-size: 2vw;
  flex-wrap: nowrap;
  white-space: nowrap;
}

.container {
  display: flex;
  flex-direction: row;
}

#bars {
  display: flex;
  flex-direction: column;
  margin-left: 40px;
  margin-top: -10px;
}

#bars h1 {
  align-content: center;
  text-align: center;
}

.selected {
  opacity: 1!important
}

image#arc0,
image#arc1,
image#arc2,
image#arc3,
image#arc4,
image#arc5,
image#arc6,
image#arc7,
image#arc8 {
  opacity: 0.35;
  transition: opacity 0.3;
  -webkit-transition: opacity 0.3 ease;
  -moz-transition: opacity 0.3 ease;
}

image#arc0:hover,
image#arc1:hover,
image#arc2:hover,
image#arc3:hover,
image#arc4:hover,
image#arc5:hover,
image#arc6:hover,
image#arc7:hover,
image#arc8:hover {
  opacity: 1
}

rect {
  transition: width 0.5s, x 0.5s, height 0.5s, y 0.5s ease;
  -webkit-transition: x 0.5s, width 0.5s, height 0.5s, y 0.5s ease;
  -moz-transition: width 0.5s, x 0.5s, height 0.5s, y 0.5s ease;
}

image,
path {
  transition: opacity 0.5s ease;
  -webkit-transition: opacity 0.5s ease;
  -moz-transition: opacity 0.5s ease;
}

#radial-chart {
  margin-top: -4vh;
  margin-bottom: -8vh;
  align-content: center;
  align-items: center;
  text-align: center;
}

#bars {
  margin-top: -4vh;
  margin-bottom: -8vh;
}

.tooltip {
  background: rgba(245, 245, 245, 0.925);
  opacity: 0;
  color: rgba(60, 60, 60, 0.925);
  border-radius: 5px;
  padding: 5px 10px;
  width: 180px;
  pointer-events: none;
  position: absolute;
  font-size: 18px;
}

#bar1,
#bar2,
#bar3,
#bar4 {
  position: relative;
}

.tooltipb1,
.tooltipb2,
.tooltipb3,
.tooltipb4 {
  flex-direction: column;
  cursor: pointer;
  position: absolute;
  border-radius: 50%;
  background: rgb(164, 164, 164);
  background: linear-gradient(150deg, rgba(255, 255, 255, 1) 0%, #B7DFF1 25%, #70C1E3 50%, #7E9CD7 75%, #8787CF 100%);
  width: 30px;
  height: 30px;
  justify-content: center;
  align-content: center;
  text-align: center;
  color: #3c3c3c;
  font-family: marsBold;
  font-size: 20px;
  z-index: 3;
  position: absolute;
  display: flex;
  top: 28px;
  right: 35px;
  margin-top: 0vh
}

.tooltipb3 {
  top: 48px;
}

.hovered {
  border: 2px solid #0000a0;
}

.tooltipb2.hovered {
  border: 2px solid cyan;
}

.tooltipb3.hovered {
  border: 2px solid goldenrod;
}

.tooltipb4.hovered {
  border: 2px solid red
}

.tooltipb1 span,
.tooltipb2 span,
.tooltipb3 span,
.tooltipb4 span {
  margin: auto;
  margin-top: 9px;
}

.desc-container1,
.desc-container2,
.desc-container3,
.desc-container4 {
  font-size: 14px;
  display: flex;
  align-items: center;
  position: absolute;
  border-radius: 0.718vw;
  background-color: whitesmoke;
  right: 80px;
  top: 0px;
  width: 240px;
  z-index: 0;
  flex-direction: column;
  justify-content: center;
  padding: 10px;
  opacity: 0;
  visibility: hidden;
  transition: visibility 0.25s, opacity 0.25s linear;
  -webkit-transition: visibility 0.25s, opacity 0.25s linear;
  -moz-transition: visibility 0.25s, opacity 0.25s linear;
  user-select: none;
}

.desc-container2 {}

.desc-container3 {
  top: 20px;
}

.desc-container4 {
  top: 0px;
  width: 240px;
}

.show {
  opacity: 0.95;
  visibility: visible;
  transition: visibility 0.25s, opacity 0.25s linear;
  -webkit-transition: visibility 0.25s, opacity 0.25s linear;
  -moz-transition: visibility 0.25s, opacity 0.25s linear;
}

.content {
  color: #3c3c3c
}

.svg-container {
  display: inline-block;
  position: relative;
  width: 100%;
  padding-bottom: 100%;
  /* aspect ratio */
  vertical-align: top;
  overflow: hidden;
}

.svg-content-responsive {
  display: inline-block;
  position: absolute;
  top: 10px;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="container">
  <div id="radial-chart"></div>
  <div id="bars">
    <div id="bar1"></div>

  </div>
</div>

1 个答案:

答案 0 :(得分:0)

我能够用一些简单的CSS来解决无响应性。

    @media screen and (max-width: 1280px) {
#radial-chart {
    zoom: 0.6
}
#bars {
    margin-left: 120px;
    zoom: 0.6
}

.footer {
    padding-top: 1vh!important;
}

.tooltip {
    font-size: 14px;
}
}

我使用过缩放功能来对div进行重做,并在不影响身体的情况下使所有项目变小。

相关问题