I'm using d3js along with AngularJS in an iPad webapp. When running on Safari/Chrome everything looks good, but when running on the iPad the images I append with d3js do not show.
Here is my JS:
directive('zoomScreen', [function() {
return{
restrict: 'E',
link: function(scope, elm, attrs) {
var width = 1024,
height = 660;
var offset= [{"xoff":-20,"yoff":10,"swipe_class":"left"},{"xoff":-80,"yoff":0,"swipe_class":"right"},{"xoff":0,"yoff":-80,"swipe_class":"left"},{"xoff":50,"yoff":0,"swipe_class":"left"}];
var svg = d3.select("svg")
.attr("width", width)
.attr("height", height)
.append("g");
var back = svg.append("image")
.attr("class", "logo")
.attr("x", 375)
.attr("y", 175)
.attr("xlink:href", "../images/brain-back.png")
.attr("height", 300)
.attr("width", 300)
.style("fill", "transparent")
.style("stroke", "black")
.style("stroke-width", 1)
.on("click", outClicked);
var image = svg.append("image")
.attr("class", "logo")
.data([offset[0]])
.attr("x", 485)
.attr("y", 175)
.attr("height", 90).attr("width", 90)
.attr("xlink:href", "../images/image1.png")
.style("stroke", "black")
.style("stroke-width", 1)
.on("click", clicked);
var image2 = svg.append("image")
.attr("class", "logo")
.data([offset[1]])
.attr("x", 545)
.attr("y", 255)
.attr("height", 90).attr("width", 90)
.attr("xlink:href", "../images/image2.png")
.style("stroke", "black")
.style("stroke-width", 1)
.on("click", clicked);
And my HTML:
<zoom-screen>
<svg class="accel"></svg>
</zoom-screen>
The strange thing is the iPad knows there are elements there, because it allows me to highlight and click them, but it doesn't show the images.
Turns out all I had to do was convert image to base 64 string. So I just set the string as a var and had my xlink:href pointing to the var instead of the location. ex:
var image1 = "data:foobase64stringhere";
.attr('xlink:href',image1)
Related
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
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);
});
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
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>
var w = 725;
var h = 500;
var padding = 20;
var svgcanvas = divElem.append("svg:svg")
.attr("width", w)
.attr("height", h);
The path that I wish to restrict the region to, but the element has disappeared
svgcanvas.append("svg:clipPath")
.attr("id", "clipper")
.attr("d","M -200,0 A200,200 0 0,0 500,0 L -200,0")
.attr("transform", "translate(220,400) scale(1, -1)")
.style("stroke-width", 2)
.style("stroke", "steelblue")
.style("fill", "yellow");
Do not wish the line to go beyond this path but the element has disappeared
var myLine = svgcanvas.append("svg:line")
.attr("x1", 40)
.attr("y1", 50)
.attr("x2", 450)
.attr("y2", 150)
.attr("clip-path", "url(#clipper)")
.style("stroke", "rgb(6,120,155)");
Do not wish the Circles to go beyond this path, but element has disappeared
var circle = svgcanvas.selectAll("circle").data(jsoncirclehigh);
circle.enter().append('circle')
.attr('opacity',0)
.attr("cursor","pointer")
.on("mouseover", function(){d3.select(this).style("fill", "red");})
.on("mouseout", function() {d3.select(this).style("fill", "orange");})
.attr("clip-path", "url(#clipper)")
.attr("cx", function(d) {return d.cx;})
.attr("cy", function(d) {return d.cy;});
Look at this example, I apply a ClipPath and a line with a setInterval:
demo