D3 axisBottom scale domain issue when resizing after transform - javascript
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.
Related
D3 X Domain shifting unexpectedly after panning
I am trying to create a plot that is pannable/zoomable only in the x and is responsive to the page resizes. I am running into an issue where the domain of the x-axis works properly at the original zoomTransform. Code snippet is below. I would suggest opening in a different window to test. Notice that the domain stays the same when the window is resized at the original state. Once the plot is panned any amount (the further you pan the more prominent the issue) the domain will shift on page resize. I have tested trying to adjust the domain on x_ax to the value of the vd axis but that does not seem to help. 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_ax = d3.scaleTime() .domain([new Date('0'), new Date('10')]) .range([60, width]); x_ax.type = "time"; var svg_gX = svg.append("g") .attr("class", "xAxis dataplot") .attr("transform", `translate(0, ${height})`) svg_gX.call(d3.axisBottom(x_ax).ticks(5)); var y_ax = d3.scaleLinear() .domain([0, 10]) .range([height, 0]); y_ax.type = "linear"; let vd_xaxis_ax = x_ax.copy(); let vd_yaxis_ax = y_ax.copy(); var svg_gY = svg.append("g") .attr("class", "yAxis dataplot") .style("padding-left", "50px") .attr("transform", "translate(" + 60 + ", 0)") .call(d3.axisLeft(y_ax).ticks(5)); allow_pan_dir = "x"; domain = x_ax.domain(); function zoom_handler_dataplot() { if (allow_pan_dir != "none") { if (allow_pan_dir == "x" || allow_pan_dir == "both") { vd_xaxis_ax = d3.event.transform.rescaleX(x_ax); domain = vd_xaxis_ax.domain() svg_gX.call(d3.axisBottom(vd_xaxis_ax)); } else { vd_xaxis_ax = x_ax; } if (allow_pan_dir == "y" || allow_pan_dir == "both") { vd_yaxis_ax = d3.event.transform.rescaleY(y_ax); svg_gY.call(d3.axisLeft(vd_yaxis_ax)); } else { vd_yaxis_ax = y_ax; } } } 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_ax.range([60, chartWidth]); y_ax.range([chartHeight - 30 - 10 + 20, 0]); if (allow_pan_dir == "x" || allow_pan_dir == "both") { vd_xaxis_ax = d3.zoomTransform(d3.select("#i3061007142472").node()).rescaleX(x_ax); svg_gX.call(d3.axisBottom(vd_xaxis_ax)); } else { vd_xaxis_ax = x_ax; } if (allow_pan_dir == "y" || allow_pan_dir == "both") { vd_yaxis_ax = d3.zoomTransform(d3.select("#i3061007142472").node()).rescaleY(y_ax); svg_gY.call(d3.axisLeft(vd_yaxis_ax)); } else { vd_yaxis_ax = y_ax; } 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>
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.
How to create progress bars?
I want to create a waveform with progress bars that fill with another color from left to right. Right now it looks: I want it to look like this. Yellow is buffered audio, orange is playing right now. I already have these values. The main question is how do I fill each rect with color by currentTime of audio? Here's my code: const elementWidth = 1100 const elementHeight = 64 const duration = 160 const currentTime = 20 const buffered = 140 // here's data that i get from web audio api // bar length in seconds would be: // duration / renderData = how much seconds in one bar const renderData = [ [-0.015067690176936956, 0.015065840696712662], [-0.009963374263646985, 0.009960838406137254], [-0.0329772714073922, 0.032922178973984494], [-0.02010780853750818, 0.020192897509204638], [-0.029141768346505944, 0.02913273608186522], [-0.03390369982419367, 0.033888949138664096], [-0.05309944789682607, 0.053106191954295334], [-0.017992382356680794, 0.0179506794436456], [-0.04118192967225779, 0.04120773269527067], [-0.032132343283569134, 0.03223372926977138], [-0.04340663941189386, 0.043317410948806916], [-0.026866048759920942, 0.02695383570549558], [-0.041548487297645216, 0.04142889765358134], [-0.0512541217270734, 0.05128097373670754], [-0.02645596673127562, 0.026461825339764114], [-0.03276659370022165, 0.032869462727325334], [-0.02983164709570332, 0.02965126735342542], [-0.06186988270590101, 0.06228762507639405], [-0.037202475771159274, 0.03684529067849468], [-0.04496168984286248, 0.044984343262096924], [-0.02961698097048877, 0.029580527280458145], [-0.06637895360455075, 0.06584970915134748], [-0.03966561332234608, 0.04028105442218536], [-0.04888827685580639, 0.04879637577182824], [-0.034440279218927505, 0.03448690299802526], [-0.04076603383847427, 0.04087949817166488], [-0.03422100968150345, 0.03407137586231854], [-0.03420552026962888, 0.034233479991186845], [-0.06124921943975816, 0.06133406711072517], [-0.08080063612343565, 0.08052139740352077], [-0.052296123826832304, 0.05245498821828788], [-0.07728568068325997, 0.0772439557897976], [-0.04070025960953707, 0.04072465208052425], [-0.016598400103531252, 0.01673240062886387], [-0.0495708419979178, 0.04952405213368158], [-0.03402468183819489, 0.03404496946468417], [-0.04719791564971553, 0.04716565090961255], [-0.024305039710776202, 0.024425998358774473], [-0.04539290174457686, 0.0453603392364138], [-0.04291280211166326, 0.042803252613569195], [-0.03237617188947045, 0.032430479168267405], [-0.046939414609483046, 0.046991124408919255], [-0.037727014544829074, 0.03756628029896137], [-0.05813820211592722, 0.058137499737658825], [-0.03306609736616569, 0.03332803022833292], [-0.03706343131822335, 0.03699838219166897], [-0.031640843865570666, 0.03150685332686255], [-0.07978720110560034, 0.07982405111308474], [-0.04565408283291298, 0.04548542047551325], [-0.03838929844552628, 0.0386080775422541], [-0.0349069030273341, 0.03516624962570975], [-0.05791808093217102, 0.057646960595115364], [-0.040111244425499945, 0.040190047578908046], [-0.0421531094659709, 0.04210734133509555], [-0.04358563889018587, 0.043380678911277275], [-0.024025454017633886, 0.024179111399202893], [-0.039038574013751944, 0.03889745017750074], [-0.02962543563292595, 0.02975662299643922], [-0.07215596460653108, 0.07225534620830149], [-0.0845103969948925, 0.08417566858032748], [-0.05029865141667644, 0.05110349428845409], [-0.06766253837563593, 0.06680008803627584], [-0.05413748268128195, 0.054261121431710246], [-0.04702217202288801, 0.04710783667779247], [-0.047177278676382065, 0.047241381909344966], [-0.04949906253183499, 0.049358880485210296], [-0.06384145451618915, 0.06398437795989458], [-0.0532812223855561, 0.05336013656088595], [-0.055032831282645335, 0.055131815418379866], [-0.05771727930777607, 0.05743980672281111], [-0.06865421948220482, 0.06896493506959074], [-0.05163944571854085, 0.05129081551014095], [-0.04546664828758613, 0.04549366890782257], [-0.02196073923070452, 0.022119579288034315], [-0.026824862238895183, 0.026915318981447094], [-0.04771898452983383, 0.04768769589918763], [-0.05221904154341058, 0.05202229643239835], [-0.04034726803191834, 0.040288317010035164], [-0.04252634158686052, 0.04275796625513488], [-0.055381424446109724, 0.05515857756430962], [-0.06160043085044191, 0.06143890271068376], [-0.04579617210990365, 0.04612433751815954], [-0.039244869887493206, 0.03927668403684328], [-0.03426885260996771, 0.03423936180141113], [-0.03516869910983574, 0.035127711830890515], [-0.026964357386084752, 0.02699723933039285], [-0.03816966714682839, 0.03778890745758835], [-0.04777519168041681, 0.04824239079542675], [-0.07617805358108933, 0.07612545525147858], [-0.047140552370394925, 0.04744151736320112], [-0.05137018378775051, 0.051114804207469784], [-0.03259493948312707, 0.0325308332802452], [-0.05715909221362399, 0.05709963073119724], [-0.04835633252739353, 0.04849600527981289], [-0.0433886628912617, 0.04331087342221564], [-0.05191740499328957, 0.05183144200010501], [-0.022690824730811025, 0.02281282548488598], [-0.021657892287654815, 0.02160585204290785], [-0.019911292276869504, 0.01990373441321122], [-0.05252214322669061, 0.052514338488489534], [-0.045757900781809524, 0.04581189437809006], [-0.02396372548560904, 0.023788207356191405], [-0.053426097224355276, 0.05348064888976746], [-0.05394891160261981, 0.05421456735805457], [-0.05251658416178273, 0.05238904616093791], [-0.04774168806444406, 0.047755594530669916], [-0.03506924339896615, 0.035076784816174336], [-0.044288649573623336, 0.044337743067559894], [-0.05109649028135573, 0.050986769978167874], [-0.03986396401411081, 0.03992226520835857], [-0.06271544843396921, 0.0628629998182233], [-0.060325113831802425, 0.06014867491287253], [-0.06409607265208252, 0.06426716029136537], [-0.02890807357828784, 0.02879981209701445], [-0.0579076968762734, 0.058055472378755635], [-0.0788244096514242, 0.07889209396389751], [-0.05489594835332056, 0.054304463238473114], [-0.05066376350430718, 0.051136225666937284], [-0.04324084422009672, 0.043106921303429975], [-0.03618639085199314, 0.03630391952984575], [-0.03229893887218463, 0.032254130211298596], [-0.040388961018727465, 0.04034166483632292], [-0.06891322548088202, 0.06894551548689337], [-0.05708462516274434, 0.05713687370165375], [-0.0908320094478539, 0.09053809343169553], [-0.06997210675874246, 0.07036387396569341], [-0.027676689451677956, 0.02757377175784071], [-0.02882633060378825, 0.029207481257562274], [-0.0414701765332311, 0.04136630655327525], [-0.05308296364144847, 0.0526747543606357], [-0.02724146501450132, 0.027406581699254588], [-0.04265844625269343, 0.04270290902986972], [-0.03899306746018118, 0.038745252551468795], [-0.0552804734553083, 0.05535944558193926], [-0.02309096284644189, 0.023040044134232315], [-0.0507964500028555, 0.05096013747702334], [-0.04123972706510699, 0.041359046982264745], [-0.03236153261658939, 0.032179960855430505], [-0.02858521671477931, 0.028570736354436077], [-0.03515761112679279, 0.03513507691850391], [-0.049852204843317816, 0.04984858000374448], [-0.038280519845162314, 0.038365751907998916], [-0.05489151074836156, 0.054958999808454506], [-0.02552547302215947, 0.025555844960312334], [-0.06393766191228746, 0.0638978766928521], [-0.04140103340243134, 0.04113465467714282], [-0.04647459357809104, 0.04654619117779597], [-0.03293849813553063, 0.03301029011724379], [-0.04428244235309984, 0.04433992273438912], [-0.047489538949244604, 0.04755256034371833], [-0.047176763166566854, 0.04719291045558167], [-0.06353201748860114, 0.06380784207550017], [-0.07775209195691819, 0.0773872824070752], [-0.054300174262817344, 0.054476381979975085], [-0.08808678703605805, 0.0879414485377677], [-0.04016286323725983, 0.04007725752721749], [-0.01889086923709467, 0.018989486049242103] ] const height = d3.scaleLinear() .domain(d3.extent(renderData.map(e => e[1] - e[0]))) .range([0, elementHeight]) d3.select(document.getElementById('app')) .append('svg') .attr('class', 'd3') .attr('width', elementWidth) .attr('height', elementHeight) .selectAll('.bar') .data(renderData) .enter() .append('rect') .attr('class', 'bar') .attr('fill', '#E0E0E0') .attr('x', (d, i) => (i * 2 + i)) .attr('y', d => elementHeight - height(d[1] - d[0])) .transition() .duration(300) .ease(d3.easeLinear) .attr('width', 2) .attr('height', d => height(d[1] - d[0])) <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div id='app' /> </body> </html>
Its really fun to play with svg :) This is what i made, have a look. const elementWidth = 1100 const elementHeight = 64 var audioTotalTime = 120.0000; // in secound var currentTime = 0; var currentBuffer = 0; const renderData = [ [-0.015067690176936956, 0.015065840696712662], [-0.009963374263646985, 0.009960838406137254], [-0.0329772714073922, 0.032922178973984494], [-0.02010780853750818, 0.020192897509204638], [-0.029141768346505944, 0.02913273608186522], [-0.03390369982419367, 0.033888949138664096], [-0.05309944789682607, 0.053106191954295334], [-0.017992382356680794, 0.0179506794436456], [-0.04118192967225779, 0.04120773269527067], [-0.032132343283569134, 0.03223372926977138], [-0.04340663941189386, 0.043317410948806916], [-0.026866048759920942, 0.02695383570549558], [-0.041548487297645216, 0.04142889765358134], [-0.0512541217270734, 0.05128097373670754], [-0.02645596673127562, 0.026461825339764114], [-0.03276659370022165, 0.032869462727325334], [-0.02983164709570332, 0.02965126735342542], [-0.06186988270590101, 0.06228762507639405], [-0.037202475771159274, 0.03684529067849468], [-0.04496168984286248, 0.044984343262096924], [-0.02961698097048877, 0.029580527280458145], [-0.06637895360455075, 0.06584970915134748], [-0.03966561332234608, 0.04028105442218536], [-0.04888827685580639, 0.04879637577182824], [-0.034440279218927505, 0.03448690299802526], [-0.04076603383847427, 0.04087949817166488], [-0.03422100968150345, 0.03407137586231854], [-0.03420552026962888, 0.034233479991186845], [-0.06124921943975816, 0.06133406711072517], [-0.08080063612343565, 0.08052139740352077], [-0.052296123826832304, 0.05245498821828788], [-0.07728568068325997, 0.0772439557897976], [-0.04070025960953707, 0.04072465208052425], [-0.016598400103531252, 0.01673240062886387], [-0.0495708419979178, 0.04952405213368158], [-0.03402468183819489, 0.03404496946468417], [-0.04719791564971553, 0.04716565090961255], [-0.024305039710776202, 0.024425998358774473], [-0.04539290174457686, 0.0453603392364138], [-0.04291280211166326, 0.042803252613569195], [-0.03237617188947045, 0.032430479168267405], [-0.046939414609483046, 0.046991124408919255], [-0.037727014544829074, 0.03756628029896137], [-0.05813820211592722, 0.058137499737658825], [-0.03306609736616569, 0.03332803022833292], [-0.03706343131822335, 0.03699838219166897], [-0.031640843865570666, 0.03150685332686255], [-0.07978720110560034, 0.07982405111308474], [-0.04565408283291298, 0.04548542047551325], [-0.03838929844552628, 0.0386080775422541], [-0.0349069030273341, 0.03516624962570975], [-0.05791808093217102, 0.057646960595115364], [-0.040111244425499945, 0.040190047578908046], [-0.0421531094659709, 0.04210734133509555], [-0.04358563889018587, 0.043380678911277275], [-0.024025454017633886, 0.024179111399202893], [-0.039038574013751944, 0.03889745017750074], [-0.02962543563292595, 0.02975662299643922], [-0.07215596460653108, 0.07225534620830149], [-0.0845103969948925, 0.08417566858032748], [-0.05029865141667644, 0.05110349428845409], [-0.06766253837563593, 0.06680008803627584], [-0.05413748268128195, 0.054261121431710246], [-0.04702217202288801, 0.04710783667779247], [-0.047177278676382065, 0.047241381909344966], [-0.04949906253183499, 0.049358880485210296], [-0.06384145451618915, 0.06398437795989458], [-0.0532812223855561, 0.05336013656088595], [-0.055032831282645335, 0.055131815418379866], [-0.05771727930777607, 0.05743980672281111], [-0.06865421948220482, 0.06896493506959074], [-0.05163944571854085, 0.05129081551014095], [-0.04546664828758613, 0.04549366890782257], [-0.02196073923070452, 0.022119579288034315], [-0.026824862238895183, 0.026915318981447094], [-0.04771898452983383, 0.04768769589918763], [-0.05221904154341058, 0.05202229643239835], [-0.04034726803191834, 0.040288317010035164], [-0.04252634158686052, 0.04275796625513488], [-0.055381424446109724, 0.05515857756430962], [-0.06160043085044191, 0.06143890271068376], [-0.04579617210990365, 0.04612433751815954], [-0.039244869887493206, 0.03927668403684328], [-0.03426885260996771, 0.03423936180141113], [-0.03516869910983574, 0.035127711830890515], [-0.026964357386084752, 0.02699723933039285], [-0.03816966714682839, 0.03778890745758835], [-0.04777519168041681, 0.04824239079542675], [-0.07617805358108933, 0.07612545525147858], [-0.047140552370394925, 0.04744151736320112], [-0.05137018378775051, 0.051114804207469784], [-0.03259493948312707, 0.0325308332802452], [-0.05715909221362399, 0.05709963073119724], [-0.04835633252739353, 0.04849600527981289], [-0.0433886628912617, 0.04331087342221564], [-0.05191740499328957, 0.05183144200010501], [-0.022690824730811025, 0.02281282548488598], [-0.021657892287654815, 0.02160585204290785], [-0.019911292276869504, 0.01990373441321122], [-0.05252214322669061, 0.052514338488489534], [-0.045757900781809524, 0.04581189437809006], [-0.02396372548560904, 0.023788207356191405], [-0.053426097224355276, 0.05348064888976746], [-0.05394891160261981, 0.05421456735805457], [-0.05251658416178273, 0.05238904616093791], [-0.04774168806444406, 0.047755594530669916], [-0.03506924339896615, 0.035076784816174336], [-0.044288649573623336, 0.044337743067559894], [-0.05109649028135573, 0.050986769978167874], [-0.03986396401411081, 0.03992226520835857], [-0.06271544843396921, 0.0628629998182233], [-0.060325113831802425, 0.06014867491287253], [-0.06409607265208252, 0.06426716029136537], [-0.02890807357828784, 0.02879981209701445], [-0.0579076968762734, 0.058055472378755635], [-0.0788244096514242, 0.07889209396389751], [-0.05489594835332056, 0.054304463238473114], [-0.05066376350430718, 0.051136225666937284], [-0.04324084422009672, 0.043106921303429975], [-0.03618639085199314, 0.03630391952984575], [-0.03229893887218463, 0.032254130211298596], [-0.040388961018727465, 0.04034166483632292], [-0.06891322548088202, 0.06894551548689337], [-0.05708462516274434, 0.05713687370165375], [-0.0908320094478539, 0.09053809343169553], [-0.06997210675874246, 0.07036387396569341], [-0.027676689451677956, 0.02757377175784071], [-0.02882633060378825, 0.029207481257562274], [-0.0414701765332311, 0.04136630655327525], [-0.05308296364144847, 0.0526747543606357], [-0.02724146501450132, 0.027406581699254588], [-0.04265844625269343, 0.04270290902986972], [-0.03899306746018118, 0.038745252551468795], [-0.0552804734553083, 0.05535944558193926], [-0.02309096284644189, 0.023040044134232315], [-0.0507964500028555, 0.05096013747702334], [-0.04123972706510699, 0.041359046982264745], [-0.03236153261658939, 0.032179960855430505], [-0.02858521671477931, 0.028570736354436077], [-0.03515761112679279, 0.03513507691850391], [-0.049852204843317816, 0.04984858000374448], [-0.038280519845162314, 0.038365751907998916], [-0.05489151074836156, 0.054958999808454506], [-0.02552547302215947, 0.025555844960312334], [-0.06393766191228746, 0.0638978766928521], [-0.04140103340243134, 0.04113465467714282], [-0.04647459357809104, 0.04654619117779597], [-0.03293849813553063, 0.03301029011724379], [-0.04428244235309984, 0.04433992273438912], [-0.047489538949244604, 0.04755256034371833], [-0.047176763166566854, 0.04719291045558167], [-0.06353201748860114, 0.06380784207550017], [-0.07775209195691819, 0.0773872824070752], [-0.054300174262817344, 0.054476381979975085], [-0.08808678703605805, 0.0879414485377677], [-0.04016286323725983, 0.04007725752721749], [-0.01889086923709467, 0.018989486049242103] ] const height = d3.scaleLinear() .domain(d3.extent(renderData.map(e => e[1] - e[0]))) .range([0, elementHeight]) d3.select(document.getElementById('app')) .append('svg') .attr('class', 'd3') .attr('width', elementWidth) .attr('height', elementHeight) .selectAll('.bar') .data(renderData) .enter() .append('rect') .attr('class', 'bar') .attr('fill', '#E0E0E0') .attr('x', (d, i) => (i * 2 + i)) .attr('y', d => elementHeight - height(d[1] - d[0])) .transition() .duration(300) .ease(d3.easeLinear) .attr('width', 2) .attr('height', d => height(d[1] - d[0])) var svg = $(".d3"); var lng = svg.find("rect").length; function update(){ var selectedRect = Math.floor(((currentTime ) / ( lng )) * (audioTotalTime + 86)); var selectedBufferRect = Math.floor(((currentBuffer ) / ( lng )) * (audioTotalTime + 86)); // this is the best i could do, but you understand the ide var playingColor = "red"; var bufferColor = "green"; // buffer Progress $.each (svg.find("rect"), function(index, i){ // buffer if (index<= selectedBufferRect &&$(this).attr("fill") != playingColor ) $(this).attr("fill", bufferColor); }); // Playing Progress $.each (svg.find("rect"), function(index, i){ // Playing if (index<= selectedRect) $(this).attr("fill", playingColor); }); } function PlayingSimulator(){ currentTime += 1 currentBuffer +=3; if (currentTime>= audioTotalTime){ update(); return false; } update(); setTimeout(PlayingSimulator, 60); } PlayingSimulator(); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div id='app' /> </body> </html>
Just add some simple logic in function paint() to determine the fill color. Then you need need to decide how often to re-render (I guess at least once every second for updating currentTime). const elementWidth = 1100; const elementHeight = 64; const duration = 160; let currentTime = 0; const buffered = 140; const renderData = [[-0.015067690176936956, 0.015065840696712662],[-0.009963374263646985, 0.009960838406137254],[-0.0329772714073922, 0.032922178973984494],[-0.02010780853750818, 0.020192897509204638],[-0.029141768346505944, 0.02913273608186522],[-0.03390369982419367, 0.033888949138664096],[-0.05309944789682607, 0.053106191954295334],[-0.017992382356680794, 0.0179506794436456],[-0.04118192967225779, 0.04120773269527067],[-0.032132343283569134, 0.03223372926977138],[-0.04340663941189386, 0.043317410948806916],[-0.026866048759920942, 0.02695383570549558],[-0.041548487297645216, 0.04142889765358134],[-0.0512541217270734, 0.05128097373670754],[-0.02645596673127562, 0.026461825339764114],[-0.03276659370022165, 0.032869462727325334],[-0.02983164709570332, 0.02965126735342542],[-0.06186988270590101, 0.06228762507639405],[-0.037202475771159274, 0.03684529067849468],[-0.04496168984286248, 0.044984343262096924],[-0.02961698097048877, 0.029580527280458145],[-0.06637895360455075, 0.06584970915134748],[-0.03966561332234608, 0.04028105442218536],[-0.04888827685580639, 0.04879637577182824],[-0.034440279218927505, 0.03448690299802526],[-0.04076603383847427, 0.04087949817166488],[-0.03422100968150345, 0.03407137586231854],[-0.03420552026962888, 0.034233479991186845],[-0.06124921943975816, 0.06133406711072517],[-0.08080063612343565, 0.08052139740352077],[-0.052296123826832304, 0.05245498821828788],[-0.07728568068325997, 0.0772439557897976],[-0.04070025960953707, 0.04072465208052425],[-0.016598400103531252, 0.01673240062886387],[-0.0495708419979178, 0.04952405213368158],[-0.03402468183819489, 0.03404496946468417],[-0.04719791564971553, 0.04716565090961255],[-0.024305039710776202, 0.024425998358774473],[-0.04539290174457686, 0.0453603392364138],[-0.04291280211166326, 0.042803252613569195],[-0.03237617188947045, 0.032430479168267405],[-0.046939414609483046, 0.046991124408919255],[-0.037727014544829074, 0.03756628029896137],[-0.05813820211592722, 0.058137499737658825],[-0.03306609736616569, 0.03332803022833292],[-0.03706343131822335, 0.03699838219166897],[-0.031640843865570666, 0.03150685332686255],[-0.07978720110560034, 0.07982405111308474],[-0.04565408283291298, 0.04548542047551325],[-0.03838929844552628, 0.0386080775422541],[-0.0349069030273341, 0.03516624962570975],[-0.05791808093217102, 0.057646960595115364],[-0.040111244425499945, 0.040190047578908046],[-0.0421531094659709, 0.04210734133509555],[-0.04358563889018587, 0.043380678911277275],[-0.024025454017633886, 0.024179111399202893],[-0.039038574013751944, 0.03889745017750074],[-0.02962543563292595, 0.02975662299643922],[-0.07215596460653108, 0.07225534620830149],[-0.0845103969948925, 0.08417566858032748],[-0.05029865141667644, 0.05110349428845409],[-0.06766253837563593, 0.06680008803627584],[-0.05413748268128195, 0.054261121431710246],[-0.04702217202288801, 0.04710783667779247],[-0.047177278676382065, 0.047241381909344966],[-0.04949906253183499, 0.049358880485210296],[-0.06384145451618915, 0.06398437795989458],[-0.0532812223855561, 0.05336013656088595],[-0.055032831282645335, 0.055131815418379866],[-0.05771727930777607, 0.05743980672281111],[-0.06865421948220482, 0.06896493506959074],[-0.05163944571854085, 0.05129081551014095],[-0.04546664828758613, 0.04549366890782257],[-0.02196073923070452, 0.022119579288034315],[-0.026824862238895183, 0.026915318981447094],[-0.04771898452983383, 0.04768769589918763],[-0.05221904154341058, 0.05202229643239835],[-0.04034726803191834, 0.040288317010035164],[-0.04252634158686052, 0.04275796625513488],[-0.055381424446109724, 0.05515857756430962],[-0.06160043085044191, 0.06143890271068376],[-0.04579617210990365, 0.04612433751815954],[-0.039244869887493206, 0.03927668403684328],[-0.03426885260996771, 0.03423936180141113],[-0.03516869910983574, 0.035127711830890515],[-0.026964357386084752, 0.02699723933039285],[-0.03816966714682839, 0.03778890745758835],[-0.04777519168041681, 0.04824239079542675],[-0.07617805358108933, 0.07612545525147858],[-0.047140552370394925, 0.04744151736320112],[-0.05137018378775051, 0.051114804207469784],[-0.03259493948312707, 0.0325308332802452],[-0.05715909221362399, 0.05709963073119724],[-0.04835633252739353, 0.04849600527981289],[-0.0433886628912617, 0.04331087342221564],[-0.05191740499328957, 0.05183144200010501],[-0.022690824730811025, 0.02281282548488598],[-0.021657892287654815, 0.02160585204290785],[-0.019911292276869504, 0.01990373441321122],[-0.05252214322669061, 0.052514338488489534],[-0.045757900781809524, 0.04581189437809006],[-0.02396372548560904, 0.023788207356191405],[-0.053426097224355276, 0.05348064888976746],[-0.05394891160261981, 0.05421456735805457],[-0.05251658416178273, 0.05238904616093791],[-0.04774168806444406, 0.047755594530669916],[-0.03506924339896615, 0.035076784816174336],[-0.044288649573623336, 0.044337743067559894],[-0.05109649028135573, 0.050986769978167874],[-0.03986396401411081, 0.03992226520835857],[-0.06271544843396921, 0.0628629998182233],[-0.060325113831802425, 0.06014867491287253],[-0.06409607265208252, 0.06426716029136537],[-0.02890807357828784, 0.02879981209701445],[-0.0579076968762734, 0.058055472378755635],[-0.0788244096514242, 0.07889209396389751],[-0.05489594835332056, 0.054304463238473114],[-0.05066376350430718, 0.051136225666937284],[-0.04324084422009672, 0.043106921303429975],[-0.03618639085199314, 0.03630391952984575],[-0.03229893887218463, 0.032254130211298596],[-0.040388961018727465, 0.04034166483632292],[-0.06891322548088202, 0.06894551548689337],[-0.05708462516274434, 0.05713687370165375],[-0.0908320094478539, 0.09053809343169553],[-0.06997210675874246, 0.07036387396569341],[-0.027676689451677956, 0.02757377175784071],[-0.02882633060378825, 0.029207481257562274],[-0.0414701765332311, 0.04136630655327525],[-0.05308296364144847, 0.0526747543606357],[-0.02724146501450132, 0.027406581699254588],[-0.04265844625269343, 0.04270290902986972],[-0.03899306746018118, 0.038745252551468795],[-0.0552804734553083, 0.05535944558193926],[-0.02309096284644189, 0.023040044134232315],[-0.0507964500028555, 0.05096013747702334],[-0.04123972706510699, 0.041359046982264745],[-0.03236153261658939, 0.032179960855430505],[-0.02858521671477931, 0.028570736354436077],[-0.03515761112679279, 0.03513507691850391],[-0.049852204843317816, 0.04984858000374448],[-0.038280519845162314, 0.038365751907998916],[-0.05489151074836156, 0.054958999808454506],[-0.02552547302215947, 0.025555844960312334],[-0.06393766191228746, 0.0638978766928521],[-0.04140103340243134, 0.04113465467714282],[-0.04647459357809104, 0.04654619117779597],[-0.03293849813553063, 0.03301029011724379],[-0.04428244235309984, 0.04433992273438912],[-0.047489538949244604, 0.04755256034371833],[-0.047176763166566854, 0.04719291045558167],[-0.06353201748860114, 0.06380784207550017],[-0.07775209195691819, 0.0773872824070752],[-0.054300174262817344, 0.054476381979975085],[-0.08808678703605805, 0.0879414485377677],[-0.04016286323725983, 0.04007725752721749],[-0.01889086923709467, 0.018989486049242103]]; const height = d3 .scaleLinear() .domain(d3.extent(renderData.map(e => e[1] - e[0]))) .range([0, elementHeight]); const svg = d3 .select("#app") .append("svg") .attr("class", "d3") .attr("width", elementWidth) .attr("height", elementHeight); const bar = svg.selectAll(".bar").data(renderData); const barEnter = bar .enter() .append("rect") .attr("class", "bar") .attr("fill", (d, i) => { return paint(i); }) .attr("x", (d, i) => i * 2 + i) .attr("y", d => elementHeight - height(d[1] - d[0])) .attr("width", 2) .attr("height", d => height(d[1] - d[0])); function reRender() { currentTime += 1 barEnter.attr("fill", (d, i) => { return paint(i); }) } window.setInterval(function () { reRender() }, 1000); function paint(i) { barPos = i / renderData.length * duration; if (barPos <= currentTime) { return "red"; } else if (barPos <= buffered) { return "orange"; } else { return "grey"; } } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div id='app' /> </body> </html> Codepen
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/