Создание шкалы d3.js с элементами SVG в качестве диапазона

1

Я пытаюсь создать шкалу, которая содержит элементы svg как диапазон. Например, линейный непрерывный масштаб с диапазоном, содержащим круги с радиусом от 0 до 100 и которые также могут быть запрошены для этих кругов. Цель этого - передать масштаб разработчику легенды, который использует приятные свойства весов d3 для построения легенды.

Я могу создавать круги, которые я вижу в инспекторе страницы браузера, но они не отображаются там, где это важно. Это почему? Если append() принимает элемент dom, почему он не отображается?

let canvas = d3.select("body").append("svg")
    .attr("width", 800)
    .attr("height", 200);

let domFun = function(scale, range) {
    scale.range(range);
    return function(d) {
        let template = document.createElement("template");
        template.innerHTML = scale(d);
        let dom = template.content.childNodes[0];
        return dom;
    }
};

let cScale = domFun(d3.scaleLinear(), ["<circle r = 0>", "<circle r = 100>"]);

let data = [0.2, 0.3, 0.6, 1];

canvas.selectAll("circle").data(data).enter()
    .append(d => cScale(d))
    .attr("cy", 100)
    .attr("cx", (d, i) => (i + 0.5) * 200)
    .attr("fill", "red");

Благодарен за любую помощь/ввод здесь.

Теги:
d3.js

2 ответа

0
Лучший ответ

В то время как другой ответ является типичным подходом D3 к этой задаче, вы можете сделать эту работу с одной модификацией.

При создании элементов необходимо указать пространство имен SVG. Это может выглядеть так:

    return function(d) {
        let template = document.createElementNS(d3.namespaces.svg, "svg")
        template.innerHTML = scale(d);
        let dom = template.firstChild;
        return dom;
    }

В целом это выглядит примерно так:

let svg = d3.select("body").append("svg")
    .attr("width", 800)
    .attr("height", 200);

let domFun = function(scale, range) {
    scale.range(range);
    return function(d) {
        let template = document.createElementNS(d3.namespaces.svg, "svg")
        template.innerHTML = scale(d);
        let dom = template.firstChild;
        return dom;
    }
};

let cScale = domFun(d3.scaleLinear(), ["<circle r = 0>", "<circle r = 100>"]);

let data = [0.2, 0.3, 0.6, 1];

svg.selectAll("circle").data(data).enter()
    .append(d => cScale(d))
    .attr("cy", 100)
    .attr("cx", (d, i) => (i + 0.5) * 200)
    .attr("fill", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
0

Зачем использовать масштаб для создания некоторых тегов и использовать функцию для извлечения из другого тега?

Просто используйте масштаб, чтобы рассчитать радиус и круги видны

let canvas = d3.select("body").append("svg")
    .attr("width", 800)
    .attr("height", 200);

let cScale = d3.scaleLinear().range([0, 100]);
let data = [0.2, 0.3, 0.6, 1];

canvas.selectAll("circle").data(data).enter()
    .append("circle")
    .attr("r", d => cScale(d))
    .attr("cy", 100)
    .attr("cx", (d, i) => (i + 0.5) * 200)
    .attr("fill", "red");

редактировать

Вместо использования строкового интерполятора и построения элемента DOM это можно сделать с помощью интерполятора Object. Это позволяет также интерполировать цвета.

let canvas = d3.select("body").append("svg")
    .attr("width", 800)
    .attr("height", 200);

let icScale = d3.scaleLinear().range([{r:10, fill:"red", cx:100}, {r:100, fill:"yellow", cx:700, cy:100, shape:"circle"}]);
let data = icScale.ticks(5);

let shape = icScale(data[0]).shape;
canvas.selectAll(shape).data(data).enter()
    .append(shape)
    .attrs(d => icScale(d));

вам нужно добавить

<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

это на вашу HTML-страницу, чтобы использовать .attrs().

Только второй объект должен иметь атрибут shape, а также потому, что здесь cy не изменяется, он должен быть только во втором объекте.

Если вам нужно, чтобы объект, возвращенный шкалой, знал, что вам нужно сделать копию.

  • 0
    Спасибо за вклад! Моя (возможно, ошибочная) идея состоит в том, чтобы создать функцию, которая создает легенды (как в пояснительном руководстве цвета / размера / ориентации / символа / рисунка рядом с графиком). Поэтому мне нужно, чтобы сами объекты содержались в масштабе, чтобы можно было легко использовать функцию ticks () для создания объекта svg и значения данных. Надеюсь, что это имеет смысл. Ответ Эндрю Рейда действительно помог мне в пути.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню