OverflowingTheGlass
OverflowingTheGlass

Reputation: 2434

Move d3 Slider Object to Specific Location

I have code for a slider:

var slider = d3.select('body').append('p').text('Title: ');

slider.append('label')
    .attr('for', 'threshold')
    .text('');
slider.append('input')
    .attr('type', 'range')
    .attr('min', d3.min(graph.links, function(d) {return d.value; }))
    .attr('max', d3.max(graph.links, function(d) {return d.value; }))
    .attr('value', d3.min(graph.links, function(d) {return d.value; }))
    .attr('id', 'threshold')
    .style('width', '50%')
    .style('display', 'block')
    .on('input', function () {
        var threshold = this.value;

        d3.select('label').text(threshold);

        var newData = [];
        graph.links.forEach( function (d) {
            if (d.value >= threshold) {newData.push(d); };
        });

  color.domain([d3.min(newData, function(d) {return d.value; }), d3.max(newData, function(d) {return d.value; })]).interpolator(d3.interpolateBlues);

        link = link.data(newData, function(d){ return d.value});
        link.exit().remove();
        var linkEnter = link.enter().append("path")
                      .style("stroke", function(d) { return color(d.value); })
                      .style("fill", "none")
                      .style("stroke-width", "3px");
        link = linkEnter.merge(link).style("stroke", function(d) { return color(d.value); });

        node = node.data(graph.nodes);

        simulation.nodes(graph.nodes)
    .on('tick', tick)
        simulation.force("link")
    .links(newData);

        simulation.alphaTarget(0.1).restart();

Where would I put .attr("transform", "translate(10,10)") to position the slider? I have tried seemingly everywhere. The example (https://bl.ocks.org/mbostock/6452972) uses svg.append("g") to group first, but I couldn't get that to integrate with my current code.

Upvotes: 1

Views: 702

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38231

Your slider isn't part of the svg, it comprises of non-svg elements appended to the body. Transforms such as these are for svg elements, not for non-svg html elements. You will need to update the position of your elements as you would with css.

The example you are referring to creates an svg slider by using svg elements to emulate a slider. The slider is contained within an svg g element, and therefore can be moved using .attr("transform","translate(x,y)")

You can move your slider as with any other html/non-svg element using css. I've created an example below that sets the initial position of the slider, and then updates it on sliding it (using selection.style() ):

var slider = d3.select('body')
  .append('p')
  .text('Title: ')
  .attr("class","slider");

slider.append('label')
    .attr('for', 'threshold')
    .text('');
slider.append('input')
    .attr('type', 'range')
    .attr('min', 0)
    .attr('max', 100)
    .attr('value', 50)
    .attr('id', 'threshold')
    .style('display', 'block')
    .on('input', function () {
        var threshold = this.value;
       slider.style("top",threshold+"px");

        d3.select('label').text(threshold);

})
.slider {
  position: absolute;
  left: 100px;
  top: 50px;
  width: 120px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

The alternative is to create an svg based slider and use that, using the transform method in the example.

The d3 tooltip by d3Noob is a good example of dynamic placement of html elements over svg elements. Keep in mind you need to know where the svg is relative to the page in order to set the offsets correctly.

Upvotes: 3

Related Questions