d3.js - masking shapes to create transparent sectio - javascript

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

Related

My d3 js chart brushed and zoomed is not working for background

My d3 js chart brushed and zoomed is not working for background.
Inside my brushed function I have below code, while brushing and zooming it should reflect the orange background.
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 calculated based on new scale dynamically.
code sandbox - https://codesandbox.io/s/quizzical-bhabha-4ullr?file=/src/TimelineChart.js
after brushing and zooming -

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

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

Fill rect with pattern

I am using d3.js for graph. at some point i have to show data with some special part of graph for example if the values is cross some boundary then show that part with filling pattern. for more clear is there in and image.
i get the rect part that cross the boundary but how can i fill it with this pattern?
any css or canvas tricks?
Note : this image is just an example not the real one
How about this:
Live Demo
JS
var svg = d3.select("body").append("svg");
svg
.append('defs')
.append('pattern')
.attr('id', 'diagonalHatch')
.attr('patternUnits', 'userSpaceOnUse')
.attr('width', 4)
.attr('height', 4)
.append('path')
.attr('d', 'M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2')
.attr('stroke', '#000000')
.attr('stroke-width', 1);
svg.append("rect")
.attr("x", 0)
.attr("width", 100)
.attr("height", 100)
.style("fill", 'yellow');
svg.append("rect")
.attr("x", 0)
.attr("width", 100)
.attr("height", 100)
.attr('fill', 'url(#diagonalHatch)');
Results
To change the color would be simple, just a conditional if statement. Here's an example i've used before:
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3.5)
.style("fill", function(d) { // <== Add these
if (d.close >= 50) {return "red"} // <== Add these
else { return "black" } // <== Add these
;}) // <== Add these
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); });
To add a pattern would be a little more involved as you first have to add the defs element to your SVG and then add your pattern to it
//first create you SVG or select it
var svg = d3.select("#container").append("svg");
//then append the defs and the pattern
svg.append("defs").append("pattern")
.attr("width", 5)
.attr("height", 5);

Categories

Resources