SVG element not being responsive - when screen resized - javascript

I have a map-container which shows world map, that is supposed to be responsive but it does not work when I run it and resize the page, I cant find whats the issue. what it is expected when screen is resized. here's my code
var tooltipMap = d3.select("body")
.append("div")
.attr("class", "map-tooltip shadow")
.style("opacity", 0);
var projection = d3.geo.mercator()
.center([0, 62 ])
.scale(150)
.rotate([0, 0]);
var svg = d3.select("#map-container").append("svg")
.attr("width", width)
.attr("height", height)
.attr('viewBox', "0 0 "+(width)+" "+(height))
.attr('preserveAspectRatio', 'xMinYMid')
.attr("class","chart");
var path = d3.geo.path()
.projection(projection);
var defs = svg.append('svg:defs');
defs.append("svg:pattern")
.attr("id", "bgImg")
.attr("width", 6)
.attr("height", 6)
.attr("patternUnits", "userSpaceOnUse")
.append("svg:image")
.attr("xlink:href", '../assets/img/map-tile.png')
.attr("width", 6)
.attr("height", 6)
.attr("x", 0)
.attr("y", 0);
var g = svg.append("g")
.attr("width", width+160)
.attr("height", height);
// load and display the World
d3.json("om.json", function (error, topology) {
g.selectAll("path")
.data(topojson.object(topology, topology.objects.countries).geometries)
.enter()
.append("path")
.attr("fill", "url(#bgImg)")
.attr("d", path);
});
<script src="js/d3.v3.min.js"></script>
<div id="map-container"></div>
Basically as of what appears,
.attr("class","chart");
does not work, wondering why ?
Solution -
CSS - strange as hell, but this was the issue my css was not placed perfectly. !!! Facepalm !!!
.chart{ width:100%; height:100%; }

Related

Rotate objects in D3.js

I'm trying to rotate rectangles according to some data. With, the following code, the rotation applies to the whole line. How can I get each "rect" to have his own rotation applied, keeping them on the same line?
let canevas = d3.select("body")
.append("svg")
.attr("width", 1000)
.attr("height", 1000);
let rectangles = d3.select("svg")
.selectAll("rect")
.data([10, 20, 30, 40])
.enter()
.append("rect")
.attr("x", (d, i) => (i * 30) + 30)
.attr("y", 20)
.attr("width", 20)
.attr("height", 20)
.attr("transform", (d) => `rotate(${d})`);
That's the normal behaviour of rotate, since the rotate function of the translate attribute rotates the elements around the origin of the coordinates system (0,0).
An easy solution is setting the positions in the same translate:
let canevas = d3.select("body")
.append("svg")
.attr("width",300)
.attr("height",100);
let rectangles = d3.select("svg")
.selectAll("rect")
.data([10,20,30,40])
.enter()
.append("rect")
.attr("width",20)
.attr("height",20)
.attr("transform", (d,i) => `translate(${(i*30)+30},30) rotate(${d})`);
<script src="https://d3js.org/d3.v4.min.js"></script>

d3.js transparent shape tesselations - complex subtractions

Expanding on this first example. I am interested to expand the solutions.
1 - make this more responsive - scaling wise
2 - make the subtraction more complex
3 - ensure the svg fits over the width of the banner.
d3.js - masking shapes to create transparent sectio
So here is the goal
this is the code as it is - I've given it a little clean up.
http://jsfiddle.net/NYEaX/1521/
function maskMaker(el) {
var backcolor = $(el).data("color");
var backopacity = $(el).data("opacity");
// Set the main elements for the series chart
var svgroot = d3.select($(el)[0]).append("svg");
var mask = svgroot
.append("defs")
.append("mask")
.attr("id", "myMask");
mask.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", "1200px")
.attr("height", 500)
.style("fill", "white")
.style("opacity", backopacity);
mask.append("circle")
.attr("cx", 550)
.attr("cy", 250)
.attr("r", 150);
var svg = svgroot
.attr("class", "series")
.attr("width", "1200px")
.attr("height", "500px")
.append("g")
.attr("transform", "translate(0,0)")
var rect = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", "1200px")
.attr("height", 500)
.attr("mask", "url(#myMask)")
.style("fill", backcolor);
}
//var el = $(".mask"); //selector
$('[data-role="mask"]').each(function(index) {
console.log("test")
maskMaker(this);
});

d3.js - masking shapes to create transparent sectio

