Rotate objects in D3.js - javascript

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>

Related

How to use scaleTime to horizontally position a background rectangle

I want to have the d3 js chart with a different background rectangle based on some timestamps.
var orangeBack = svg
.append("rect")
.attr("x", margin.left + 0)
.attr("y", margin.top)
.attr("height", containerHeight - 120)
.attr("width", 200)
.style("stroke", bordercolor)
.attr("fill", "orange")
.attr("opacity", 0.2)
.style("stroke-width", border);
I have a d3 js chart created per below:
My code sandbox - https://codesandbox.io/s/quizzical-bhabha-4ullr?file=/src/TimelineChart.js
Right now I have given 200 in width but this will be my timestamp in x scale.
.attr("width", 200)
How I can use x scale for horizontally positioning the rectangle by timestamp ?
.attr("width", xScale()) // or XDomain something..
I tried to use scale e.g. but it's not working.
var orangeBack = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
//.attr("x", margin.left + 0)
.attr("x", function(d){return xScale(d.startTime)})
.attr("y", margin.top)
.attr("height", containerHeight - 120)
// .attr("width", 200)
.attr("width", function(d){return (xScale(d.startTime) - xScale("1568283720049"));})
.style("stroke", bordercolor)
.attr("fill", "orange")
.attr("opacity", 0.05)
.style("stroke-width", border);
Any reference will be helpful. Thanks..
I am trying to follow something like this.. How to add background shading to D3 line chart
This is how I am trying to achieve this. Let me know if anything better we can do.
var orangeBack = svg
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", margin.left)
// .attr("x", function (d) {
// return xScale(1568283720049);
// })
.attr("y", margin.top)
.attr("height", containerHeight - 120)
// .attr("width", 200)
.attr("width", function (d) {
return xScale(1568283720049) - xScale(1567851720049) + 10;
})
.style("stroke", bordercolor)
.attr("fill", "orange")
.attr("opacity", 0.05)
.style("stroke-width", border);
currently I have given the timestamp directly e.g. xScale(1568283720049) this can be done dynamically.
code sandbox - https://codesandbox.io/s/quizzical-bhabha-4ullr?file=/src/TimelineChart.js

SVG element not being responsive - when screen resized

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%; }

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 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