- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个圆环图,当图例中的标签/类别被禁用时,它会重新计算每个类别的百分比和大小。我想做的是重新计算不包括残疾人类别的总数。每次用户启用或禁用图例中的类别时,我都想这样做。
代码如下:
// define data
var dataset = [
{label: "Venue", count: 16107},
{label: "Photographer", count: 2783},
{label: "Wedding/Event Planner", count: 2037},
{label: "Reception Band", count: 4156},
{label: "Reception DJ", count: 1245},
{label: "Florist/Decor", count: 2534},
{label: "Videographer", count: 1995},
{label: "Wedding Dress", count: 1564},
{label: "Groom's Attire", count: 280},
{label: "Wedding Cake", count: 582},
{label: "Ceremony Site", count: 2197},
{label: "Ceremony Musicians", count: 755},
{label: "Invitations", count: 2534},
{label: "Transportation", count: 1995},
{label: "Favors", count: 1564},
{label: "Rehearsal Dinner", count: 280},
{label: "Engagement Ring", count: 582},
{label: "Officiant", count: 2197}
];
// chart dimensions
var width = 800;
var height = 800;
// a circle chart needs a radius
var radius = Math.min(width, height) / 2;
var donutWidth = 100; // size of donut hole. not needed if doing pie chart
// legend dimensions
var legendRectSize = 25; // defines the size of the colored squares in legend
var legendSpacing = 6; // defines spacing between squares
// define color scale
var color = d3.scaleOrdinal(d3.schemeCategory20b);
// more color scales: https://bl.ocks.org/pstuffa/3393ff2711a53975040077b7453781a9
// calculate new total
var total = d3.sum(dataset, d => d.count);
// define new total section
var newTotal = d3.select('new-total-holder')
.append('span')
.attr('class', 'newTotal')
var svg = d3.select('#chart') // select element in the DOM with id 'chart'
.append('svg') // append an svg element to the element we've selected
.attr('width', width) // set the width of the svg element we just added
.attr('height', height) // set the height of the svg element we just added
.append('g') // append 'g' element to the svg element
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')'); // our reference is now to the 'g' element. centerting the 'g' element to the svg element
var arc = d3.arc()
.innerRadius(radius - donutWidth) // radius - donutWidth = size of donut hole. use 0 for pie chart
.outerRadius(radius); // size of overall chart
var pie = d3.pie() // start and end angles of the segments
.value(function(d) { return d.count; }) // how to extract the numerical data from each entry in our dataset
.sort(null); // by default, data sorts in oescending value. this will mess with our animation so we set it to null
// define tooltip
var tooltip = d3.select('#chart') // select element in the DOM with id 'chart'
.append('div') // append a div element to the element we've selected
.attr('class', 'tooltip'); // add class 'tooltip' on the divs we just selected
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'label'); // add class 'label' on the selection
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'count'); // add class 'count' on the selection
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'percent'); // add class 'percent' on the selection
// Confused? see below:
// <div id="chart">
// <div class="tooltip">
// <div class="label">
// </div>
// <div class="count">
// </div>
// <div class="percent">
// </div>
// </div>
// </div>
dataset.forEach(function(d) {
d.count = +d.count; // calculate count as we iterate through the data
d.enabled = true; // add enabled property to track which entries are checked
});
// creating the chart
var path = svg.selectAll('path') // select all path elements inside the svg. specifically the 'g' element. they don't exist yet but they will be created below
.data(pie(dataset)) //associate dataset wit he path elements we're about to create. must pass through the pie function. it magically knows how to extract values and bakes it into the pie
.enter() //creates placeholder nodes for each of the values
.append('path') // replace placeholders with path elements
.attr('d', arc) // define d attribute with arc function above
.attr('fill', function(d) { return color(d.data.label); }) // use color scale to define fill of each label in dataset
.each(function(d) { this._current - d; }); // creates a smooth animation for each track
// mouse event handlers are attached to path so they need to come after its definition
path.on('mouseover', function(d) { // when mouse enters div
var total = d3.sum(dataset.map(function(d) { // calculate the total number of tickets in the dataset
return (d.enabled) ? d.count : 0; // checking to see if the entry is enabled. if it isn't, we return 0 and cause other percentages to increase
}));
var percent = Math.round(1000 * d.data.count / total) / 10; // calculate percent
tooltip.select('.label').html(d.data.label); // set current label
tooltip.select('.count').html('$' + d.data.count); // set current count
tooltip.select('.percent').html(percent + '%'); // set percent calculated above
tooltip.style('display', 'block'); // set display
});
path.on('mouseout', function() { // when mouse leaves div
tooltip.style('display', 'none'); // hide tooltip for that element
});
path.on('mousemove', function(d) { // when mouse moves
tooltip.style('top', (d3.event.layerY + 10) + 'px') // always 10px below the cursor
.style('left', (d3.event.layerX + 10) + 'px'); // always 10px to the right of the mouse
});
// define legend
var legend = svg.selectAll('.legend') // selecting elements with class 'legend'
.data(color.domain()) // refers to an array of labels from our dataset
.enter() // creates placeholder
.append('g') // replace placeholders with g elements
.attr('class', 'legend') // each g is given a legend class
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing; // height of element is the height of the colored square plus the spacing
var offset = height * color.domain().length / 2; // vertical offset of the entire legend = height of a single element & half the total number of elements
var horz = -2 * legendRectSize; // the legend is shifted to the left to make room for the text
var vert = i * height - offset; // the top of the element is hifted up or down from the center using the offset defiend earlier and the index of the current element 'i'
return 'translate(' + horz + ',' + vert + ')'; //return translation
});
// adding colored squares to legend
legend.append('rect') // append rectangle squares to legend
.attr('width', legendRectSize) // width of rect size is defined above
.attr('height', legendRectSize) // height of rect size is defined above
.style('fill', color) // each fill is passed a color
.style('stroke', color) // each stroke is passed a color
.on('click', function(label) {
var rect = d3.select(this); // this refers to the colored squared just clicked
var enabled = true; // set enabled true to default
var totalEnabled = d3.sum(dataset.map(function(d) { // can't disable all options
return (d.enabled) ? 1 : 0; // return 1 for each enabled entry. and summing it up
}));
if (rect.attr('class') === 'disabled') { // if class is disabled
rect.attr('class', ''); // remove class disabled
} else { // else
if (totalEnabled < 2) return; // if less than two labels are flagged, exit
rect.attr('class', 'disabled'); // otherwise flag the square disabled
enabled = false; // set enabled to false
}
pie.value(function(d) {
if (d.label === label) d.enabled = enabled; // if entry label matches legend label
return (d.enabled) ? d.count : 0; // update enabled property and return count or 0 based on the entry's status
});
path = path.data(pie(dataset)); // update pie with new data
path.transition() // transition of redrawn pie
.duration(750) //
.attrTween('d', function(d) { // 'd' specifies the d attribute that we'll be animating
var interpolate = d3.interpolate(this._current, d); // this = current path element
this._current = interpolate(0); // interpolate between current value and the new value of 'd'
return function(t) {
return arc(interpolate(t));
};
});
// calculate new total
var newTotalCalc = d3.sum(dataset, d => d.count)
console.log(newTotalCalc);
// append newTotalCalc to newTotal which is defined above
newTotal.append("text")
.text(newTotalCalc);
});
// adding text to legend
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) { return d; }); // return label
body {
font-family: 'Open Sans Condensed', sans-serif;
}
.title-holder {
text-align: center;
}
.title {
font-family: 'Pacifico', cursive;
}
.font {
font-size: 20px;
}
/* legend */
.legend {
font-size: 14px;
}
rect {
cursor: pointer;
stroke-width: 2;
}
rect.disabled {
fill: transparent !important;
}
/* chart */
#chart {
height: 800px;
margin: 0 auto;
position: relative;
display: block;
width: 800px;
}
/* tooltip */
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
display: none;
font-size: 18px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 80px;
z-index: 10;
}
.footer {
padding-top: 50px;
text-align: center;
list-style-type: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>D3.js Donut Chart</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Pacifico" rel="stylesheet">
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="title-holder">
<h1 class="title">2016 Average Wedding Budget Breakdown</h1>
<p class="font">Uncheck categories to recalculate.</p>
<p class="font new-total-holder">New Total:</p>
</div>
<div id="chart"></div>
<footer>
<a href="https://xogroupinc.com/press-releases/theknot2016realweddings_costofweddingsus/?__hstc=131446032.9fd6826aa789a27bcd4899793f171195.1518035170660.1518035170660.1518035170660.1&__hssc=131446032.1.1518035170660&__hsfp=2080303699" target="_blank">Data Source</a></li>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<script src="script.js"></script> <!-- remove if no javascript -->
</body>
</html>
最佳答案
这是一种方法:
当您切换 enabled
时标志基于图例点击,新 计数 可以根据这个标志计算如下:
var newTotalCalc = d3.sum(dataset.filter(function(d) { return d.enabled;}), d => d.count)
var newTotal = d3.select('.new-total-holder')
text
新元素总数<span>
,我只是在更改文本。newTotal.text(newTotalCalc);
// define data
var dataset = [
{label: "Venue", count: 16107},
{label: "Photographer", count: 2783},
{label: "Wedding/Event Planner", count: 2037},
{label: "Reception Band", count: 4156},
{label: "Reception DJ", count: 1245},
{label: "Florist/Decor", count: 2534},
{label: "Videographer", count: 1995},
{label: "Wedding Dress", count: 1564},
{label: "Groom's Attire", count: 280},
{label: "Wedding Cake", count: 582},
{label: "Ceremony Site", count: 2197},
{label: "Ceremony Musicians", count: 755},
{label: "Invitations", count: 2534},
{label: "Transportation", count: 1995},
{label: "Favors", count: 1564},
{label: "Rehearsal Dinner", count: 280},
{label: "Engagement Ring", count: 582},
{label: "Officiant", count: 2197}
];
// chart dimensions
var width = 800;
var height = 800;
// a circle chart needs a radius
var radius = Math.min(width, height) / 2;
var donutWidth = 100; // size of donut hole. not needed if doing pie chart
// legend dimensions
var legendRectSize = 25; // defines the size of the colored squares in legend
var legendSpacing = 6; // defines spacing between squares
// define color scale
var color = d3.scaleOrdinal(d3.schemeCategory20b);
// more color scales: https://bl.ocks.org/pstuffa/3393ff2711a53975040077b7453781a9
// calculate new total
var total = d3.sum(dataset, d => d.count);
// define new total section
var newTotal = d3.select('.new-total-holder')
.append('span')
.attr('class', 'newTotal').text(total);
var svg = d3.select('#chart') // select element in the DOM with id 'chart'
.append('svg') // append an svg element to the element we've selected
.attr('width', width) // set the width of the svg element we just added
.attr('height', height) // set the height of the svg element we just added
.append('g') // append 'g' element to the svg element
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')'); // our reference is now to the 'g' element. centerting the 'g' element to the svg element
var arc = d3.arc()
.innerRadius(radius - donutWidth) // radius - donutWidth = size of donut hole. use 0 for pie chart
.outerRadius(radius); // size of overall chart
var pie = d3.pie() // start and end angles of the segments
.value(function(d) { return d.count; }) // how to extract the numerical data from each entry in our dataset
.sort(null); // by default, data sorts in oescending value. this will mess with our animation so we set it to null
// define tooltip
var tooltip = d3.select('#chart') // select element in the DOM with id 'chart'
.append('div') // append a div element to the element we've selected
.attr('class', 'tooltip'); // add class 'tooltip' on the divs we just selected
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'label'); // add class 'label' on the selection
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'count'); // add class 'count' on the selection
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'percent'); // add class 'percent' on the selection
// Confused? see below:
// <div id="chart">
// <div class="tooltip">
// <div class="label">
// </div>
// <div class="count">
// </div>
// <div class="percent">
// </div>
// </div>
// </div>
dataset.forEach(function(d) {
d.count = +d.count; // calculate count as we iterate through the data
d.enabled = true; // add enabled property to track which entries are checked
});
// creating the chart
var path = svg.selectAll('path') // select all path elements inside the svg. specifically the 'g' element. they don't exist yet but they will be created below
.data(pie(dataset)) //associate dataset wit he path elements we're about to create. must pass through the pie function. it magically knows how to extract values and bakes it into the pie
.enter() //creates placeholder nodes for each of the values
.append('path') // replace placeholders with path elements
.attr('d', arc) // define d attribute with arc function above
.attr('fill', function(d) { return color(d.data.label); }) // use color scale to define fill of each label in dataset
.each(function(d) { this._current - d; }); // creates a smooth animation for each track
// mouse event handlers are attached to path so they need to come after its definition
path.on('mouseover', function(d) { // when mouse enters div
var total = d3.sum(dataset.map(function(d) { // calculate the total number of tickets in the dataset
return (d.enabled) ? d.count : 0; // checking to see if the entry is enabled. if it isn't, we return 0 and cause other percentages to increase
}));
var percent = Math.round(1000 * d.data.count / total) / 10; // calculate percent
tooltip.select('.label').html(d.data.label); // set current label
tooltip.select('.count').html('$' + d.data.count); // set current count
tooltip.select('.percent').html(percent + '%'); // set percent calculated above
tooltip.style('display', 'block'); // set display
});
path.on('mouseout', function() { // when mouse leaves div
tooltip.style('display', 'none'); // hide tooltip for that element
});
path.on('mousemove', function(d) { // when mouse moves
tooltip.style('top', (d3.event.layerY + 10) + 'px') // always 10px below the cursor
.style('left', (d3.event.layerX + 10) + 'px'); // always 10px to the right of the mouse
});
// define legend
var legend = svg.selectAll('.legend') // selecting elements with class 'legend'
.data(color.domain()) // refers to an array of labels from our dataset
.enter() // creates placeholder
.append('g') // replace placeholders with g elements
.attr('class', 'legend') // each g is given a legend class
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing; // height of element is the height of the colored square plus the spacing
var offset = height * color.domain().length / 2; // vertical offset of the entire legend = height of a single element & half the total number of elements
var horz = -2 * legendRectSize; // the legend is shifted to the left to make room for the text
var vert = i * height - offset; // the top of the element is hifted up or down from the center using the offset defiend earlier and the index of the current element 'i'
return 'translate(' + horz + ',' + vert + ')'; //return translation
});
// adding colored squares to legend
legend.append('rect') // append rectangle squares to legend
.attr('width', legendRectSize) // width of rect size is defined above
.attr('height', legendRectSize) // height of rect size is defined above
.style('fill', color) // each fill is passed a color
.style('stroke', color) // each stroke is passed a color
.on('click', function(label) {
var rect = d3.select(this); // this refers to the colored squared just clicked
var enabled = true; // set enabled true to default
var totalEnabled = d3.sum(dataset.map(function(d) { // can't disable all options
return (d.enabled) ? 1 : 0; // return 1 for each enabled entry. and summing it up
}));
if (rect.attr('class') === 'disabled') { // if class is disabled
rect.attr('class', ''); // remove class disabled
} else { // else
if (totalEnabled < 2) return; // if less than two labels are flagged, exit
rect.attr('class', 'disabled'); // otherwise flag the square disabled
enabled = false; // set enabled to false
}
pie.value(function(d) {
if (d.label === label) d.enabled = enabled; // if entry label matches legend label
return (d.enabled) ? d.count : 0; // update enabled property and return count or 0 based on the entry's status
});
path = path.data(pie(dataset)); // update pie with new data
path.transition() // transition of redrawn pie
.duration(750) //
.attrTween('d', function(d) { // 'd' specifies the d attribute that we'll be animating
var interpolate = d3.interpolate(this._current, d); // this = current path element
this._current = interpolate(0); // interpolate between current value and the new value of 'd'
return function(t) {
return arc(interpolate(t));
};
});
// calculate new total
var newTotalCalc = d3.sum(dataset.filter(function(d) { return d.enabled;}), d => d.count)
// console.log(newTotalCalc);
// append newTotalCalc to newTotal which is defined above
newTotal.text(newTotalCalc);
});
// adding text to legend
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) { return d; }); // return label
body {
font-family: 'Open Sans Condensed', sans-serif;
}
.title-holder {
text-align: center;
}
.title {
font-family: 'Pacifico', cursive;
}
.font {
font-size: 20px;
}
/* legend */
.legend {
font-size: 14px;
}
rect {
cursor: pointer;
stroke-width: 2;
}
rect.disabled {
fill: transparent !important;
}
/* chart */
#chart {
height: 800px;
margin: 0 auto;
position: relative;
display: block;
width: 800px;
}
/* tooltip */
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
display: none;
font-size: 18px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 80px;
z-index: 10;
}
.footer {
padding-top: 50px;
text-align: center;
list-style-type: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>D3.js Donut Chart</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Pacifico" rel="stylesheet">
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="title-holder">
<h1 class="title">2016 Average Wedding Budget Breakdown</h1>
<p class="font">Uncheck categories to recalculate.</p>
<p class="font new-total-holder">New Total:</p>
</div>
<div id="chart"></div>
<footer>
<a href="https://xogroupinc.com/press-releases/theknot2016realweddings_costofweddingsus/?__hstc=131446032.9fd6826aa789a27bcd4899793f171195.1518035170660.1518035170660.1518035170660.1&__hssc=131446032.1.1518035170660&__hsfp=2080303699" target="_blank">Data Source</a></li>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<script src="script.js"></script> <!-- remove if no javascript -->
</body>
</html>
关于d3.js - 在 D3.js 圆环图中禁用类别后的新总数总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48711871/
我正在学习构建单页应用程序 (SPA) 所需的所有技术。总而言之,我想将我的应用程序实现为单独的层,其中前端仅使用 API Web 服务(json 通过 socket.io)与后端通信。前端基本上是
当我看到存储在我的数据库中的日期时。 这是 正常 。日期和时间就是这样。 但是当我运行 get 请求来获取数据时。 此格式与存储在数据库 中的格式不同。为什么会发生这种情况? 最佳答案 我认为您可以将
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在尝试使用backbone.js 实现一些代码 和 hogan.js (http://twitter.github.com/hogan.js/) Hogan.js was developed ag
我正在使用 Backbone.js、Node.js 和 Express.js 制作一个 Web 应用程序,并且想要添加用户功能(登录、注销、配置文件、显示内容与该用户相关)。我打算使用 Passpor
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我尝试在 NodeJS 中加载数据,然后将其传递给 ExpressJS 以在浏览器中呈现 d3 图表。 我知道我可以通过这种方式加载数据 - https://github.com/mbostock/q
在 node.js 中,我似乎遇到了相同的 3 个文件名来描述应用程序的主要入口点: 使用 express-generator 包时,会创建一个 app.js 文件作为生成应用的主要入口点。 通过 n
最近,我有机会观看了 john papa 关于构建单页应用程序的精彩类(class)。我会喜欢的。它涉及服务器端和客户端应用程序的方方面面。 我更喜欢客户端。在他的实现过程中,papa先生在客户端有类
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我是一个图形新手,需要帮助了解各种 javascript 2D 库的功能。 . . 我从 Pixi.js 中得到了什么,而我没有从 Konva 等基于 Canvas 的库中得到什么? 我从 Konva
我正在尝试将一些 LESS 代码(通过 ember-cli-less)构建到 CSS 文件中。 1) https://almsaeedstudio.com/ AdminLTE LESS 文件2) Bo
尝试查看 Express Passport 中所有登录用户的所有 session ,并希望能够查看当前登录的用户。最好和最快的方法是什么? 我在想也许我可以在登录时执行此操作并将用户模型数据库“在线”
我有一个 React 应用程序,但我需要在组件加载完成后运行一些客户端 js。一旦渲染函数完成并加载,运行与 DOM 交互的 js 的最佳方式是什么,例如 $('div').mixItUp() 。对
请告诉我如何使用bodyparser.raw()将文件上传到express.js服务器 客户端 // ... onFilePicked(file) { const url = 'upload/a
我正在尝试从 Grunt 迁移到 Gulp。这个项目在 Grunt 下运行得很好,所以我一定是在 Gulp 中做错了什么。 除脚本外,所有其他任务均有效。我现在厌倦了添加和注释部分。 我不断收到与意外
我正在尝试更改我的网站名称。找不到可以设置标题或应用程序名称的位置。 最佳答案 您可以在 config/ 目录中创建任何文件,例如 config/app.js 包含如下内容: module.expor
经过多年的服务器端 PHP/MySQL 开发,我正在尝试探索用于构建现代 Web 应用程序的新技术。 我正在尝试对所有 JavaScript 内容进行排序,如果我理解得很好,一个有效的解决方案可以是服
我是 Nodejs 的新手。我在 route 目录中有一个 app.js 和一个 index.js。我有一个 app.use(multer....)。我还定义了 app.post('filter-re
我正在使用 angular-seed用于构建我的应用程序的模板。最初,我将所有 JavaScript 代码放入一个文件 main.js。该文件包含我的模块声明、 Controller 、指令、过滤器和
我是一名优秀的程序员,十分优秀!