A simple ball movement transition in d3.js using SVG.
jsfiddle : http://jsfiddle.net/eNe3U/1/
When I run above example, the ball looks blurred during the transition and the tranistion is not smooth.
Is there any option to get smooth transition in d3.js or am I missing something here?
Code :
var width = 720, height = 580;
var padding = 50;
var svg = d3.select("body").append("svg");
svg.attr("width",width)
.attr("height",height);
var circle = svg.append("circle")
.attr("cx","100")
.attr("cy","100")
.attr("r",10)
.attr("stroke","red")
.attr("stroke-width","1")
.attr("fill","steelblue");
circle.transition()
.duration(2000)
.attr("cx","600")
.attr("cy","700")
.attr("fill","green");
Related
I'm trying to draw choropleth map of Seoul but it just gives me only a black rectangle.
I thought there might be a problem with projection.scale but I couldn't figure it out.
I used scale.fitSize() function to handle it. but my d3 is older version that not available of fitSize().
my code is here:
var width = 600, height = 700;
var svg = d3.select('#chart').append('svg')
.attr('width',width)
.attr('height',height);
var projection = d3.geo.mercator()
.center([128,36])
.scale(5000)
.translate([width/2, height/2]);
var path = d3.geo.path()
.projection(projection);
d3.json('Seoulmap.json',function(error,data) {
var features = topojson.feature(data, data.objects['Seoulmap']).features;
svg.selectAll('path')
.data(features)
.enter().append('path')
.attr('class','name')
.attr('d',path)
.attr('id',function(d) { return d.properties.ADM_DR_NM; });
});
How my code is rendering black rectangle:
Some background:
I have plotted a map and about 35k circles on it with zoom and tooltips working fine on SVG. However, due to the amount of circles that need to be drawn (and may be not the best written code; i'm a beginner) I see performance issues while getting the page to run.
And so, I wanted to try out the same page on a canvas to improve performance.
Problem:
I got the map itself working on canvas but I have been trying to add the zoom feature but in vain. Any help in getting this fixed will be greatly appreciated.
Sample with SVG - https://bl.ocks.org/sharad-vm/af74ae5932de1bcf5a39b0f3f849d847
The code I have for Canvas is as below:
//Width and height
var w = 700;
var h = 600;
//Create Canvas element
var canvas = d3.select('#map')
.append('canvas')
.attr('width', w)
.attr('height', h);
var context = canvas.node().getContext('2d');
//Define map projection
var projection = d3.geo.mercator()
.translate([w/2, h/1.72])
.scale([100]);
//Define path generator
var path = d3.geo.path()
.projection(projection)
.context(context);
var init = 0;
canvas.call(zoom);
var zoom = d3.behavior.zoom()
.translate([0, 0])
.scale(1)
.scaleExtent([1, 30])
.on("zoom", zoomed);
//function to zoom
function zoomed() {
context.save();
context.clearRect(0, 0, w, h);
context.translate(d3.event.transform.x, d3.event.transform.y);
context.scale(d3.event.transform.k, d3.event.transform.k);
draw();
context.restore();
};
draw();
//Load in GeoJSON data
function draw() {
...
}
When using projections the secret to get the zoom working is to transform the projection itself. For your example you can just adjust your projection before redrawing with something like:
projection.translate([w/2 + d3.event.transform.x, h/1.72 + d3.event.transform.y])
.scale([100*d3.event.transform.k]);
Another option is to scale the canvas itself, like in this example I made
I have the following code which should to display drowned line in the canvas element.
var initCanvas = function () {
var episodeLengthInPixels = moment.duration(episodeLogLength).asSeconds() * episodeWidthMultiplication;
console.log("Length of chart is "+episodeLengthInPixels +" px");
try {
canvas = d3.select("body").append("canvas")
.attr("width", 500)
.attr("height", canvasHeight)
.attr("class", canvasSelector);
//Draw the Line
canvas.append("line") // attach a line
.style("stroke", "black") // colour the line
.attr("x1", 0) // x position of the first end of the line
.attr("x2", 500)
.attr("y1", waveHeight)
.attr("y2", waveHeight) ;
} catch (e) {
console.error(e);
}
}
Problem is that canvas and the line are available in the DOM model but are not visible (no exception is throwned). When i tried to work with SVG instead of the canvas, everything works fine.
How can I display the content in canvas using the D3.js library please? I tried to find any examples, but without the luck. Should i use D3.js fro canvas usage or something else (pure drawing to canvas in example)?
Many thanks for any advice.
Canvas and SVG are way different. It's not just a matter of changing "svg" for "canvas" in your d3.select("body").append() code. You should study the canvas documentation and the SVG documentation.
This, for instance, is how to draw a line in canvas:
var chart = d3.select("body").append("canvas")
.attr("width", 400)
.attr("height", 300);
var context = chart.node().getContext("2d");
context.beginPath();
context.moveTo(0,100);//here you set the equiv. to X1 and Y1 in SVG
context.lineTo(400,100);//here you set the equiv. to X2 and Y2 in SVG
context.stroke();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Also, keep in mind that the fact that you see a given element when inspecting the DOM doesn't mean that the element will show up. You can make this very simple test using d3:
d3.select("body").append("div").append("charlesdarwin");
You're gonna see this inspecting the DOM:
<div>
<charlesdarwin></charlesdarwin>
</div>
But, of course, you don't expect that this have any result.
Here is kinda an example taken from here.
https://bocoup.com/weblog/d3js-and-canvas
d3 and canvas are not the same.
var base = d3.select("#foo");
var chart = base.append("canvas")
.attr("width", 400)
.attr("height", 300);
var context = chart.node().getContext("2d");
var data = [1,2,13,20,23];
var scale = d3.scale.linear()
.range([10, 390])
.domain([1,23]);
data.forEach(function(d, i) {
context.beginPath();
context.rect(scale(d), 150, 10, 10);
context.fillStyle="red";
context.fill();
context.closePath();
});
// Your line here...
context.beginPath();
context.moveTo(10,10);
context.lineTo(40,60); // x2,y2 ...
context.stroke();
context.closePath();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Examples here
<div id="foo"></div>
I have three shapes all in the same group. This group have been transformed. I want to draw a line from one of the elements within that group. I am trying to access this elements coordinates by:
s.select("#hitboxHeel").getBBox().cx and s.select("#hitboxHeel").getBBox().cy
However this gives some weird coordinates, that are far off from where they should be. How do i get the actual position of the points, thus being able to draw a line?
I had a similar problem and found the solution from this post : Rectangle coordinates after transform
Here, you basically want to apply the 'aggregated' transform matrix of your shape to coordinates that are not transformed (sorry for the awkward phrasing). This matrix also incorporates the transformations of parent elements (group nodes here), so you shouldn't have to worry about them.
So, given :
your native svg element node
your native svg container svg
your original point of interest coordinates (before transforms) x and y that you want transformed
the expected transformed coordinates of your original point transformedPoint
`
// get the component transform matrix
var ctm = node.getCTM();
var svgPoint = svg.createSVGPoint();
svgPoint.x = x;
svgPoint.y = y;
// apply the matrix to the point
var transformedPoint = svgPoint.matrixTransform(ctm);
// an example using d3.js ( svg > g > rect )
// get the center of the rectangle after tansformations occured
var svg = d3.select('body').append('svg')
.attr('width', 500)
.attr('height', 500)
.attr('id', 'myCanvas')
.style('margin', 100)
var g = svg.append('g')
.attr('transform', 'translate(-10,10)')
var r = g.append('rect')
.attr('x', 300).attr('y', 100).attr('width', 79).attr('height', 150)
.attr('transform', 'translate(-54,300)rotate(-30,30,20)')
.attr('stroke', 'black')
.attr('fill', 'red')
var pt = svg.node().createSVGPoint()
pt.x = parseInt(r.attr('x')) + parseInt(r.attr('width')) / 2
pt.y = parseInt(r.attr('y')) + parseInt(r.attr('height')) / 2
var ctm = r.node().getCTM()
var center = pt.matrixTransform(ctm)
console.log('the transformed rectangle center', center)
// draw the center to confirm the accuracy of the process
svg.append('circle')
.attr('cx', center.x).attr('cy', center.y).attr('r', 5)
.attr('stroke', 'black')
.attr('fill', 'blue')
`
I am trying to get zoom to work by dragging a rectangle over my series plot to identify the interval of zooming. Here is my plunkr
http://plnkr.co/edit/isaHzvCO6fTNlXpE18Yt?p=preview
You can see the issue by drawing a rectangle with the mouse over the chart - The new chart overshoots the boundary of the X and Y axes. I thought my group under the svg would take care of the bounds of the series (path) but I am clearly mistaken. After staring at it for a long time, I could not figure it out. Please ignore the angular aspect of the plunkr. I think the issue is somewhere in the
//Build series group
var series = svgGroup.selectAll(".series")
.data(data)
.enter().append("g")
.attr("class", "series");
//Build each series using the line function
series.append("path")
.attr("class", "line")
.attr("d", function (d) {
return line(d.series);
})
.attr("id", function (d) {
//While generating the id for each series, map series name to the path element.
//This is useful later on for dealing with legend clicks to enable/disable plots
legendMap[d.name] = this;
//Build series id
return buildPathId(d.name);
})
.style("stroke", function (d) {
//Use series name to get the color for plotting
return colorFcn(d.name);
})
.style("stroke-width", "1px")
.style("fill", "none");
Any help with this is appreciated.
Thank you very much.
I think the method renderChartWithinSpecifiedInterval(minX, maxX, minY, maxY, pixelCoordinates) maybe has some problem there.
It seems the parameter like max_x passed in line 130 are a very big value like time seconds
var svg = renderChartWithinSpecifiedInterval(min_X, max_X, min_Y, max_Y, false);
max_X,min_X are value like 1415171404335
min_Y = 0, max_Y = 100
But in dragDrop call in line 192
function gEnd(d,i){
svg.selectAll(".zoom-rect").remove();
var svgGp = svg.select("g");
var groupTransform = d3.transform(svgGp.attr("transform"));
var xOffset = groupTransform.translate[0];
var yOffset = groupTransform.translate[1];
var xBegin = Math.min(xStart,xDyn) - xOffset;
var xEnd = Math.max(xStart,xDyn) - xOffset;
var yBegin = Math.min(yStart,yDyn) - yOffset;
var yEnd = Math.max(yStart,yDyn) - yOffset;
renderChartWithinSpecifiedInterval(xBegin, xEnd, yBegin, yEnd, true);
//It seems here the parameters values are all pixels
like xBegin = 100, xEnd = 200
}
hope it helps!