Trying to convert Stacked BarPlot from D3 to Aframe - javascript

As the title suggests, I am trying to convert a Stacked BarPlot from D3 (version 4) to Aframe (using the AR.js library).
The D3 example I am using can be found here:
https://www.d3-graph-gallery.com/graph/barplot_stacked_basicWide.html
When I run the code in the browser, I can see 4 boxes (squares), stacked on top of the other corresponding boxes, however in a weird, layered fashion. I believe this is due to my 'scale' and 'position' attributes which are incorrectly reading in the data and rendering like they should. Or perhaps it's how I appended the "a-entity" and then "a-box" to my "a-scene". Or perhaps it's neither / both (?)
Here is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src='https://aframe.io/releases/0.9.2/aframe.min.js'></script>
<script src="https://raw.githack.com/jeromeetienne/AR.js/master/aframe/build/aframe-
ar.min.js"></script>
<script src="https://raw.githack.com/donmccurdy/aframe-extras/master/dist/aframe-
extras.loaders.min.js"></script>
<script>
THREEx.ArToolkitContext.baseURL =
'https://raw.githack.com/jeromeetienne/ar.js/master/three.js/'
</script>
<script src="https://unpkg.com/aframe-animation-component#3.2.5/dist/aframe-
animation-component.min.js"></script>
<script src="https://unpkg.com/aframe-randomizer-components#3.0.2/dist/aframe-
randomizer-components.min.js"></script>
<script src="https://unpkg.com/aframe-entity-generator-component#3.0.1/dist/aframe-
entity-generator-component.min.js"></script>
<script src="https://rawgit.com/mayognaise/aframe-mouse-cursor-
component/master/dist/aframe-mouse-cursor-component.min.js"></script>
</head>
<body style="margin : 0px; overflow: hidden;">
<div id="data_by_age"></div>
<a-scene vr-mode-ui="enabled: false" embedded arjs='sourceType: webcam;
sourceWidth:1280; sourceHeight:960; displayWidth: 1280; displayHeight: 960;
debugUIEnabled: false;'>
<a-entity gps-entity-place="longitude: -73.766327; latitude: 41.032730;">
<a-cursor fuse="true" color="yellow"></a-cursor>
</a-entity>
<a-camera gps-camera rotation-reader></a-camera>
</a-scene>
<script type="text/javascript">
byAge();
function byAge() {
var scene = d3.select("a-scene");
d3.csv("../static/sample.csv", function(data) {
var subgroups = data.columns.slice(1)
var groups = d3.map(data, function(d){return(d.group)}).keys()
var color = d3.scaleOrdinal()
.domain(subgroups)
.range(['#011f4b','#03396c','#005b96', '#6497b1', '#b3cde0'])
var stackedData = d3.stack()
.keys(subgroups)
(data)
var data_scle = [];
var data_pos = [];
scene
.append("a-entity")
.selectAll("a-entity")
.data(stackedData)
.enter()
.append('a-entity')
.attr("fill", function(d) { return color(d.key); })
.selectAll("a-box")
.data(function(d) { return d; })
.enter().append("a-box")
.attr('rotation', '0 180 0')
.attr('scale', function (d,i) {
return d + " " + d + " " + d;
})
// .attr('scale', function (d,i) {
// var x = i * 10;
// var y = d;
// var z = d;
// data_scle[i] = {"x": x, "y": y, "z": z};
// return x+" "+y+" "+z;
// })
.attr('position', function(d,i) {
var x = i * 175;
// var y = 0;
var y = d;
var z = -500;
data_pos[i] = {"x": x, "y": y, "z": z};
return x+" "+y+" "+z;
})
})
};
</script>
</body>
</html>
Here is my csv file:
group, stronglyAgree, somewhatAgree, stronglyDisagree, notSureNoOpinion
eighteen, 21, 22, 11, 18, 28
thirtyfive, 33, 29, 11, 5, 22
fortyfive, 36, 23, 9, 8, 24
sixtyfive, 42, 24, 7, 10, 17
I've also seen github repos tailored specifically for making stacked bar chart components in Aframe, however I couldn't seem to get it to work properly.
https://github.com/fran-aguilar/a-framedc/tree/master/src/components/barchartstack
Any help would be immensely appreciated.

