I am completely lost trying to spawn circles with pictures inside that all move within a force.drag. They should be created based on a list of arrays. Any help is really appreciated!
This is my code so far:
var data2 = [
{id: 1, name: "Sachin", pop: 200, x: 0, y: 0, color: 'red', image: "https://picsum.photos/900" },
{id: 2, name: "Murali", pop: 100, x: 200, y: 200, color: 'green', image: "https://random.imagecdn.app/500/500" }
]
var body = d3.select("body")
var svg = body.append("svg")
.attr("width", 800)
.attr("height", 800)
data2.forEach(function(d){
svg.append("clipPath")
.attr('id', d.id)
.append('circle')
.attr("cx", d.x + d.pop /2)
.attr("cy", d.y + d.pop / 2)
.attr("r", d.pop /2)
.attr("", console.log(d))
.style("fill", "green")
.attr("", console.log("done! with this one"))
})
data2.forEach(function(d){
svg.append('image')
.attr('xlink:href',d.image)
.attr('width', d3.sum([d.pop]))
.attr('height', d3.sum([d.pop]))
.attr('x', d.x)
.attr('y', d.y)
.attr('clip-path','url(#' + d.id + ')');
});
But this only gives me this:
But I am trying to make this...
and applying force to it as shown in this snippet:
var data2 = [
{id: 1, name: "Sachin", pop: 20, color: 'red', image: "https://picsum.photos/900" },
{id: 2, name: "Murali", pop: 10, color: 'green', image: "https://random.imagecdn.app/500/500" }
]
var width = 400//Dimensions.get('window').width,
var height = 400//Dimensions.get('window').height,
// create SVG
var body = d3.select("body") //SVG ÄR HELA ARBETSYTAN
var svg = body.append("svg")
.attr("width", width)
.attr("height", height)
//.style("background", "#000000")
// init a force layout, using the nodes and edges in dataset
var force = d3.layout.force()
.nodes(data2)
//.links(data.edges)
.size([width, height])
.charge([-300]) //.linkDistance([100])
.start()
// define 10 random colors
//var colors = d3.scale.category10()*/
var drums = svg.selectAll("circle")
.data(data2)
.enter()
.append("circle")
drums.attr("cx", function(d) { return width/2 }) //för att vara olika för varje item.
.attr("cy", height/2)
.attr("r", function(d) { return d.pop })
.attr("", function(d) { console.log(d) })
.call(force.drag)
drums.style("fill", function(d) {
if (!d.image) {
return ("url(#" + d.id + ")"); //console.log(d.image)
}else{
return d.color
}
})
force.on("tick", function() {
(svg.selectAll('circle') //drums
.attr("cx", function(d) { return d.x })
.attr("cy", function(d) { return d.y })
)
})
drums.on("click", function(d) {
console.log(d)
d3.select(this)
.attr("r" , d3.sum([d3.select(this).attr("r"),10]))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.4/d3.min.js"></script>
Thank you so much for taking a look into this! :)
I am new to using d3.js. I am trying to append multiple text elements in a svg group. With that, I want to be able to drag the group of multiple text.
So for an example:
export function testNode (config = {}) {
let { svg, rectX, rectY, text1, text2 } = config
var data = [{ x: rectX, y:rectY, label: text1, label2: text2, labelX: rectX + 100, labelY: rectY + 200, labelX2: rectX + 300, labelY2: rectY + 300 }]
var group = svg.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",
"translate(" + 0 + "," + 0 + ")")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
group.append("text")
.data(data)
.attr("x", (d) => { return d.labelX })
.attr("y", (d) => { return d.labelY })
.attr("font-size", "1em")
.attr("color", "black")
.text((d) => { return d.label });
group.append("text")
.data(data)
.attr("x", (d) => { return d.labelX2 })
.attr("y", (d) => { return d.labelY2 })
.attr("font-size", ".75em")
.attr("color", "black")
.attr("class", "label")
.text((d) => { return d.metricValue_01 });
function dragStarted() {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this).select("text")
.attr("x", d.labelX = d3.event.x + 10)
.attr("y", d.labelY = d3.event.y + 20);
d3.select(this).select("text")
.attr("x", d.labelX2 = d3.event.x + 10)
.attr("y", d.labelY2 = d3.event.y + 20);
function dragended() {
d3.select(this).classed("active", false);
}
If I use the selectAll method, the text gets clumped together. Therefore, I was wondering if I can drag the text group in their proper position based on the coordinate I give it (while being dragged). Anyways please let me know if I need to provide any further information. Thank you
If you want to select the second label, but don't want to use selectAll as it selects both, you can give the labels classes when appending and select those when dragging:
d3.select(this).select(".bigLabel")
.attr("x", d.labelX = d3.event.x + 10)
.attr("y", d.labelY = d3.event.y + 20);
d3.select(this).select(".smallLabel")
.attr("x", d.labelX2 = d3.event.x + 10)
.attr("y", d.labelY2 = d3.event.y + 20);
Though of course this will set the same coordinate for both labels unless you specify an offset, as below:
var data = [
{ x: 100, x2: 100, y: 100, y2: 120, label: "label1", value: "17%" },
{ x: 300, x2: 300, y: 200, y2: 220, label: "label2", value: "83%" },
{ x: 100, x2: 100, y: 200, y2: 220, label: "label3", value: "11%" },
{ x: 300, x2: 300, y: 100, y2: 120, label: "label4", value: "96%" }
];
var svg = d3.select("svg");
var labels = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.call(d3.drag()
.on("drag",drag));
labels.append("text")
.attr("font-size", "1em")
.attr("x", function(d) { return d.x;})
.attr("y", function(d) { return d.y;})
.text(function(d) { return d.label; })
.attr("class","label1");
labels.append("text")
.attr("font-size", ".75em")
.attr("x", function(d) { return d.x2;})
.attr("y", function(d) { return d.y2;})
.text(function(d) { return d.value; })
.attr("class","label2");
function drag(d) {
var x = d3.event.x;
var y = d3.event.y;
d3.select(this)
.select(".label1")
.attr("x", function(d) { return d.x = x; })
.attr("y", function(d) { return d.y = y; })
d3.select(this)
.select(".label2")
.attr("x", function(d) { return d.x2 = x; })
.attr("y", function(d) { return d.y2 = y + 20; })
}
text {
text-anchor:middle;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="400"></svg>
I won't dive into the alternative in too much depth, but it applies the drag to the g, positioning both text labels at the same time. This can handle irregular spacing between sibling labels easier than the above:
var data = [
{ x: 100, y: 100, label: "label1", value: "17%" },
{ x: 300, y: 200, label: "label2", value: "83%" },
{ x: 100, y: 200, label: "label3", value: "11%" },
{ x: 300, y: 100, label: "label4", value: "96%" }
];
var svg = d3.select("svg");
var labels = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",function(d) {
return "translate("+[d.x,d.y]+")";
})
.call(d3.drag().on("drag", drag));
labels.append("text")
.attr("font-size", "1em")
.text(function(d) { return d.label; });
labels.append("text")
.attr("font-size", ".75em")
.text(function(d) { return d.value; })
.attr("dy", "1em")
function drag(d) {
d3.select(this)
.attr("transform","translate("+[d.x=d3.event.x,d.y=d3.event.y]+")");
}
text {
text-anchor: middle;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="400"></svg>
Also, there is no need to use append("text").data(data), this is not doing anything - your datum is already bound to the newly appended element
Lastly, you can make this work with selectAll() if you set attributes using the second parameter of any provided function when setting attributes: (d,i)=>... i is the index of the element, so if your sibling labels are regularly spaced, you can use something like:
var data = [
{ x: 100, y: 100, label: "label1", value: "17%" },
{ x: 300, y: 200, label: "label2", value: "83%" },
{ x: 100, y: 200, label: "label3", value: "11%" },
{ x: 300, y: 100, label: "label4", value: "96%" }
];
var svg = d3.select("svg");
var labels = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.call(d3.drag()
.on("drag",drag));
labels.append("text")
.attr("font-size", "1em")
.attr("x", function(d) { return d.x;})
.attr("y", function(d) { return d.y;})
.text(function(d) { return d.label; })
labels.append("text")
.attr("font-size", ".75em")
.attr("x", function(d) { return d.x;})
.attr("y", function(d) { return d.y + 20;})
.text(function(d) { return d.value; })
function drag(d) {
var x = d3.event.x;
var y = d3.event.y;
d3.select(this)
.selectAll("text")
.attr("x", function(d) { return d.x = x; })
.attr("y", function(d,i) { d.y = y;
return d.y + i * 20;
})
}
text {
text-anchor:middle;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="400"></svg>
I try to create bar chart with zoom/pan functionality using d3 js. Zooming works perfectly but when I pan the chart to the left or to the right the bars go out of beside min and max X values. What I'm doing wrong?
please check this image with issue described
Here is the fiddle: https://jsfiddle.net/Cayman/vpn8mz4g/1/
function render_chart(){
var stack = d3.layout.stack();
var dataset = {
"categories": ['2018-06-01T00:00:00.000+03:00',
'2018-06-02T00:00:00.000+03:00',
'2018-06-03T00:00:00.000+03:00',
'2018-06-04T00:00:00.000+03:00',
'2018-06-05T00:00:00.000+03:00',
'2018-06-06T00:00:00.000+03:00',
'2018-06-07T00:00:00.000+03:00',
'2018-06-08T00:00:00.000+03:00',
'2018-06-09T00:00:00.000+03:00',
'2018-06-10T00:00:00.000+03:00',
'2018-06-11T00:00:00.000+03:00',
'2018-06-12T00:00:00.000+03:00'],
"series": ["New York","Mumbai","Bengaluru"],
"colors": ["#3498db","#e74c3c","#2ecc71"],
"layers": [
[
{"y":1,"y0":20,"month":"2018-06-01T00:00:00.000+03:00"},
{"y":2,"y0":18,"month":"2018-06-02T00:00:00.000+03:00"},
{"y":5,"y0":18,"month":"2018-06-03T00:00:00.000+03:00"},
{"y":10,"y0":20,"month":"2018-06-04T00:00:00.000+03:00"},
{"y":14,"y0":23,"month":"2018-06-05T00:00:00.000+03:00"},
{"y":18,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
{"y":20,"y0":31,"month":"2018-06-07T00:00:00.000+03:00"},
{"y":20,"y0":29,"month":"2018-06-08T00:00:00.000+03:00"},
{"y":16,"y0":24,"month":"2018-06-09T00:00:00.000+03:00"},
{"y":10,"y0":19,"month":"2018-06-10T00:00:00.000+03:00"},
{"y":5,"y0":23,"month":"2018-06-11T00:00:00.000+03:00"},
{"y":3,"y0":20,"month":"2018-06-12T00:00:00.000+03:00"}
],
[
{"y":12,"y0":24,"month":"2018-06-01T00:00:00.000+03:00"},
{"y":14,"y0":25,"month":"2018-06-02T00:00:00.000+03:00"},
{"y":13,"y0":31,"month":"2018-06-03T00:00:00.000+03:00"},
{"y":16,"y0":32,"month":"2018-06-04T00:00:00.000+03:00"},
{"y":18,"y0":33,"month":"2018-06-05T00:00:00.000+03:00"},
{"y":19,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
{"y":20,"y0":27,"month":"2018-06-07T00:00:00.000+03:00"},
{"y":18,"y0":26,"month":"2018-06-08T00:00:00.000+03:00"},
{"y":20,"y0":31,"month":"2018-06-09T00:00:00.000+03:00"},
{"y":17,"y0":29,"month":"2018-06-10T00:00:00.000+03:00"},
{"y":18,"y0":26,"month":"2018-06-11T00:00:00.000+03:00"},
{"y":14,"y0":24,"month":"2018-06-12T00:00:00.000+03:00"}
],[
{"y":8,"y0":24,"month":"2018-06-01T00:00:00.000+03:00"},
{"y":14,"y0":26,"month":"2018-06-02T00:00:00.000+03:00"},
{"y":12,"y0":31,"month":"2018-06-03T00:00:00.000+03:00"},
{"y":15,"y0":33,"month":"2018-06-04T00:00:00.000+03:00"},
{"y":18,"y0":37,"month":"2018-06-05T00:00:00.000+03:00"},
{"y":16,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
{"y":17,"y0":27,"month":"2018-06-07T00:00:00.000+03:00"},
{"y":19,"y0":25,"month":"2018-06-08T00:00:00.000+03:00"},
{"y":25,"y0":30,"month":"2018-06-09T00:00:00.000+03:00"},
{"y":23,"y0":31,"month":"2018-06-10T00:00:00.000+03:00"},
{"y":11,"y0":26,"month":"2018-06-11T00:00:00.000+03:00"},
{"y":12,"y0":23,"month":"2018-06-12T00:00:00.000+03:00"}
]
]
}
dataset["categories"].forEach(function(d2) {
d = new Date(d2);
});
dataset["layers"].forEach(function(d) {
d.forEach(function(d2) {
d2.month = new Date(d2.month);
});
});
n = dataset["series"].length, // Number of Layers
m = dataset["layers"].length, // Number of Samples in 1 layer
yGroupMax = d3.max(dataset["layers"], function(layer) { return d3.max(layer, function(d) { return d.y0; }); });
yGroupMin = d3.min(dataset["layers"], function(layer) { return d3.min(layer, function(d) { return d.y; }); });
var pWidth = document.getElementById('chart1').offsetWidth;
var margin = {top: 50, right: 0, bottom: 50, left: 100},
width = pWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain([new Date(dataset["categories"][0]),new Date(dataset["categories"][11]),])
.range([0, width]);
var y = d3.scale.linear()
.domain([yGroupMin, yGroupMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(dataset["categories"].length)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([0, Infinity])
.on("zoom", zoomed);
var svg = d3.select("#chart1").append("svg")
.call(zoom)
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d,i){d.map(function(b){b.colorIndex=i;return b;});return d;})
.enter().append("rect")
.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) {
var qqq = x(d.month);
var qqq2 = x(d.month) + 30 / n * j;
return x(d.month) + 30 / n * j;
})
.attr("width", 30 / n)
.transition()
.attr("y", function(d) { return y(d.y0); })
.attr("height", function(d) { return height - y(d.y0-0)})
.attr("class","bar")
.style("fill",function(d){return dataset["colors"][d.colorIndex];})
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("text")
.attr("x", width/3)
.attr("y", 0)
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Min - Max Temperature (Month wise)");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
function zoomed() {
console.warn("zoom");
svg.select(".x.axis").call(xAxis);
console.log(d3.event.translate[0] + " " + d3.event.translate[1]);
svg.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
}
enter code here
}
You need to add a clip-path into the mix:
var svg = d3.select("#chart1").append("svg")
.call(zoom)
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// create clip-path that's the same size as drawing area
svg.append('defs')
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
svg = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer")
.attr('clip-path', 'url(#clip)'); //<-- clip drawing area
Running code:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var stack = d3.layout.stack();
var dataset = {
"categories": ['2018-06-01T00:00:00.000+03:00',
'2018-06-02T00:00:00.000+03:00',
'2018-06-03T00:00:00.000+03:00',
'2018-06-04T00:00:00.000+03:00',
'2018-06-05T00:00:00.000+03:00',
'2018-06-06T00:00:00.000+03:00',
'2018-06-07T00:00:00.000+03:00',
'2018-06-08T00:00:00.000+03:00',
'2018-06-09T00:00:00.000+03:00',
'2018-06-10T00:00:00.000+03:00',
'2018-06-11T00:00:00.000+03:00',
'2018-06-12T00:00:00.000+03:00'
],
"series": ["New York", "Mumbai", "Bengaluru"],
"colors": ["#3498db", "#e74c3c", "#2ecc71"],
"layers": [
[{
"y": 1,
"y0": 20,
"month": "2018-06-01T00:00:00.000+03:00"
},
{
"y": 2,
"y0": 18,
"month": "2018-06-02T00:00:00.000+03:00"
},
{
"y": 5,
"y0": 18,
"month": "2018-06-03T00:00:00.000+03:00"
},
{
"y": 10,
"y0": 20,
"month": "2018-06-04T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 23,
"month": "2018-06-05T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 29,
"month": "2018-06-06T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 31,
"month": "2018-06-07T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 29,
"month": "2018-06-08T00:00:00.000+03:00"
},
{
"y": 16,
"y0": 24,
"month": "2018-06-09T00:00:00.000+03:00"
},
{
"y": 10,
"y0": 19,
"month": "2018-06-10T00:00:00.000+03:00"
},
{
"y": 5,
"y0": 23,
"month": "2018-06-11T00:00:00.000+03:00"
},
{
"y": 3,
"y0": 20,
"month": "2018-06-12T00:00:00.000+03:00"
}
],
[{
"y": 12,
"y0": 24,
"month": "2018-06-01T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 25,
"month": "2018-06-02T00:00:00.000+03:00"
},
{
"y": 13,
"y0": 31,
"month": "2018-06-03T00:00:00.000+03:00"
},
{
"y": 16,
"y0": 32,
"month": "2018-06-04T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 33,
"month": "2018-06-05T00:00:00.000+03:00"
},
{
"y": 19,
"y0": 29,
"month": "2018-06-06T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 27,
"month": "2018-06-07T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 26,
"month": "2018-06-08T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 31,
"month": "2018-06-09T00:00:00.000+03:00"
},
{
"y": 17,
"y0": 29,
"month": "2018-06-10T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 26,
"month": "2018-06-11T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 24,
"month": "2018-06-12T00:00:00.000+03:00"
}
],
[{
"y": 8,
"y0": 24,
"month": "2018-06-01T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 26,
"month": "2018-06-02T00:00:00.000+03:00"
},
{
"y": 12,
"y0": 31,
"month": "2018-06-03T00:00:00.000+03:00"
},
{
"y": 15,
"y0": 33,
"month": "2018-06-04T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 37,
"month": "2018-06-05T00:00:00.000+03:00"
},
{
"y": 16,
"y0": 29,
"month": "2018-06-06T00:00:00.000+03:00"
},
{
"y": 17,
"y0": 27,
"month": "2018-06-07T00:00:00.000+03:00"
},
{
"y": 19,
"y0": 25,
"month": "2018-06-08T00:00:00.000+03:00"
},
{
"y": 25,
"y0": 30,
"month": "2018-06-09T00:00:00.000+03:00"
},
{
"y": 23,
"y0": 31,
"month": "2018-06-10T00:00:00.000+03:00"
},
{
"y": 11,
"y0": 26,
"month": "2018-06-11T00:00:00.000+03:00"
},
{
"y": 12,
"y0": 23,
"month": "2018-06-12T00:00:00.000+03:00"
}
]
]
}
var parseDate = d3.time.format("%Y-%m-%d").parse;
dataset["categories"].forEach(function(d2) {
d = new Date(d2);
});
dataset["layers"].forEach(function(d) {
d.forEach(function(d2) {
d2.month = new Date(d2.month);
});
});
n = dataset["series"].length, // Number of Layers
m = dataset["layers"].length, // Number of Samples in 1 layer
yGroupMax = d3.max(dataset["layers"], function(layer) {
return d3.max(layer, function(d) {
return d.y0;
});
});
yGroupMin = d3.min(dataset["layers"], function(layer) {
return d3.min(layer, function(d) {
return d.y;
});
});
var pWidth = document.getElementById('chart1').offsetWidth;
var margin = {
top: 50,
right: 0,
bottom: 50,
left: 100
},
width = pWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain([new Date(dataset["categories"][0]), addDays(new Date(dataset["categories"][11]), 1)])
.range([0, width]);
var y = d3.scale.linear()
.domain([yGroupMin, yGroupMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(dataset["categories"].length)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([0, Infinity])
.on("zoom", zoomed);
var svg = d3.select("#chart1").append("svg")
.call(zoom)
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append('defs')
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
svg = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer")
.attr('clip-path', 'url(#clip)');
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter().append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("x", function(d, i, j) {
var qqq = x(d.month);
var qqq2 = x(d.month) + 30 / n * j;
return x(d.month) + 30 / n * j;
})
.attr("width", 30 / n)
.transition()
.attr("y", function(d) {
return y(d.y0);
})
.attr("height", function(d) {
return height - y(d.y0 - 0)
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
})
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("text")
.attr("x", width / 3)
.attr("y", 0)
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Min - Max Temperature (Month wise)");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'month');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d) {
if (!d.month) return null;
tooltip.select('.month').html("<b>" + d.month + "</b>");
tooltip.select('.tempRange').html(d.y + "℃ to " + d.y0 + "℃");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.month) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
function zoomed() {
console.warn("zoom");
svg.select(".x.axis").call(xAxis);
console.log(d3.event.translate[0] + " " + d3.event.translate[1]);
svg.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
}
function addDays(startDate, numberOfDays) {
var returnDate = new Date(
startDate.getFullYear(),
startDate.getMonth(),
startDate.getDate() + numberOfDays,
startDate.getHours(),
startDate.getMinutes(),
startDate.getSeconds());
return returnDate;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Multi Series Span Chart (Vertical)</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div id="chart1" class="chart" style="width: 100%;"></div>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</body>
<script type="text/javascript" src="main.js"></script>
</html>
I am trying to port a d3 chart (which I found online) to v4 but for some reason only the axes are shown and nothing else. The code runs without any errors in the console of Chrome's developer tools and I have hit the wall as I am not an advanced d3 user. Any ideas are highly appreciated.
Here are two jsfiddles, in v3 and v4
https://jsfiddle.net/54mp286c/31/
https://jsfiddle.net/54mp286c/36/
and this is the d3 v4 code
var data = [{
"Cell_Num": 0,
"y": 3,
"x": 2
}, {
"Cell_Num": 1,
"y": 3,
"x": 6
}, {
"Cell_Num": 2,
"y": 7,
"x": 1
}, {
"Cell_Num": 3,
"y": 5,
"x": 5
}]
var margin = {
top: 10,
left: 50,
bottom: 30,
right: 10
},
width = 460 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var scale = {
x: d3.scaleLinear().range([0, width]).nice(),
y: d3.scaleLinear().range([height, 0]).nice()
};
var access = {
x: function(d) {
return d.x;
},
y: function(d) {
return d.y;
}
};
var value = {
x: function(d) {
return scale.x(access.x(d));
},
y: function(d) {
return scale.y(access.y(d));
}
};
var axis = {
x: d3.axisBottom(scale.x),
y: d3.axisLeft(scale.y)
};
var svg = d3.select(".chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g").attr("class", "x axis");
svg.append("g").attr("class", "y axis");
svg.call(renderPlot, data);
function renderPlot(selection, data) {
updateScales(data);
selection.select(".x.axis").call(axis.x)
.attr("transform", "translate(0," + height + ")");
selection.select(".y.axis").call(axis.y);
selection
.call(renderVoronoi, data)
.call(renderPoints, data);
}
function renderVoronoi(selection, data) {
var voronoi = d3.voronoi()
.x(value.x)
.y(value.y)
.extent([
[0, 0],
[width, height]
]);
var polygons = selection.selectAll(".voronoi")
.data(voronoi(data));
polygons.enter().append("path")
.attr("class", "voronoi")
.on("mouseenter", function(d, i) {
var datum = selection.selectAll(".point").data()[i];
selection.call(renderCrosshair, datum);
})
.on("mouseleave", function(d, i) {
selection.selectAll(".crosshair").remove();
});
polygons
.attr("d", d3.line());
polygons.exit()
.remove();
}
function renderCrosshair(selection, datum) {
var lineData = [
// vertical line
[
[value.x(datum), height],
[value.x(datum), 0]
],
// horizontal line
[
[0, value.y(datum)],
[width, value.y(datum)]
]
];
var crosshairs = selection.selectAll(".crosshair.line").data(lineData);
crosshairs.enter().append("path")
.attr("class", "crosshair line");
crosshairs
.attr("d", d3.svg.line());
crosshairs.exit()
.remove();
var labelData = [{
x: -6,
y: value.y(datum) + 4,
text: Math.round(access.y(datum)),
orient: "left"
},
{
x: value.x(datum),
y: height + 16,
text: Math.round(access.x(datum)),
orient: "bottom"
}
];
var labels = selection.selectAll(".crosshair.label").data(labelData);
labels.enter().append("text")
.attr("class", "crosshair label");
labels
.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
})
.style("text-anchor", function(d) {
return d.orient === "left" ? "end" : "middle";
})
.text(function(d) {
return d.text;
});
labels.exit().remove();
}
function renderPoints(selection, data) {
var points = selection.selectAll(".point").data(data);
points.enter().append("circle")
.attr("class", "point")
.attr("cx", value.x)
.attr("cy", value.y)
.attr("r", 0)
.style("opacity", 0);
points
.transition().duration(1000)
.attr("cx", value.x)
.attr("cy", value.y)
.attr("r", 2)
.style("opacity", 1);
points.exit()
.transition().duration(1000)
.attr("r", 0)
.style("opacity", 0)
.remove();
}
function updateScales(data) {
var extent = {
x: d3.extent(data, access.x),
y: d3.extent(data, access.y)
};
scale.x.domain([extent.x[0] - 0.5, extent.x[1] + 0.5]);
scale.y.domain([extent.y[0] - 0.5, extent.y[1] + 0.5]);
}
Many thanks!