I have an svg element, where height and width both equal 100%, with a defined viewbox attribute. The svg contains a range of polygon objects. On clicking a polygon, I want it to expand to fill the entire svg (read: the entire screen).
I can access the svg element dimensions and resize the polygon accordingly, but due to the viewbox attribute, plotting the width comes up short.
Is there any way to calculate the x dimension within the viewbox which corresponds to the far right edge?
The maximum X value you want will be the maximum X of the viewBox, which you can calculat by adding the viewBox minX + the viewBox width.
Related
I am scaling (resizing) a div on mousemove, I am also maintaining aspect ratio of the div. I can scale it as I wanted. I need to calculate the width and height of a scaled div.
Suppose if I scaled a div by some value d in picture, I need to calculate the width and height of div.
Also the div may already be in a rotated position, I have the angle as well.
I dont want values of getBoundingClientRect().
I think the problem is more mathematical.
I am building a d3js chart that plots some dots on a gradient scale of agree to disagree. I need it to be able to zoom and pan and I have all of that working except for a rectangle holding a linearGradient. The gradient zooms just as I need it, but it scales up both horizontally AND vertically, expanding past the original 20px height:
Or shrinking excessively:
I tried to use a clip path which is clearly not working, it seems that the clip path scales with the gradient. How can I clamp the rectangle to the axis and keep it the same size?
Here is my block
Thank you!!
There are two primary challenges from what I can see:
the rectangle filled with the gradient scales on the y axis as you note.
the clip path isn't working as intended.
Let's drop the clip path, that'll make things a bit easier. Secondly, let's not scale the rectangle at all when we zoom (we can keep the translate that is applied though).
Now that I've destroyed what we had, let's build it back up.
Instead of scaling the rectangle with transform(scale()) let's modify its width directly. If d3.event.transform.k is the factor at which we were scaling (both x and y), let's just modify the width of the rectangle. Instead of:
gradientScale
.attr("transform","translate("+d3.event.transform.x+","+(height- spacer*3)+")scale("+d3.event.transform.k+")");
Let's use:
gradientScale
.attr("transform", "translate( " +d3.event.transform.x+ " , " + (height - spacer*3) + ")")
.attr("width", width * d3.event.transform.k);
By removing the scaling, the above won't warp any coordinates, which won't lead to stretching of the y axis. It doesn't modify any y coordiantes, so the bar stays where it is height wise with the same height.
It does modify the width - by the same amount we were scaling it before (the rectangle's width at k = 1 is width). This achieves the stretching of the scale as we zoom in. The x translate factor is unchanged.
Here's a bl.ock of the modified code.
My initial thought before looking closely was to try a completely different approach. So, for comparison, here's a completely different approach modifying the axis itself.
I am new and I am working using this map. I have a div container called: #statesvg where I want the map to adapt to its size. but this one is cut.
in which part of the code can I modify the height and width of the map?
Thank you very much
http://bl.ocks.org/michellechandra/0b2ce4923dc9b5809922
//I get the actual size of the div
var width = document.getElementById('statesvg').offsetWidth;
var height = document.getElementById('statesvg').offsetWidth;
.
.
.
Same code
Other than scaling the entire svg (or portions of it), you can change the projection. The projection determines how much space your features occupy, no matter what the svg size. The easiest method would be to use projection.fitSize() in d3v4+:
projection.fitSize([width,height],feature);
Where width and height are your svg dimensions, and feature is your geojson feature collection (json in your example, not json.features, it takes an object, not an array). This method sets the scale and translate of the projection so that your features are centered and scaled appropriately for your svg/canvas.
Alternatively, given that all fitSize does is set the translate and scale of a projection, you could modify these attributes directly to set the appropriate scale and translate. Since your example centers the projection with [width/2,height/2] this is will already adapt to provided dimensions. Consequently, all you need to do is set the scale. If the scale value of 1000 is appropriate for a width of 960 and height of 500, then a scale of 2000 will be appropriate for a width of 480 and a height of 250. With this we can just use some simple math:
var scale = 960/width*1000; // assuming that width is always limiting
If width or height could be limiting, find the scale value for both using the above logic and take the higher scale value. Then apply the scale to the map the same as your example does now: projection.scale(scale);. This lets you scale the map easily, and in d3v3 as well (like your example block).
I have a D3.js component and it renders a chart dynamically based on the data received. My problem is that when I receive huge sets of data my component grows (I have predefined sizes for each visual element) and I don't want to refactor my component and compute the sizes for all my elements in order to fit the screen.
SVG attribute preserveAspectRatio indicates whether or not to force uniform scaling.
xMinYMin - Force uniform scaling.
Align the of the element's viewBox with the smallest X value of the viewport.
Align the of the element's viewBox with the smallest Y value of the viewport.
<svg preserveAspectRatio="xMinYMin" viewBox="0 0 300 100"></svg>
Note viewBox as opposed to width and height attributes.
I need to do something like this:
This may look quite easy, but there are some requirements:
- the width of the containing div should depend on the text length (is it possible at all in CSS?)
- all circles should be positioned randomly - this is the most diffucult part for me.
As I'm using border-radius for creating circles (setting height, width and border-radius of 50%) I try to create some kind of grid in JavaScript where I iterate through each element and get its dimensions. Then I get the position of previous element (if any) and add them to the current element dimensions. Additionally, adding some margins will help avoid collisions. Is it correct approach?
I'm just looking for a suggestion how to solve my two issues.
Circles that scale based on size of content.
This is something you will need to solve first, because you wont be able to place them anywhere without first knowing their dimensions.
Naturally the size of a DIV expands first by width, then by height. That is, the maximum width of a container must first be utilized before moving on to the height constraint. Because of this, making a circle scale with equal radius may prove to be quite difficult without using a relative averaging.
Relative averaging is finding the average dimensions of your height / width based of the exhisting area of the contianer bounding your content. For example:
The width and height of the DIV bounding your content can be detected with javascript. Let's say youve discovered those properties too be 200px x 20px respectively.
Your total area is width * height so 4000px; But we are trying to acheive a square so we can apply rounded corners and form a rounded circle. We want to find dimensions of a rectangle that will be equal to the same area and then apply those new dimensions.
To acheive the same area with an equal width * height you can do something like:
√ 4000 = 63.2455532
Thus: 63.2455532 x 63.2455532 = 4000
Random placement of DIVs, and avoid collisons between DIVs.
After finding dimensions, you will be able to use a rand on your (X,Y) coordinates for the placement. Push these coordinates and radius onto an array. Use recursion too place the remaining circles on collsion failures. A collision failure would come from an element that has overlapping (X,Y)+radius relative too elements in the array that were pushed successfully.