Related

D3 axisBottom scale domain issue when resizing after transform

I am trying to create a simple plot that is zoomable, pannable, and dynamically resizes with the window. In this case I only want it be to zoomable and pannable on the x axis. I'm using d3 v4.
The main issue I have run into is that the domain of the bottom axis will shift/slide when the page is being resized after the plot has been transformed. On resizing without having first transformed the plot, the bottom axis behaves as desired and maintains its domain, just "compressing" and "expanding" on resize.
To see the desired behavior, you can resize the plot without first transforming the plot by zooming or panning, and you'll see that the bottom axis maintains its domain.
To see the undesirable behavior, you can pan or zoom the plot and then resize the page. You will notice that the domain of the bottom axis will slide/shift.
I suspect there is something I'm doing wrong with setting my scales, however I am quite stuck.
The snippet below is a minimum working example of what I am working with:
window.addEventListener("resize", redraw);
let parentRect = $("#i3061007142472").parent()[0].getBoundingClientRect();
let pWidth = parentRect.width;
let pHeight = parentRect.height;
var margin = {
'top': 10,
'right': 30,
'bottom': 30,
'left': 60
},
width = pWidth - margin.left - margin.right,
height = pHeight - margin.top - margin.bottom;
var svg = d3.select("#i3061007142472")
.attr("width", width)
.attr("height", height + 20);
var zoom = d3.zoom();
zoom.on("zoom", zoom_handler_dataplot);
d3.select("#i3061007142472").call(zoom);
var x_i3061007142472 = d3.scaleTime()
.domain([new Date('0'), new Date('10')])
.range([60, width]);
x_i3061007142472.type = "time";
var svg_gX = svg.append("g")
.attr("class", "xAxis dataplot")
.attr("transform", `translate(0, ${height})`)
svg_gX.call(d3.axisBottom(x_i3061007142472).ticks(5));
var y_i3061007142472 = d3.scaleLinear()
.domain([0, 10])
.range([height, 0]);
y_i3061007142472.type = "linear";
let vd_xaxis_i3061007142472 = x_i3061007142472.copy();
let vd_yaxis_i3061007142472 = y_i3061007142472.copy();
var svg_gY = svg.append("g")
.attr("class", "yAxis dataplot")
.style("padding-left", "50px")
.attr("transform", "translate(" + 60 + ", 0)")
.call(d3.axisLeft(y_i3061007142472).ticks(5));
allow_pan_dir = "x";
domain = x_i3061007142472.domain();
function zoom_handler_dataplot() {
if (allow_pan_dir != "none") {
if (allow_pan_dir == "x" || allow_pan_dir == "both") {
vd_xaxis_i3061007142472 = d3.event.transform.rescaleX(x_i3061007142472);
domain = vd_xaxis_i3061007142472.domain()
svg_gX.call(d3.axisBottom(vd_xaxis_i3061007142472));
} else {
vd_xaxis_i3061007142472 = x_i3061007142472;
}
if (allow_pan_dir == "y" || allow_pan_dir == "both") {
vd_yaxis_i3061007142472 = d3.event.transform.rescaleY(y_i3061007142472);
svg_gY.call(d3.axisLeft(vd_yaxis_i3061007142472));
} else {
vd_yaxis_i3061007142472 = y_i3061007142472;
}
}
}
function redraw() {
console.warn("calling redraw");
console.warn(allow_pan_dir);
chartWidth = parseInt(d3.select(".dataplot_i3061007142472").style("width"));
chartHeight = parseInt(d3.select(".dataplot_i3061007142472").style("height"));
height = chartHeight - margin.top - margin.bottom + 20;
x_i3061007142472.range([60, chartWidth]);
y_i3061007142472.range([chartHeight - 30 - 10 + 20, 0]);
if (allow_pan_dir == "x" || allow_pan_dir == "both") {
vd_xaxis_i3061007142472 = d3.zoomTransform(d3.select("#i3061007142472").node()).rescaleX(x_i3061007142472);
svg_gX.call(d3.axisBottom(vd_xaxis_i3061007142472));
} else {
vd_xaxis_i3061007142472 = x_i3061007142472;
}
if (allow_pan_dir == "y" || allow_pan_dir == "both") {
vd_yaxis_i3061007142472 = d3.zoomTransform(d3.select("#i3061007142472").node()).rescaleY(y_i3061007142472);
svg_gY.call(d3.axisLeft(vd_yaxis_i3061007142472));
} else {
vd_yaxis_i3061007142472 = y_i3061007142472;
}
let currTransform = d3.zoomTransform(d3.select('#i3061007142472').node());
d3.select("#i3061007142472").call(zoom.transform, currTransform);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./styles.css ">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js" integrity="sha512-il/oXcqETt5LGGmWWbOZLxrDgQQXlr7+ZI37ksA//3e9mxFloAOzlkF8SqtMOlWL6zTCk8hPYUQnreiQvT4elQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
</head>
<body>
<div id="my_plot" style="display: flex; flex: 1;">
<svg id="i3061007142472" class="dataplot_i3061007142472 dataplot"></svg>
</div>
<script src="./app.js"></script>
</body>
</html>
I tried changing the domain on resize to match the transformed, tried using an intermediary scale, tried modifying the reference scale.

d3 contour Observable to Vanilla JS

I am converting the d3 contour example https://observablehq.com/#d3/volcano-contours?collection=#d3/d3-contour to vanilla js for a stand alone application. I am new to observable and JS.
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://d3js.org/d3-contour.v2.min.js"></script>
<script src="https://d3js.org/d3-hsv.v0.1.min.js"></script>
</head>
<body>
<div class="container"></div>
<script>
function vChart(container){
const data = FileAttachment("volcano.json").json();
const height = data.height;
const width = data.width;
const contours = d3.contours().size([width, height]);
const path = d3.geoPath();
function interpolateTerrain() {
const i0 = d3.interpolateHsvLong(d3.hsv(120, 1, 0.65), d3.hsv(60, 1, 0.90));
const i1 = d3.interpolateHsvLong(d3.hsv(60, 1, 0.90), d3.hsv(0, 0, 0.95));
return t => t < 0.5 ? i0(t * 2) : i1((t - 0.5) * 2);
}
const color = d3.scaleSequential(interpolateTerrain).domain(d3.extent(data.values)).nice();
const thresholds = color.ticks(20);
const wide = Generators.observe(notify => {
let wide;
function resized() {
let w = innerWidth > 640;
if (w !== wide) notify(wide = w);
}
resized();
addEventListener("resize", resized);
return () => removeEventListener("resize", resized);
})
const svg = d3.select(container).append('svg')
.attr("viewBox", wide ? [0, 0, width, height] : [0, 0, height, width])
.style("display", "block")
.style("margin", "0 -14px")
.style("width", "calc(100% + 28px)")
.style("height", "auto");
const g = svg.append("g")
.attr("transform", wide ? null : `
rotate(90 ${width/2},${height/2})
translate(${(width - height) / 2},${(width - height) / 2})
`)
.attr("stroke", "white")
.attr("stroke-width", 0.03);
for (const threshold of thresholds) {
g.append("path")
.attr("d", path(contours.contour(data.values, threshold)))
.attr("fill", color(threshold));
yield svg.node();
}
}
vChart('.container')
</script>
</body>
</html>
This results in two errors
Uncaught ReferenceError: Fileattachment is not defined
Uncaught ReferenceError: Generators is not defined
I am not able to recreate the generator function, Fileattachment function I guess it is related to observable.

Simple Bar Plot with dimple.js and d3.js

I'm working on a very basic bar plot with dimple.js. When I render in the browser, it shows only the axes and axis labels, but no bars. Any help appreciated. I am using python to create a localhost.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="main.css" rel="stylesheet">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.0.0.min.js"></script>
</head>
<body>
<h2> Rise of the Machines: R&D on Unmanned Aerial Aircrafts</h2>
<script src="index.js"></script>
</body>
</html>
index.js
function draw(data) {
/*
D3.js setup code
*/
var margin = 75;
var width = 1400 - margin;
var height = 600 - margin;
/* Find body tag, append svg, and add chart group tag*/
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin)
.attr("height", height + margin)
.append("g")
.attr("class","chart");
/*
Dimple.js Chart construction code
*/
var myChart = new dimple.chart(svg, data);
x = myChart.addCategoryAxis("x", "");
y = myChart.addMeasureAxis("y", "Share of Global Spending (%)");
myChart.addSeries(null, dimple.plot.bar);
myChart.draw();
};
d3.csv("data.csv", draw);
You'd not tell to dimple where to get the data:
x = myChart.addCategoryAxis("x", ""); //<---- X values
y = myChart.addMeasureAxis("y", "Share of Global Spending (%)"); // <--- Y values
example
var data = [
{ "Word":"Hello", "Awesomeness":2000 },
{ "Word":"World", "Awesomeness":3000 }
];
chart.addCategoryAxis("x", "Word");
chart.addMeasureAxis("y", "Awesomeness");
another example
var data = [
{ "data1":"Hello", "data2":2000 },
{ "data1":"World", "data2":3000 }
];
chart.addCategoryAxis("x", "data1");
chart.addMeasureAxis("y", "data2");
You must point to data origin, from csv column name. With your csv:
Xdata, Yvalue
1,10
2,20
3,30
4,20
Your code:
chart.addCategoryAxis("x", "Xdata");
chart.addMeasureAxis("y", "Yvalue");
On the dimple website, it seems to be recommended procedure to use .tsv (tab seperated values) as opposed to comma seperated values.
Here is a sample (vertical) bar chart code taken from the site
<html>
<div id="chartContainer">
<script src="/lib/d3.v3.4.8.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.2.0.min.js"></script>
<script type="text/javascript">
var svg = dimple.newSvg("#chartContainer", 590, 400);
d3.tsv("/data/example_data.tsv", function (data) {
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 510, 330)
myChart.addCategoryAxis("x", ["Price Tier", "Channel"]);
myChart.addMeasureAxis("y", "Unit Sales");
myChart.addSeries("Channel", dimple.plot.bar);
myChart.addLegend(65, 10, 510, 20, "right");
myChart.draw();
});
</script>
</div>
</html>
Hopefully, this will guide you in the right direction.

