I am a beginner with D3.js I am stuck with a problem for last few days. below is the code snippet
function zoomed() {
var tiles = tile
.scale(zoom.scale())
.translate(zoom.translate())
();
projection
.scale(zoom.scale() / 2 / Math.PI)
.translate(zoom.translate());
var image = layer
.style(prefix + "transform", matrix3d(tiles.scale, tiles.translate))
.selectAll(".tile")
.data(tiles, function(d) { return d; });
image.exit()
.remove();
image.enter().append("img")
.attr("class", "tile")
.attr("src", function(d) { return "http://111.118.179.198/Data/63699_1600x1200-wallpaper-cb1362414617.jpg_" + 8 + "_" + d[0] + "_" + d[1] + ".png"; })
.style("left", function(d) {return (d[0] << 8) + "px"; })
.style("top", function(d) { return (d[1] << 8) + "px"; });
}
my requirement is before I set the src attribute to img I need to check whether the url is an existing one, if it is a valid existing url then proper value will get set to src otherwise src will be empty.
This would easier to do with jQuery:
var url = "some_url";
$.ajax(url,
{
statusCode: {
200: function() {
image.attr("src," url);
},
404: function() {
image.attr("src", otherURL);
}
}
}
Related
The following code creates a circle and makes it draggable:
HTML:
<svg width='400' height='400'>
<rect width='100%' height='100%'></rect>
<circle transform='translate(259.5,197)' r='10'></circle>
</svg>
JS:
var drag = d3.behavior.drag().on('drag', dragMove)
d3.select('svg').append('circle').attr('transform', 'translate(' + '100px' + ',' + '100px' + ')').attr('r', '5').call(drag)
function dragMove(test) {
var x = d3.event.x
var y = d3.event.y
console.log(test)
d3.select(this).attr('transform', 'translate(' + '200px' + ',' + '200px' + ')')
}
It works. But when I add an argument to dragMove:
'drag', function() { dragMove('test') }
The dragging functionality stops working (console.log(test) outputs 'test', though)
Why is this happening and how to fix it?
https://jsfiddle.net/alexcheninfo/d8doyc9r/4/
It should be this way:
var drag = d3.behavior.drag().on('drag', function(d) {
dragMove(this);//pass the this
})
function dragMove(me) {
var x = d3.event.x
var y = d3.event.y
//operate on me
d3.select(me).attr('transform', 'translate(' + x + ',' + y + ')')
}
working code here
Hope this helps!
I've written some code that highlights (via increased stroke width / change in stroke colour) node visualisations (some circles, some rects) and associated links/nodes when the user 'mouses down' on the node. The highlight disappears when the user 'mouses up'. This all works fine except when the node thats in a clicked state is dragged off of the svg space (technically I've constrained the visualisation to the svg space but obviously the mouse point isn't constrained) and released. The highlight then does not disappear as it should when the mouse button is released.
jsfiddle here - http://jsfiddle.net/hiwilson1/bga0wcLL/.
The method I chose to accomplish the highlighting was to manipulate the underlying objects associated with the clicked visualised node and then update the visualisations, which is all taken care of in the following onmousedown/onmouseup event function:
function highlight(d) {
if (event.type == "mousedown") {
d.highlight = 1;
d.associatedLinks.forEach(function(link, i) {
link.highlight = 1;
link.source.highlight = 1;
link.target.highlight = 1;
})
}
else {
d.highlight = 0;
d.associatedLinks.forEach(function(link, i) {
link.highlight = 0;
link.source.highlight = 0;
link.target.highlight = 0;
})
}
svg.selectAll(".node .shape")
.attr("stroke", function(d) { if (d.highlight == 1) { return "Black"}})
.attr("stroke-width", function(d) { return (d.highlight == 1) ? 3 : 1 });
svg.selectAll(".link")
.attr("stroke", function(d) { return (d.highlight == 1) ? "Black" : "Grey" })
.attr("stroke-width", function(d) { return (d.highlight == 1) ? 3 : 1 });
}
You can listen to the mousemove event and make assumptions thereafter. In the highlight function you will set the value of lastHighlightedNode
e.g.
lastHighlightedNode = null;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
d3.select("body").on('mousemove', function () {
if ((d3.mouse(document.getElementsByTagName('svg')[0])[0] == 0 || d3.mouse(document.getElementsByTagName('svg')[0])[1] == 0) && lastHighlightedNode != null) {
highlight(lastHighlightedNode);
};
});
.....
function highlight(d) {
lastHighlightedNode = d;
....
Demo: http://jsfiddle.net/bga0wcLL/1/
I am creating D3 tree. With the dragging of tree node the auto scroll is not working in Firefox. The auto-scroll with dragging tree node is working in Firefox. It is working fine in Chrome.
HTML code
<div class="row">
<div class="tree-container" id="treeId"></div>
</div>
D3.js code
var nodeEnter = node.enter().append("g").call(dragListener).attr(
"class", "node").attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
}).on("mouseenter", nodeMouseEnter).on("mouseleave", nodeMouseLeave)
.on('click', click).attr('id', function(d) {
return d.nodeId;
});
$('.tree-container').css('overflow', 'auto');
Bootstrap.css
svg:not(:root) {
overflow: visible;
}
var svg_scroll = d3.select("svg").node(),
$parent = $('.tree-container'),
$parent_document_height=$(document),
w = $parent.width(),
h = $parent_document_height.height(),
sL = $parent.scrollLeft(),
sT = $parent_document_height.scrollTop();
var coordinates = d3.mouse(svg_scroll),
x = coordinates[0],
y = coordinates[1];
if (x > w + sL) {
$parent.scrollLeft(x - w);
} else if (x < sL) {
$parent.scrollLeft(x);
}
if (y > sT) {
$parent_document_height.scrollTop(y);
} else if (y < sT) {
$parent_document_height.scrollTop(y);
}
d3.select(this).attr({
x: x - 50,
y: y - 25
});
I have been working with D3.js graph in force layout. I have been using Leap Motion device with javascript language.
My problem is that I'm not able to create Zoom and drag functions which do NOT use default methods written for mouse like d3.behavior.zoom(), d3.behavior.drag().
For example I have this method for Zoom:
function zoom(graph) {
graph.zoom =
d3.behavior.zoom()
.x(graph.x)
.y(graph.y)
.scaleExtent([0.1, 10])
.on("zoom", function () {
if (d3.event) {
graph.scale = d3.event.scale;
graph.translate = d3.event.translate;
graph.scaledNormalLength = graph.defaultNormalLength / graph.scale;
}
d3.select("svg").selectAll(".router").each(function (d) {
if ((graph.scale <= graph.zoomShrinkCondition && d.physicalRole == "router") || (graph.scale > graph.zoomShrinkCondition && d.physicalRole == "cloud"))
if (d.locked == undefined || !d.locked) {
graph.nodeZoom(d);
}
});
//remove tooltip
graph.mouseOut();
//calculate positions - graph will freeze without this
graph.tick();
});
}
and this function for drag
function drag(graph) {
graph.drag =
d3.behavior.drag()
.on("dragstart", function (d) {
d.fixed = true;
d3.select(this).classed("fixed", true);
d3.event.sourceEvent.stopPropagation();
})
.on("drag", function (d) {
//remove tooltip
graph.mouseOut();
//compute coordinates of dragged node (NOTE: if some coordinates are wrong, it is probably because of simulate() function)
d.px += d3.event.dx / graph.scale;
d.py += d3.event.dy / graph.scale;
//compute coordinate of children if they are not hidden
if (d.physicalRole == "router") {
setNodePosition(d, d3.event);
}
//compute coordinates of children if they are hidden
if (d.physicalRole == "cloud") {
d._children.forEach(function (ch) {
ch.px += d3.event.dx / graph.scale;
ch.py += d3.event.dy / graph.scale;
setNodePosition(ch, d3.event);
});
}
graph.getForce().resume()
});
function setNodePosition(node, event) {
if (node.children)
node.children.forEach(function (ch) {
setNodePosition(ch, event);
ch.px += event.dx / graph.scale;
ch.py += event.dy / graph.scale;
})
}
}
Is there any way how to create this methods without calling d3.behavior functions? Thanks a lot for yours ideas.
Have some code like:
var el = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
var c = this.chart;
el.setAttribute('x', c.x + c.padding + 'px');
el.setAttribute('y', c.y + c.padding + i * (b.height + b.margin) + 'px');
el.setAttribute('width', model.value * c.scale + 'px');
el.setAttribute('height', b.height + 'px');
el.classList.add('bar');
this.svg.appendChild(el);
Any options to make it look not as ugly? There is a chance that can be more attributes...
Time to use a function? Something like:
function setAttributes(el, attrs) {
for(var key in attrs) {
el.setAttribute(key, attrs[key]);
}
}
And call it as:
setAttributes(elem, {"src": "http://example.com/something.jpeg", "height": "100%", ...});