2017-01-05 5 views
1

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

Это соответствующий код участка

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 и срезанные clipPath до перевода может быть выполнена.

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

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

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

ответ

1

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

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

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

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

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

+0

Brilliant! Это простое и элегантное решение! От вашего предложения, однако, похоже, что большинство моих «проблем» возникло из дизайна больше, чем от d3: есть ли хороший источник информации о заказе, в котором этот вид svg-операций (отсечение областей/преобразование/и т. Д.).) происходит? Рекомендация W3C «... данный дочерний элемент обрезается ссылочной обтравочной дорожкой до того, как OR'ing [...] с силуэтами других дочерних элементов« не был так понятен мне и кто знает, если я 'm все еще не хватает дальнейших подробностей :-( –

+0

Ну, я не лучший человек, который поможет вам в этом, потому что я обычно не использую клипы в своих графиках. Возможно, вы можете опубликовать эту проблему в качестве нового вопроса, используя " svg ", так что гуру SVG могут вам помочь. Но вы должны задать вопрос о реальном коде, а не просто« просить учебник или лучшие практики », иначе они закроют ваш вопрос как неактивный в считанные секунды. .. –

Смежные вопросы