Ответы, которые вы упомянули, используют D3 v3, но ситуация значительно изменилась с v3 до v4 / v5.Основное отличие, когда дело доходит до выборок, покрывается одним предложением в changelog :
Выборы больше не подклассируют Array с использованием инжекции цепочки прототипов;теперь они - простые объекты, улучшающие производительность.
Хотя это звучит довольно просто, тем не менее, потребовались значительные изменения под капотом.Все объекты выбора теперь являются экземплярами функции Selection
, которая не предоставляется напрямую.d3.selection
- это функция, возвращающая новый экземпляр Selection
:
function selection() {
return new Selection([[document.documentElement]], root);
}
Хотя оба Selection
и d3.selection
имеют один и тот же прототип , который содержит свойство .enter
, нет свойства .enter
, если не создан экземпляр, следовательно, ошибка в вашем коде.
Правильный способ расширения объектов выбора D3 в v4 / v5 будет следующим:следующие строки:
d3.selection
.prototype // This prototype is shared across all types of selections.
.appendHTML = // Apply changes to the selection's prototype.
Поскольку свойство prototype
Selection
и d3.selection
указывает на один и тот же объект, эти изменения будут влиять как на обычный, так и на выбор, поскольку оба они являются экземплярамиSelection
функция.
Как вы можете видеть, это всего лишь первая строка вашего собственного кода, и это прекрасно.Ваше расширение использует d3.selection.prototype.enter.prototype.appendHTML
только вид работ: оно не приносит ни вреда, ни пользы!Установка свойства для функции .enter
не имеет смысла, так как никогда не создается экземпляр, созданный из этой функции.
Посмотрите на следующую рабочую демонстрацию, которую я взял из сущности, с которой вы связались в своем вопросе:
d3.selection.prototype.appendHTML =
function(HTMLString) {
return this.select(function() {
return this.appendChild(
document.importNode(
new DOMParser().parseFromString(HTMLString, 'text/html').body.childNodes[0], true)
);
});
};
d3.selection.prototype.appendSVG =
function(SVGString) {
return this.select(function() {
return this.appendChild(
document.importNode(
new DOMParser()
.parseFromString('<svg xmlns="http://www.w3.org/2000/svg">' + SVGString + '</svg>', 'application/xml').documentElement.firstChild, true));
});
};
d3.select('.container').appendHTML('<svg><g><rect width="50" height="50" /></g></svg>');
var svg = d3.select('.container')
.appendHTML('<svg xmlns="http://www.w3.org/2000/svg"><g><circle class="circle1" cx="50" cy="50" r="50"></circle></g></svg>')
.select('g');
svg.appendSVG('<circle class="circle2" cx="20" cy="20" r="20"></circle>');
svg.appendSVG('<rect width="30" height="30"></rect>');
div,
svg {
border: 1px solid silver;
margin: 10px;
}
rect {
fill: skyblue;
}
.circle1 {
fill: orange;
}
.circle2 {
fill: lime;
}
<script src="https://d3js.org/d3.v5.js"></script>
<div class="container"></div>