Plotting a very large number of points on HTML5 canvas with JavaScript

I am trying to draw a huge (60k) number of (x, y) points on an HTML5 canvas and simulate streaming data points with D3.js in Chrome and Firefox, and finding that the browser freezes and crashes after about 10 seconds.
I am generating the data set with random values as follows:
var data = d3.range(60000).map(function() { return Math.random() * 500; });
Would it help to break generation of data into sections? I feel that this might be caused by trying to store such a large data set at one time as I have shown.
Is there any way that I can prevent this from happening? Such as drawing and saving smaller sections as tiled images?
Added code:
var margin = {top: 20, right: 20, bottom: 20, left: 40},
w = 100 - margin.left - margin.right,
h = 100 - margin.top - margin.bottom;
var canvas = d3.select("canvas")
.node();
var context = canvas.getContext('2d');
var scale = d3.scale.linear()
. range([0,w])
.domain([0,h]);
data = d3.range(60000).map(function(){return Math.random()*500});
data.forEach(function(d,i) {
context.strokeStyle="red";
context.lineWidth="1";
context.lineTo(scale(++k),scale(d));
context.stroke();
});
Since you are asking a completely different question in the comment section I thought of put it another answer.
Comments and working code inline.
var margin = {top: 20, right: 20, bottom: 20, left: 40},
w = 100 - margin.left - margin.right,
h = 100 - margin.top - margin.bottom;
var canvas = d3.select("canvas")
.node();
var context = canvas.getContext('2d');
var data = d3.range(11).map(function(){return Math.random()*10})
var x = d3.scale.linear().domain([0, 10]).range([0, 700]);
var y = d3.scale.linear().domain([0, 10]).range([10, 290]);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d,i) {console.log(x(i));return x(i);})
.y(function(d) {return y(d);})
//making a dummy SVG
var path = d3.select("body").append("svg").append("path")
.attr("d", line(data))
.attr("stroke", "steelblue")
.attr("stroke-width", "2")
.attr("fill", "none").remove();
d3.select("body svg").remove();
//going from 0 to the paths total length and storing all the points
var points = [];
for(var i =0; i < path.node().getTotalLength(); i++){
points.push(path.node().getPointAtLength(i));//store point # that length
}
var id = window.setInterval(function(){
console.log("Doing")
var point = points.shift();//take each point
context.strokeStyle="red";
context.lineWidth="1";
context.lineTo(point.x,point.y);
context.stroke();
if(points.length <= 0){
console.log("Finished")
window.clearInterval(id);//clear the interval since the drawing is complete
}
}, 10)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.10/d3.js"></script>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
</canvas>
<script src="script.js"></script>
</body>
</html>
Working code on Plunker.
The problem is here:
data.forEach(function(d,i) {
context.strokeStyle="red";
context.lineWidth="1";
context.lineTo(scale(++k),scale(d));
context.stroke();//this should be out of the for loop you should be doing it once not everytime
});
Something like this:
data.forEach(function(d,i) {
context.strokeStyle="red";
context.lineWidth="1";
var j = scale(d);
var m = scale(d++);
context.lineTo(j,m);
});
context.stroke();
Working code here
Hope this helps!

