d3.символы обрезаются областью ClipPath

Все еще в процессе повышения моей компетентности в отношении D3, я столкнулся с проблемой, когда я пытаюсь построить масштабируемую кривую в элементе SVG с полями (поэтому мне нужен прямоугольник clipPath, чтобы избежать того, чтобы график вторгался в поля при увеличении) но поля clipPath обрезают отображение d3.symbols на графике.

Это соответствующий код для сюжета

var margin = {top: 20, right: 60, bottom: 30, left: 30},
    w = 960 - margin.left - margin.right,
    h = 500 - margin.top - margin.bottom;

var svg = d3.select("body").append("svg")
                .attr("width", w + margin.left + margin.right)
            .attr("height", h + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("defs").append("clipPath")
        .attr("id", "clip")
    .append("rect")
        .attr("width", w)
        .attr("height", h);

// The curve I want to plot: y=x^2
var my_curve = d3.range(10).map(function(d) { var my_y = d * d; return { "x" : d, "y" : my_y }; });

var x_range_min = d3.min(my_curve, function(d) { return d.x; }); 
var x_range_max = d3.max(my_curve, function(d) { return d.x; });
var y_range_min = d3.min(my_curve, function(d) { return d.y; }); 
var y_range_max = d3.max(my_curve, function(d) { return d.y; });

var xScale = d3.scaleLinear().domain([x_range_min, x_range_max]).range([0, w]);
var yScale = d3.scaleLinear().domain([y_range_max, y_range_min]).range([0, h]);

var xAxis = d3.axisBottom().scale(xScale);
var yAxis = d3.axisLeft().scale(yScale);


// symbols
svg.selectAll(".my_pts").data(my_curve).enter().append("path")
    .attr("class", "my_pts")
    .attr("d", d3.symbol().type(d3.symbolTriangle).size(200))
    .attr("transform", function(d) { return "translate(" + xScale(d.x) + "," + yScale(d.y) + ")"; })
    // with this zoomed line does not enter margin area
    .attr("clip-path", "url(#clip)");

... как вы можете видеть, изображена только часть символа треугольника, я думаю, потому что путь нарисован в 0,0 и обрезан клипом до того, как перевод может быть выполнен.

Я также разместил эту скрипту https://jsfiddle.net/fabio_p/988c1sjv/, где вы можете найдите более полную версию кода с функцией кисти и масштабирования, чтобы вы могли понять, зачем нужен clipPath (если вы никогда раньше не сталкивались с проблемой полей)

У меня следующий вопрос: есть ли решение этой проблемы? Я надеялся найти способ напрямую нарисовать символ в нужном месте без необходимости последующего перевода (возможно, с помощью «настраиваемого типа символа»), но, похоже, это выходит за рамки моих текущих навыков, поскольку я не смог создать любое актуальное решение.

Любое предложение будет приветствоваться. Заранее спасибо.


person Fabio P.    schedule 05.01.2017    source источник


Ответы (1)


Создайте группу с путем клипа:

var clipping = svg.append("g")
    .attr("clip-path", "url(#clip)");

И добавьте в группу и строку, и символы:

clipping.append("path")
    .data([my_curve])
    //etc...

Вот ваша обновленная скрипта: https://jsfiddle.net/cvtvrL2q/

person Gerardo Furtado    schedule 05.01.2017
comment
Великолепно! Это решение простое и элегантное! Однако из вашего предложения кажется, что большинство моих проблем возникло из-за дизайна ‹svg›, а не из-за d3: есть ли хороший источник информации о порядке, в котором выполняются такие операции svg (обрезка областей/преобразование/и т. д.)? место? Рекомендация W3C ... данный дочерний элемент обрезается указанным путем отсечения до того, как OR'ing [...] с силуэтами других дочерних элементов не была для меня настолько очевидной, и кто знает, если я все еще недостающие подробности :-( - person Fabio P.; 06.01.2017
comment
Ну, я не лучший человек, чтобы направлять вас в этом, потому что обычно я не использую пути отсечения в своих графиках. Может быть, вы можете опубликовать эту проблему как новый вопрос, используя только тег svg, чтобы гуру SVG могли вам помочь. Но вы должны задать вопрос о реальном коде, а не просто попросить учебник или лучшие практики, иначе они закроют ваш вопрос как не по теме в считанные секунды... - person Gerardo Furtado; 06.01.2017