我知道有一些关于此的问题/教程,但不知怎的,我的设置有点不同而且我被卡住了。 我想动态添加和删除d3(version4)多线图中的线条。我非常接近添加/删除工作,但删除/添加了错误的行。 这是有缺陷/工作的例子。
谢谢,Hannes
(function($, d3) {
const ATTR_DATA_ITEM = 'data-lmn-data-item';
const ATTR_DATA_ITEM_CODE = 'data-lmn-data-item-code';
const ATTR_DATA_ITEM_NAME = 'data-lmn-data-item-name';
const ATTR_DATA_ITEM_UNIT = 'data-lmn-data-item-unit';
const ATTR_DATA_ITEM_MIN = 'data-lmn-data-item-min';
const ATTR_DATA_ITEM_MAX = 'data-lmn-data-item-max';
const ATTR_DATA_ITEM_SELECT = 'data-lmn-data-item-select';
const ATTR_DATA_ENTRY = 'data-lmn-data-entry';
const ATTR_DATA_ENTRY_DATETIME = 'data-lmn-data-entry-datetime';
const ATTR_DATA_ENTRY_ITEM = 'data-lmn-data-entry-item';
const ATTR_DATA_PERIOD = 'data-lmn-data-period';
$(document)
.on('change', 'input[' + ATTR_DATA_ITEM_SELECT + ']', redrawGraph);
// create data object from data table
var data = {
'config': {
'period': getTimeFormatFromPeriod()
},
'items': {},
'entries': {}
};
$('[' + ATTR_DATA_ITEM + ']').each(function() {
var code = $(this).attr(ATTR_DATA_ITEM_CODE);
data.items[code] = {
'code': code,
'name': $(this).attr(ATTR_DATA_ITEM_NAME),
'unit': $(this).attr(ATTR_DATA_ITEM_UNIT),
'min': $(this).attr(ATTR_DATA_ITEM_MIN),
'max': $(this).attr(ATTR_DATA_ITEM_MAX),
};
data.entries[code] = {};
});
$('[' + ATTR_DATA_ENTRY + ']').each(function () {
var datetime = $(this).find('[' + ATTR_DATA_ENTRY_DATETIME + ']').attr(ATTR_DATA_ENTRY_DATETIME);
$(this).find('[' + ATTR_DATA_ENTRY_ITEM + ']').each(function() {
var code = $(this).attr(ATTR_DATA_ENTRY_ITEM);
data.entries[code][datetime] = parseFloat($(this).text());
});
});
//console.log(data);
var selector = '#chart',
canvas = d3.select(selector),
margin = {top: 20, right: 50, bottom: 30, left: 30},
width = $(selector).width() - margin.left - margin.right,
height = $(selector).height() - margin.top - margin.bottom,
g = canvas.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var parseTime = d3.timeParse('%Y%m%d%H');
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var line = d3.line()
.x(function(d) { return x(parseTime(d.key)); })
.y(function(d) { return y(d.value); });
// draw x-axis
g.append('g')
.attr('class', 'axis axis--x')
.attr('transform', 'translate(0,' + height + ')');
// draw y-axis
g.append('g')
.attr('class', 'axis axis--y');
$('[' + ATTR_DATA_ITEM_SELECT + ']').each(function () {
$(this).closest('label').css({
'background-color': z($(this).attr(ATTR_DATA_ITEM_SELECT))
})
})
// redraw graph from data object
function redrawGraph() {
// select only activated items
var entries = d3
.entries(data.entries)
.filter(function (entry) {
// filter all items not selected
return $('[' + ATTR_DATA_ITEM_SELECT + '="' + entry.key + '"]').prop('checked');
});
var items = d3
.entries(data.items)
.filter(function (item) {
// filter all items not selected
return $('[' + ATTR_DATA_ITEM_SELECT + '="' + item.key + '"]').prop('checked');
});
// calculate ranges
var minX = d3.min(entries, function (es) {
var entry = d3.entries(es.value);
return d3.min(entry, function (e) {
return parseTime(e.key);
})
});
var maxX = d3.max(entries, function (es) {
var entry = d3.entries(es.value);
return d3.max(entry, function (e) {
return parseTime(e.key);
})
});
var minY = d3.min(items, function (i) {
return i.value.min;
});
var maxY = d3.max(items, function (i) {
return i.value.max;
});
x.domain([minX, maxX]);
y.domain([minY, maxY]);
z.domain(entries, function(e) { return e.key; });
// redraw y-axes
g.selectAll('g.axis--y')
.call(d3.axisLeft(y));
// redraw x-axis
g.selectAll('g.axis--x')
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat(getTimeFormatFromPeriod()))
);
// redraw lines
var gline = g.selectAll('.gline')
.data(entries);
gline.exit().remove();
gline
.enter().append('g')
.attr('class', 'gline')
.append('path')
.attr('class', 'line')
.attr('d', function (d) {
var entry = d3.entries(d.value);
return line(entry);
})
.style('stroke', function(d) {
return z(d.key);
})
;
}
function getTimeFormatFromPeriod() {
var period = $('[' + ATTR_DATA_PERIOD + ']').attr(ATTR_DATA_PERIOD);
var timeFormat;
switch(true) {
case (period === '1h' || period === '8hg' || period === '24hg'):
timeFormat = '%d.%m %H:00';
break;
case (period === '24h'):
timeFormat = '%y.%m.%d';
break;
case (period === '1m'):
timeFormat = '%y.%m';
break;
case (period === '1y' || period === '1yAOT40' || period === '5yAOT40'):
timeFormat = '%Y';
break;
}
return timeFormat;
}
// draw initial graph
redrawGraph();
})(jQuery, d3);
@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:local('Open Sans Light'),local('OpenSans-Light'),url(https://fonts.gstatic.com/s/opensans/v13/DXI1ORHCpsQm3Vp6mXoaTYnF5uFdDttMLvmWuJdhhgs.ttf) format('truetype')}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local('Open Sans'),local('OpenSans'),url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf) format('truetype')}@font-face{font-family:icomoon;src:url(../fonts/icomoon.eot?dablr5);src:url(../fonts/icomoon.eot?dablr5#iefix) format("embedded-opentype"),url(../fonts/icomoon.ttf?dablr5) format("truetype"),url(../fonts/icomoon.woff?dablr5) format("woff"),url(../fonts/icomoon.svg?dablr5#icomoon) format("svg");font-weight:400;font-style:normal}.lmn-body{margin:0;font-family:"Open Sans","Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-size:.9rem;line-height:1;color:#222}.lmn-body b,.lmn-body button,.lmn-body h1,.lmn-body h2,.lmn-body h3,.lmn-body h4,.lmn-body h5,.lmn-body h6,.lmn-body input,.lmn-body select,.lmn-body strong,.lmn-body td,.lmn-body textarea,.lmn-body th{font-family:inherit;font-size:inherit;line-height:inherit;font-weight:inherit}.lmn-body th{text-align:left}.lmn-body dd,.lmn-body dl,.lmn-body dt,.lmn-body fieldset,.lmn-body figure,.lmn-body h1,.lmn-body h2,.lmn-body h3,.lmn-body h4,.lmn-body h5,.lmn-body h6,.lmn-body input,.lmn-body ol,.lmn-body p,.lmn-body ul{margin:0;padding:0}.lmn-body fieldset,.lmn-body iframe{border:none}.lmn-body ol,.lmn-body ul{list-style-type:none}.lmn-body a,.lmn-body a:active,.lmn-body a:focus,.lmn-body a:hover{color:inherit;text-decoration:none}.lmn-body .lmn-headline,.lmn-content{text-rendering:optimizeLegibility;color:#222}.lmn-body img{max-width:100%}.lmn-body img:not([height]){height:auto}.lmn-body hr{border:none;border-top:1px solid #f1f5fa;margin:.3rem 0}.lmn-content{margin:0;padding:0;font-family:"Open Sans","Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-size:.9rem;font-weight:300;line-height:1;background-color:#fff;max-width:960px}.lmn-body .lmn-alignright{text-align:right}.lmn-body .lmn-bg--gray{background-color:#f1f5fa}.lmn-body .lmn-icon{font-family:icomoon!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;font-size:30px;vertical-align:sub;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.lmn-body .lmn-icon--archive:before{content:"\e149"}.lmn-body .lmn-icon--arrow_back:before{content:"\e5c4"}.lmn-body .lmn-icon--arrow_forward:before{content:"\e5c8"}.lmn-body .lmn-icon--send:before{content:"\e163"}.lmn-body .lmn-headline{font-family:"Open Sans","Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-size:.9rem;font-weight:300;margin-top:.2rem;margin-bottom:.5rem;line-height:1.4}.lmn-body .lmn-headline--h1{font-size:26px;margin-bottom:1.6rem}.lmn-body .lmn-headline--h3{font-size:.9rem;text-transform:uppercase}.lmn-body .lmn-bold{font-weight:700}.lmn-body a{color:#2ba6cb;font-weight:400;text-decoration:none;-webkit-transition:all .3s;transition:all .3s}.lmn-body a:hover{text-decoration:underline;cursor:pointer}.lmn-body small{color:#6a7e95;font-size:14px}.lmn-body .lmn-alert{border-radius:5px;border-width:1px;border-style:solid;background-color:#E1F5FE;color:#03A9F4;border-color:#03A9F4;padding:16px 14px;padding:16px 14px;padding:16px 14px}.lmn-body .lmn-alert--error{color:#D32F2F;background-color:#FFEBEE;border-color:#F44336}.lmn-body .lmn-alert--warning{background-color:#FFF8E1;color:#FF8F00;border-color:#FFC107}.lmn-body .lmn-alert--done{background-color:#E8F5E9;color:#388E3C;border-color:#4CAF50}.lmn-body .lmn-button{text-align:center;text-decoration:none!important;padding:.5rem 1.5rem;display:inline-block;cursor:pointer;-webkit-transition:all .3s;transition:all .3s;background-color:transparent;color:#2ba6cb;border:1px solid #2ba6cb;line-height:30px}.lmn-body .lmn-button:hover{color:#fff;background-color:#2ba6cb;text-decoration:none}.lmn-body .lmn-button--small{font-size:14px!important;line-height:20px!important;padding:.7rem 1.4rem}.lmn-body .lmn-button--full{color:#fff;background-color:#2ba6cb;border:0}.lmn-body .lmn-input--select,.lmn-body .lmn-input--text{font-family:"Open Sans","Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-size:.9rem;font-weight:300;text-rendering:optimizeLegibility;display:inline-block;width:100%;color:#526475;height:40px}.lmn-body .lmn-button--full:hover{opacity:.8}.lmn-body .lmn-input--text{-webkit-transition:all .3s;transition:all .3s;padding:10px;margin:0;border:1px solid #d1e1e8;border-radius:0;outline:0;box-sizing:border-box;line-height:40px}.lmn-body .lmn-input--text:focus{border:1px solid #2ba6cb}.lmn-body .lmn-input--select{line-height:1;-webkit-transition:all .3s;transition:all .3s;padding:6px 10px 10px;margin:0;border:1px solid #d1e1e8;border-radius:0;outline:0;box-sizing:border-box;background-color:#fff}.lmn-body .lmn-input--textarea,.lmn-body .lmn-input[disabled]{font-family:"Open Sans","Helvetica Neue",Helvetica,Helvetica,Arial,sans-serif;font-size:.9rem;font-weight:300;line-height:1;text-rendering:optimizeLegibility;display:inline-block;color:#526475;padding:10px;margin:0;outline:0;box-sizing:border-box;width:100%}.lmn-body .lmn-input--select:focus{border:1px solid #2ba6cb}.lmn-body .lmn-input--textarea{-webkit-transition:all .3s;transition:all .3s;border:1px solid #d1e1e8;border-radius:0;resize:vertical}.lmn-body .lmn-input--textarea:focus{border:1px solid #2ba6cb}.lmn-body .lmn-input[disabled]{-webkit-transition:all .3s;transition:all .3s;border:1px solid #d1e1e8;border-radius:0;cursor:not-allowed;background-color:#d1e1e8;height:40px}.lmn-body .lmn-input[disabled]:focus{border:1px solid #2ba6cb}.lmn-body .lmn-label{font-size:.8rem;margin:.3rem 0;display:block}.lmn-body .lmn-label--uper{text-transform:uppercase}.lmn-body .lmn-grid{display:block;width:100%;max-width:960px;margin:auto}@media (max-width:960px){.lmn-body .lmn-grid{width:94%}}.lmn-body .lmn-row{display:block;width:100%;margin-bottom:.3rem}.lmn-body .lmn-row:after{content:" ";clear:both;display:table;line-height:0}.lmn-body .lmn-col--1,.lmn-body .lmn-col--10,.lmn-body .lmn-col--11,.lmn-body .lmn-col--12,.lmn-body .lmn-col--2,.lmn-body .lmn-col--3,.lmn-body .lmn-col--4,.lmn-body .lmn-col--5,.lmn-body .lmn-col--7,.lmn-body .lmn-col--8,.lmn-body .lmn-col--9{display:inline-block;vertical-align:top;float:left;padding:1%}.lmn-body .lmn-row--mediumMargin{margin-bottom:.8rem}.lmn-body .lmn-col--1{width:6.33%}.lmn-body .lmn-col--2{width:14.66%}.lmn-body .lmn-col--3{width:22.99%}.lmn-body .lmn-col--4{width:31.33%}.lmn-body .lmn-col--5{width:39.66%}.lmn-body .lmn-col--6{width:47.99%;display:inline-block;vertical-align:top;float:left;padding:1%}.lmn-body .lmn-col--7{width:56.33%}.lmn-body .lmn-col--8{width:64.66%}.lmn-body .lmn-col--9{width:72.99%}.lmn-body .lmn-col--10{width:81.33%}.lmn-body .lmn-col--11{width:89.66%}.lmn-body .lmn-col--12{width:97.99%}@media (max-width:400px){.lmn-body .lmn-col-1,.lmn-body .lmn-col-10,.lmn-body .lmn-col-11,.lmn-body .lmn-col-12,.lmn-body .lmn-col-2,.lmn-body .lmn-col-3,.lmn-body .lmn-col-4,.lmn-body .lmn-col-5,.lmn-body .lmn-col-6,.lmn-body .lmn-col-7,.lmn-body .lmn-col-8,.lmn-body .lmn-col-9{width:98%}}.lmn-body .lmn-table{display:table;width:100%;border-width:0;border-collapse:collapse}.lmn-body .lmn-table--data .lmn-table__hcell{font-size:.8em;padding:8px;background-color:#8bcae3}.lmn-body .lmn-table--data .lmn-table__row:nth-child(even){background-color:#f1f5fa}.lmn-body .lmn-table--data .lmn-table__cell{padding:4px 8px;border-bottom:1px solid #d1e1e8}.lmn-body .lmn-list--vertical__item{line-height:1.3rem}.lmn-body #chart{width:100%;height:500px;font:10px sans-serif}.lmn-body #chart path{fill:none}.lmn-body #chart .axis line,.lmn-body #chart .axis path{fill:none;stroke:#000;shape-rendering:crispEdges}.lmn-body #chart .element text{text-anchor:end}.lmn-body #chart .area{opacity:.7}.lmn-body .lmn-map{width:100%;height:400px}
/*# sourceMappingURL=main.css.map */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.js"></script>
<div class="lmn-body lmn-content">
<div class="lmn-row">
<div class="lmn-col--9 lmn-bg lmn-bg--gray">
<svg id="chart"></svg>
</div>
<div class="lmn-col--3">
<div class="lmn-headline lmn-headline--h3">Messkomponenten</div>
<ul class="lmn-list lmn-list--vertical">
<li class=" lmn-list--vertical__item">
<label class="lmn-label" style="background-color: rgb(31, 119, 180);">
<input type="checkbox" data-lmn-data-item-select="so2_1h" checked="checked">
SO₂ (µg/m³)
</label>
</li>
<li class=" lmn-list--vertical__item">
<label class="lmn-label" style="background-color: rgb(255, 127, 14);">
<input type="checkbox" data-lmn-data-item-select="no_1h" checked="checked">
NO (µg/m³)
</label>
</li>
<li class=" lmn-list--vertical__item">
<label class="lmn-label" style="background-color: rgb(44, 160, 44);">
<input type="checkbox" data-lmn-data-item-select="no2_1h" checked="checked">
NO₂ (µg/m³)
</label>
</li>
</ul>
</div>
</div>
<table class="lmn-table lmn-table--data" data-lmn-data-period="1h">
<thead>
<tr class="lmn-table__hrow">
<th class="lmn-table__hcell"> </th>
<th class="lmn-table__hcell" data-lmn-data-item="" data-lmn-data-item-code="so2_1h" data-lmn-data-item-name="SO₂" data-lmn-data-item-unit="µg/m³" data-lmn-data-item-min="0" data-lmn-data-item-max="110">
SO₂
</th>
<th class="lmn-table__hcell" data-lmn-data-item="" data-lmn-data-item-code="no_1h" data-lmn-data-item-name="NO" data-lmn-data-item-unit="µg/m³" data-lmn-data-item-min="0" data-lmn-data-item-max="500">
NO
</th>
<th class="lmn-table__hcell" data-lmn-data-item="" data-lmn-data-item-code="no2_1h" data-lmn-data-item-name="NO₂" data-lmn-data-item-unit="µg/m³" data-lmn-data-item-min="0" data-lmn-data-item-max="500">
NO₂
</th>
</tr>
<tr class="lmn-table__hrow">
<th class="lmn-table__hcell">Einheit</th>
<th class="lmn-table__hcell">µg/m³</th>
<th class="lmn-table__hcell">µg/m³</th>
<th class="lmn-table__hcell">µg/m³</th>
</tr>
<tr class="lmn-table__hrow">
<th class="lmn-table__hcell">Messzeit</th>
<th class="lmn-table__hcell">Stundenwerte</th>
<th class="lmn-table__hcell">Stundenwerte</th>
<th class="lmn-table__hcell">Stundenwerte</th>
</tr>
</thead>
<tbody>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110311">03.11.2016 11:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">6</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">114</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">58</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110310">03.11.2016 10:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">211</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">69</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110309">03.11.2016 09:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">285</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">80</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110308">03.11.2016 08:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">244</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">71</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110307">03.11.2016 07:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">156</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">57</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110306">03.11.2016 06:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">23</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">42</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110305">03.11.2016 05:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">2</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">31</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110304">03.11.2016 04:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">2</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">24</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110303">03.11.2016 03:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">2</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">20</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110302">03.11.2016 02:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">2</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">18</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110301">03.11.2016 01:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">2</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">17</td>
</tr>
<tr class="lmn-table__row" data-lmn-data-entry="">
<td class="lmn-table__cell" data-lmn-data-entry-datetime="2016110300">03.11.2016 00:00</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="so2_1h">3</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no_1h">2</td>
<td class="lmn-table__cell" data-lmn-data-entry-item="no2_1h">16</td>
</tr>
</tbody>
</table>
</div>
答案 0 :(得分:0)
如果有人有兴趣。为.data()提供自定义/常量索引解决了我的问题。
var gline = g.selectAll('.line')
.data(entries, function (d) {
return d.key;
});