D3 behave weird when I do a drag act which also trigger unexpected zoom function

I am yet a noob for d3 and javascript,while I was writing some code to deal with drag the dots and zoom the coordinate, something weird happened, the dots call the drag function,an outer group() element call the zoom, but when I dragging the dot, the outer group change its translate attribute.Code comes below:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>zoom test</title>
</head>
<body></body>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js">
</script>
<script type="text/javascript" charset="utf-8">
function addElem(container,elem){
return container.append(elem);
}
function createLinearScale(dx,dy,rx,ry){
return d3.scale.linear()
.domain([dx,dy])
.range([rx,ry])
}
function appendWithData(container,selector,type,id,classed,dataset){
var result = container.selectAll(selector)
.data(dataset)
.enter()
.append(type);
if(id)
result.attr("id",id);
if(classed)
result.classed(classed,true);
return result;
}
function getElem(selector){
return d3.select(selector);
}
function getAxis(){
return d3.svg.axis();
}
function drag(){
return d3.behavior.drag();
}
function getThis(){
return d3.select("this");
}
function zoom(){
return d3.behavior.zoom();
}
function arrayDelete(array,target,condition){
for (var i = 0, l = array.length; i < l; i ++) {
var v = arr[i];
if((target = v) && condition){
array.splice(i,1);
}
}
}
</script>
<script type="text/javascript" charset="utf-8">
/**
* Set frame for page
*
*/
var body = getElem("body");
var svg = addElem(body,"svg");
var outer = addElem(svg,"g");
var target = addElem(outer,"g");
var x_axis = addElem(target,"g");
var y_axis = addElem(target,"g");
var dots = addElem(target,"g");
var data = [
[ 5, 20 ],
[ 480, 90 ],
[ 250, 50 ],
[ 100, 33 ],
[ 330, 95 ],
[ 410, 12 ],
[ 475, 44 ],
[ 25, 67 ],
[ 85, 21 ],
[ 220, 88 ]
];
/**
* Add axis to chart
*
*/
var height = 500;
var width = 960;
var x_scale = createLinearScale(0, d3.max(data,function(d){return d[0];}) + 50, 0, width - 10);
var y_scale = createLinearScale(0, d3.max(data, function(d){return d[1];}) + 50, height - 10, 0);
var ax_scale = createLinearScale(0, width - 10, 0, d3.max(data,function(d){return d[0];}) + 50);
var ay_scale = createLinearScale(height -10, 0, 0, d3.max(data, function(d){ return d[1];}) + 50);
var xaxis = getAxis().scale(x_scale).orient("bottom").ticks(30);
var yaxis = getAxis().scale(y_scale).orient("right").ticks(10);
x_axis.attr("transform",function(d){return "translate(0," + (height - 10) + ")"}).call(xaxis);
y_axis.attr("transform",function(d){return "translate(0,0)"}).call(yaxis);
/**
* Add dots * */
var dot = appendWithData(dots,"circle","circle","","datum",data);
var text = appendWithData(dots,"text","text","","index",data);
dot.data(data).attr({
"id" : function(d,i){return "datum" +i;},
"tag": function(d,i){return i + "";},
"cx" : function(d){return x_scale(d[0]).toFixed(0)},
"cy" : function(d){return y_scale(d[1]).toFixed(0)},
"fill" : function(d){return "rgb(0," + (d[1] * 5) % 255 + ",53)"},
"r" : 10 });
text.data(data).attr({
"id" : function(d,i){return "index" + i;},
"tag": function(d,i){return i + ""},
"y" : function(d){return y_scale(d[1]).toFixed(0)},
"x" : function(d){return x_scale(d[0]).toFixed(0)},
"transform" : "translate(15,-15)"
})
.text(function(d){return d[0] + "," + d[1]});
var flag = 1;
var drag = drag();
function dragstart(){
console.log("dragstart")
var cur = d3.select(this);
console.log("drag");
cur.transition().ease("elastc").attr({
"r" : 15
});
}
function dragging(){
flag = 0;
var cur = d3.select(this);
var tag = cur.attr("tag");
cir = d3.select("circle[tag='" + tag + "']");
txt = d3.select("text[tag='" + tag + "']");
console.log(cur);
console.log(txt);
var cur_x = d3.event.x;
var cur_y = d3.event.y;
//target.attr("transform","translate(0,0)");
cir.attr({
"cx" : function(d){return cur_x.toFixed(0)},
"cy" : function(d){return cur_y.toFixed(0)},
//"fill" : function(d){return "rgb(0," + (y_scale(cur_y) * 5) % 255 + ",53)"},
});
txt.attr({
"x" : function(d){return cur_x.toFixed(0)},
"y" : function(d){return cur_y.toFixed(0)},
})
.text(new Number(ax_scale(cur_x)).toFixed(0) + "," + new Number(ay_scale(cur_y)).toFixed(0));
}
function dragged(){
var cur = d3.select(this);
cur.transition().ease("elastc").attr({
"r" : 10
});
flag = 1;
}
drag.on("dragstart",dragstart)
.on("drag",dragging)
.on("dragend",dragged);
dot.call(drag);;
var zoom = zoom();
function zoomed(){
//if(flag){
console.log("zoomed");
outer.attr("transform","translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")");
//}
}
zoom.on("zoom",zoomed);
outer.call(zoom);
</script>
</html>
As you see, I set a toggle(the variable called flag) to solve the trigger problem,but it cause a new problem, I can't zoom with wheel when the mouse is aloft a blank space.
If I understand the question correctly, you want the zooming on the outer while you want dragging on the dots. In that case, there were two problems with your program:
Empty g as the outer: A g element is just an empty container and is unable to capture events inside itself. If you want to capture mouse actions anywhere inside the g, you need to include an invisible background rect inside it with pointer-events: all. Also, you want this element to appear before all other elements in the DOM so that it is indeed in the background:
var bgRect = addElem(outer, "rect");
bgRect.attr('fill', 'none')
.attr('stroke', 'none')
.attr('width', width)
.attr('height', height);
var target = addElem(outer, "g");
// ...
Update: See this question as well: d3.js - mouseover event not working properly on svg group
Transitioning on zooming: The "expected" zoom behavior is that the point under the mouse pointer stays static while everything around the pointer zooms in/out. Hence, the container needs to both scale and transition.
function zoomed(){
console.log("zoomed");
outer.attr("transform","translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")");
}
However, in your case, you do not want the container to transition so that the axis stays firmly rooted at the origin (0, 0). So:
function zoomed(){
console.log("zoomed");
outer.attr("transform","translate(" + [0,0] + ") scale(" + d3.event.scale + ")");
}
Working demo with these changes: http://jsfiddle.net/S3GsC/

Categories

Resources