In one application I have both d3 map and leaflet map, I follow Mike's code to sync them(http://bost.ocks.org/mike/leaflet/) and draw svg points on leaflet map. The problem is that some points being cutoff at the edge of SVG container, and other SVG elements added later on (an animated pulse in this case) will only partially shown. I wonder if there's anyway to expand the SVG container based on the features (points) bound.
a working demo is here: http://xqin1.github.io/usschools/usac_school_stat.html, to reproduce the issue:
1. select the 'Number of Students' slider bar to 5300-6545, the two points on Leaftlet map only half shown.
2. click the first table row, map will zoom to the point, but the animated pulse being cut off.
Any suggestions are highly appreciated.
thanks
xiaoming
I had this problem as well, and found a solution. Referencing mbostock's sample code you just need to add a little bit of padding to the projected bounding box that is calculated each time reset is called:
var bottomLeft = project(bounds[0]),
topRight = project(bounds[1]);
Insert something like this (just after the above declarations):
var padding = 25; // In pixels, choose large enough to prevent edge clipping
// of your largest element
bottomLeft = [bottomLeft[0]-padding, bottomLeft[1]+padding]
topRight = [topRight[0]+padding, topRight[1]-padding]
Related
I based some code on the "Add a 3D model" example at maplibre.org in order to draw only a horizontal plane on a map which uses setTerrain to add a terrain layer.
My intention is to draw a couple of semitransparent layers at a given heights above sea level and have them intersect with mountains, somewhat similar to contour lines.
In my first test I just created a 1km-wide square at altitude 0.
I am somewhat confused by the behavior, since altitude 0 turns out to be the height of the terrain in the center of the visible map area. When I then drag the map and release the mouse, altitude 0 gets somehow reset again to the new altitude 0 of the terrain at the center, making the plane change its relative altitude.
The following animated GIF illustrates the problem:
The GIF has a mountain range to the right and the elevation is greatly exaggerated, in order to better illustrate the issue.
What do I need to do in order to be able to specify the height of the plane in meters above sea level and have it appear to be fixed at that height when dragging the map?
I think I need to get the height of the terrain at the center and then add/substract it from the plane's z-position in order for it to stay put at the height relative to given landmarks, but I have got no idea on how to do this inside of a custom layer's render function.
In this jsfiddle I have a D3 map that I took from here, but I'm trying to fit it in an svg that is half the original size. For that, I changed:
var width = 480;
var height = 300;
.....
var path = d3.geoPath(d3.geoIdentity().translate([width/2, height/2]).scale(height*.5));
But it's not working. How to make the map fit the svg?
D3's geoIdentity exposes almost all the standard methods of a d3 projection (off the top of my head, only rotation is not possible as the identity assumes cartesian data). Most importantly here, it exposes the fitSize and fitExtent methods. These methods set translate and scale based on the coordinate extent of displayed geojson data and the pixel extent of the svg/canvas.
To scale your features with a geo identity you can use:
d3.geoIdentity().fitSize([width,height],geojsonObject)
Note that an array of geojson features won't work, but a geojson feature collection or any individual feature/geometry object works too. The width and height are of the svg/canvas.
If you want to apply a margin, you can use:
d3.geoIdentity().fitExtent([[margin,margin],[width-margin,height-margin]],geojsonObject)
The margin doesn't need to be uniform, the format is [[left,top],[right,bottom]],geojsonObject
If using fitSize or fitExtent there is no need to set center, translate or scale manually and setting these afterwards will recenter or rescale the map.
I work with Forge Autodesk, and I want to apply a texture to some rectangle object. In fact I just needed some plan, but I was given a rectangle. So I want to apply my image on the main face of the rectangle.
const mytex = THREE.ImageUtils.loadTexture(mytexture)
// Repeat image through object
mytex.wrapS = THREE.RepeatWrapping //ClampToEdgeWrapping //MirroredRepeatWrapping //RepeatWrapping
mytex.wrapT = THREE.RepeatWrapping //ClampToEdgeWrapping //MirroredRepeatWrapping //RepeatWrapping
mytex.mapping = THREE.UVMapping
mytex.repeat.set (0.05, 0.05)
console.log("applied texture")
But I get this problem : a part of my image appears on the right upper side (upper and right corners are cut, so not on the rectangle), but the left and bottom sides are stretched across the rest of the rectangle face.
I would like to adapt my image so that its dimension fit the rectangle's dimensions, and not just repeat it.
I read this and this. I think my code is correctly written, but I may be missing a parameter or set the wrong one... The 2 images I am testing are 676x676 and 1024x484 pixels. I cannot access the rectangle dimensions from my function (I don't think so).
I tried to just repeat the image too but it does not work either...
Any idea ?
I'm trying to implement a responsive d3 bubble chart that updates its container svg (and the nodes it contains) while the page is being resized (kinda like this shows: http://jsfiddle.net/63K4n/)
But instead of just shrinking the nodes down to a size that fits the screen, I want to increase the height of the container as the width is being decreased to create the additional space necessary for the nodes to fall into without being shrunk.
I played with updating the last few lines of the fiddle to this...
chart.attr("width", targetWidth);
chart.attr("height", Math.round(921600/targetWidth)); //was targetWidth/aspectRatio
(where 921,600 was simply the diameter [960] squared - i.e. the total required space)
But of course although this increases the height of the container correctly, the nodes don't exploit the new space - that's what I'm struggling to figure out - how to change the shape of the bubble chart to fit the new space (if that's even possible!)
If not possible with a standard bubble chart, I'd also be happy to try a static force layout (e.g. http://bl.ocks.org/mbostock/1667139) combined with a resizable example like http://bl.ocks.org/mbostock/3355967. Again the problem is finding a way to reshape the nodes to within the confines of their new container, so I'm guessing I'd have to adapt collision detection to account for the svg container boundaries. And with all that going on I'm pretty sure there'd be a decent lag on a mobile device while you're waiting for the force layout to tick its way to something I can update the page with.
Sorry if that's all a little vague, but I'm really just hoping someone has a general suggestion on an appropriate way to tackle the problem. Huge thanks for any thoughts at all!
When a resize event occurs call a function with:
d3.selectAll('#chart svg').remove()
to clear the current chart then pass the new height/size info into a update function that redraws the chart. Its kinda hard to give you a more specific answer without your code and where you're stuck...but that's generally how I redraw my D3 stuff when data or other groovy things change.
Ok, based on the two fiddles/code pens it looks like
var diameter = 500, // <---Feed new variable here
format = d3.format(",d"),
color = d3.scale.category20c();
var width = 450, height = 2000;
var bubble = d3.layout.pack()
.sort(null)
.size([diameter, diameter])
.padding(1.5);
var svg = d3.select("body").append("svg")
.attr("viewBox","0 0 500 500") //<----and Here
.attr("width", diameter)
.attr("height", diameter)
.attr("class", "bubble");
Changing the diameter and the veiwBox attribute makes everything shrink in the proper proportion. Sorry if i miss understood the question, and if I'm still not getting it. But a redraw function that feeds in new data there based on a change in window should work.
Also, just changing the
var height = XXX
doesn't look like its changing the height, since the
.attr('width',diameter)
is using diameter instead of height.
Anyway, I hope that helps.
I have looked and looked but have not come across anything close to what I'm trying to accomplish.
I am using THREE.js and I have a 3D object, say a human skull. I want to wrap a square grid around its surface while maintaining the unit spacing of the grid lines. Like wire frame but all the line spacing is uniform and straight.
Goal is to have the user easily see the surface length of an object. Real world example. Draw a line from the front of a skull to the back over the top and measure the length of the line.
Any code example, or even a start on the process I could take to solve this problem using THREE.js.
Thanks
you can compute Bounding Box on the object(skull) , and draw a cube using properties of Bounding Box .
object.computeBoundingBox();
// adding cube
var centerX = (object.boundingBox.max.x - object.boundingBox.min.x);
var centerY = (object.boundingBox.max.y - object.boundingBox.min.y);
var centerZ = (object.boundingBox.max.z - object.boundingBox.min.z);
var boundingBoxGeometry = new THREE.CubeGeometry(centerX, centerY, centerZ);
here is a sample fiddle for that : Bounding box fiddle