Here is a very simple demo that I wrote from scratch, so not based on your code in the fiddle, showing the main aspects of the created dataviz file.
In this demo, I use only D3, no jQuery (mixing D3 with jQuery gives me headaches):
var width = 500, height = 180, padding = 16; var svg = d3.select("#svg") .append("svg") .attr("width", width) .attr("height", height); var data = d3.range(1, 21); var xScale = d3.scaleBand() .domain(data) .range([padding * 2, width - padding]) .padding(0.2); var yScale = d3.scaleLinear() .domain([0, d3.max(data, d => d)]) .range([height - padding, padding]); var bars = svg.selectAll(".bars") .data(data) .enter() .append("rect") .attr("x", d => xScale(d)) .attr("width", xScale.bandwidth()) .attr("y", d => yScale(d)) .attr("height", d => height - padding - yScale(d)) .attr("fill", (d => d3.select("#slider").node().value == d ? "firebrick" : "teal")); var xAxis = d3.axisBottom(xScale); var yAxis = d3.axisLeft(yScale); var gX = svg.append("g") .attr("transform", "translate(0," + (height - padding) + ")") .call(xAxis); var gY = svg.append("g") .attr("transform", "translate(" + padding * 2 + ",0)") .call(yAxis); d3.select("#slider").on("input", function() { var currentValue = this.value; yScale.domain([0, currentValue * 2]) bars.attr("y", d => yScale(d)) .attr("height", d => height - padding - yScale(d)) .attr("fill", (d => currentValue == d ? "firebrick" : "teal")); gY.call(yAxis); })
#slider { width: 435px; } #sliderdiv{ padding-left: 40px; }
<script src="https://d3js.org/d3.v4.min.js"></script> <div id="svg"></div> <div id="sliderdiv"><input id="slider" type="range" min="1" max="20" step="1" value="10"/></div>
Explanation:
In this example, I use plain HTML input for the slider:
<input id="slider" type="range" min="1" max="20" step="1" value="10"/>
Then we get the changes in this slider using this function:
d3.select("#slider").on("input", function() { var currentValue = this.value; yScale.domain([0, currentValue * 2]) bars.attr("y", d => yScale(d)) .attr("height", d => height - padding - yScale(d)) .attr("fill", (d => currentValue == d ? "firebrick" : "teal")); gY.call(yAxis); })
Inside this function, we have 3 main steps. First we get the current value of the slider:
var currentValue = this.value;
And using this value, we change the scale of y:
yScale.domain([0, currentValue * 2])
Thus, the selected strip will always remain at the same height, exactly the same as in the Bostok code. Then we update the lines:
bars.attr("y", d => yScale(d)) .attr("height", d => height - padding - yScale(d)) .attr("fill", (d => currentValue == d ? "firebrick" : "teal"));
And finally, the y axis:
gY.call(yAxis);