I am interested in learning how to create a transparent mask with d3.js.
http://jsfiddle.net/59bunh8u/35/
This is where I am up to - how would I create a subtraction mask on the red rectangle - also how could you style the red rectangle to take on more of a multiply style property?
$(document).ready(function() {
var el = $(".mask"); //selector
// Set the main elements for the series chart
var svg = d3.select(el[0]).append("svg")
.attr("class", "series")
.attr("width", "800px")
.attr("height", "500px")
.append("g")
.attr("transform", "translate(0,0)")
var rect = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 500)
.attr("height", 500)
.style("fill", "red")
.style('opacity', 0.75)
var rect = svg
.append("circle").attr("cx", 250).attr("cy", 250).attr("r", 125).style("fill", "white");
});
You need an SVG mask. Feel free to play with it to tweak the parameters:
var mask = svgroot
.append("defs")
.append("mask")
.attr("id", "myMask");
mask.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 500)
.attr("height", 500)
.style("fill", "white")
.style("opacity", 0.7);
mask.append("circle")
.attr("cx", 300)
.attr("cy", 300)
.attr("r", 100);
Modified example: http://jsfiddle.net/59bunh8u/40/
See also SVG clipPath to clip the *outer* content out

d3.js zoom without overflow

I have a force directed graph with fixed nodes. I have allowed zoom in the graph :
var force = d3.layout.force()
.on("tick", tick);
var zoom = d3.behavior.zoom()
.scaleExtent([0, 50])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(zoom);
var graphGroup = svg.append("g")
.attr("height", graphHeight)
.attr("width", graphWidth)
.attr("class", "graph-group")
.attr("transform", "translate(" + margin + "," + margin + ")");
graphGroup.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", graphHeight)
.attr("class", "graph-limit")
.attr("width", graphWidth);
...
function zoomed() {
graphContainer.attr("transform", "translate(" + t + ")scale(" + d3.event.scale + ")");
}
I would like to limit the zoom (scale and translation) of the graph within the rectangle with class "graph-limit".
I've tried to put overflow:hidden in style, but without success.
Any idea ?
EDIT :
Here a jsfiddle
http://jsfiddle.net/Lxc43v8d/20/
This is how you can do it.
Use clip path with dimension exactly same as that off the rectangle:
//make a clip path
svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("id", "clip-rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", graphHeight)
.attr("width", graphWidth);
To the group which holds the rectangle all nodes and links add the clip path like this
var graphGroup = svg.append("g")
.attr("clip-path", "url(#clip)")//add the clip path
.attr("height", graphHeight)
.attr("width", graphWidth)
.attr("class", "graph-group");
Working code here
Hope this helps!

D3 fill shape with image using pattern

I'm trying to create a circular avatar with D3.js but I cannot get my image to show up in my circle. I'm using a svg pattern def to attempt to fill the circle with an image.
Can anyone tell me what I'm doing wrong below? Thank you.
var config = {
"avatar_size" : 48
}
var body = d3.select("body");
var svg = body.append("svg")
.attr("width", 500)
.attr("height", 500);
var defs = svg.append('svg:defs');
defs.append("svg:pattern")
.attr("id", "grump_avatar")
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("patternUnits", "userSpaceOnUse")
.append("svg:image")
.attr("xlink:href", 'images/avatars/avatar_grumpy.png')
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("x", 0)
.attr("y", 0);
var circle = svg.append("circle")
.attr("cx", config.avatar_size)
.attr("cy", config.avatar_size)
.attr("r", config.avatar_size)
.style("fill", "#fff")
.style("fill", "#grump_avatar");
"Fill" is a style property, you have to use CSS url() notation for the reference to the pattern element.
Once you fix that, you'll discover that you also have your sizes wrong -- unless your intention was to have four copies of the avatar tiled in the circle!
P.S. I would normally have left this just as a comment, and marked this for closure as a simple typo, but I wanted to try out Stack Snippets:
var config = {
"avatar_size" : 48
}
var body = d3.select("body");
var svg = body.append("svg")
.attr("width", 500)
.attr("height", 500);
var defs = svg.append('svg:defs');
defs.append("svg:pattern")
.attr("id", "grump_avatar")
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("patternUnits", "userSpaceOnUse")
.append("svg:image")
.attr("xlink:href", 'http://placekitten.com/g/48/48')
.attr("width", config.avatar_size)
.attr("height", config.avatar_size)
.attr("x", 0)
.attr("y", 0);
var circle = svg.append("circle")
.attr("cx", config.avatar_size/2)
.attr("cy", config.avatar_size/2)
.attr("r", config.avatar_size/2)
.style("fill", "#fff")
.style("fill", "url(#grump_avatar)");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Categories

Resources