I have rendered a complex canvas with several layers of Fabric.js Groups, PathGroups and Paths. Many of the elements are selectable and when they are selected they should be highlighted.
Right now I'm rendering all the possible highlights together with the foundation, before the selectable objects. Really what I would prefer is to render the highlight simply when someone clicks on a Group or Path. For this I would need to insert the highlight below the selection, so is there a way of inserting a Path before a Group or another way of doing this?
Please notice, I'm not looking for element.sendBackwards(true); because there is not always the same amount of elements that the highlight should be bellow.
I found out that it is possible to get the index of an element and move an element to a specific index! Problem solved.
var index = canvas.getObjects().indexOf(group1);
canvas.moveTo(group2, index);
Related
I want to update a circle and text element at the same time. I was able to make it work with only the circle:
https://plnkr.co/edit/FckQcVd1EkYLoZggmJN4
However, when I try adding a wrapping g to contain the circle and text it doesn't update properly.
https://plnkr.co/edit/EtL11O5qQph0xAeu88mu?p=preview
Any insight how to fix it?
i'm struggling to understand the following behaviour: i have two maps (based on topojson-data, visualised through d3), and on mouseover over certain parts of map1, the corresponding parts of map2 should light up. i got it to work with changing the style (opacity or fill), but now i wanted to highlight the borders of each map-part.
as seen for instance here one needs to move the specific path to the front to make all the borders visible. this is no problem for the area where i move the mouse across (using this), but when i select the corresponding part of the other map, it works one time and after that other parts get selected - so my guess is something is messing with the selection.
here is the code:
.on("mouseover",function(d){
var old=d.properties.iso; //this is the identifying number of the map-part(s)
sel=svg2.selectAll("path")
.data(datastore2015.features)
.filter(function(d){return d.properties.iso==old;})
.node(); //here the corresponding part(s) get filtered
d3.select(sel.parentNode.appendChild(sel)).classed("high2",true); //and this moves it to front and highlights the borders
on mouseout, it just resets:
.on("mouseout",function(d){
svg2.selectAll("path").classed("high2",false);
when i log the data to the console it seems that each mouseover moves +1 entry through the dataset, starting by the first entry the mouse moved over. i could not figure out why this happens and how to avoid it.
i'd appreciate any ideas you could give me, mainly i'd like to understand what's going wrong and why.
thanks
so i found my error, calling the data-variable once again seems to have messed things up - somehow i was under the impression that i need it, but it works just fine this way:
sel=svg2.selectAll("path").filter(function(d){return d.properties.iso==old;}).node();
d3.select(sel.parentNode.appendChild(sel)).classed("high2",true);
sorry for the bother, i didn't see this possibility before.
Im using this great article to produce a venn diagram with D3.
http://www.benfrederickson.com/venn-diagrams-with-d3.js/
It looks great but on occasion I get bubbles overlapping the the labels become hidden. Is there a way to make sure the text element is always on top? (see the picture below.. label A needs to be on top of circle B.
I found this good article but im struggling in how to implement this in the venn.
How can I bring a circle to the front with d3?
You should grab the latest code from master: this commit should fix the issue you had there https://github.com/benfred/venn.js/commit/4cb3bbef65b5b3c3ce02aee7d913e8814e898baf
Instead of having the 'A' label be overtop of the 'B' circle - it willnow move the label so that its in the certain of the 'A' region that isn't overlapped with 'B'. Some details are in this issue here: https://github.com/benfred/venn.js/issues/18
You might find it easier to work in actual layers. You can use g elements to create them. For example:
var lowerLayer = svg.append('g');
var upperLayer = svg.append('g');
Now anything you append to upperLayer will appear above anything you append to lowerLayer because the two g elements have been added to the DOM and are in a specific order.
Also check out this answer I wrote up for a similar question.
I have the following json and I need to create a grid and also above the grid need to show vertical lines based on the values :
var arr = [];
arr= [
{"Measure":"Air Pollution","Rank":"1","Value":"15.5"},
{"Measure":"Water Pollution","Rank":"2","Value":"13.5"},
{"Measure":"Soil Erosion","Rank":"3","Value":"10.5"}
]
Now I need to create a grid and above the grid, need to create vertical bars based on the "Value". There will be 3 bars created since there are 3 Values. Now when 1st row in the grid is selected, the first vertical bar needs to be highlighted . Similarly, when the 1st vertical bar is selected, the 1st row in the grid to be selected. Creating the grid is not a problem since I am using KendoUI grid but to create the vertical bars and the selection is the one where I am stuck . Any views ?
Thanks.
Based on #Bogdan M.'s suggestion on using div elements, I've set up a jsFiddle demonstrating vertical bars built using jQuery. It relays on the input of values as an array of numbers, and converts those to DOM elements, setting their height accordingly.
This demo can be very easily updated to use the OP's supplied data structure, and selection behavior functionality can be added as well.
This final version (contains the complete solution, both for building the component and for assigning it with selection behavior) can be seen in the full demo on jsFiddle.
All that's left now is to assign handlers for the selection functionality - as cell / row listeners - to the KendoUI grid.
I see that you aim to visualize your data as a bar-chart. If so, don't re-invent the wheel. there are a lot of good JS libraries designated for that purpose.
I've had a good experience using HighCharts, try it out.
Disclaimer: This may be an overkill, but is a suited solution should the component be generic (for future compatibility with flexible data)
I am trying to design a little game using JS, and what I want it to do is make a random number say... 1-100 and then randomly scatter the dots (I used periods with the font size at 200) on the screen. By random, I just mean that I don't want them to be arranged in rows and columns. What I have so far achieves all but scattering the dots, so how do I do that?
var i=0;
var inhtml="."
var num=10
function exe(){
i=Math.floor(Math.random()*100)
//alert(i)
while (i<=100){
document.getElementById("dot").innerHTML = inhtml + "."
inhtml = document.getElementById("dot").innerHTML
if (inhtml.length>num){
inhtml=document.getElementById("dot").innerHTML+"<br />"
num=num+20
}
i++;
}
}
Instead of using a single element containing several periods at a large size, I'd recommend using separate elements for each dot. Then, (besides not having to use 200px periods), you can use CSS to position each element however you want. I have an example here.
Edit: I don't know what the exact problem with getting the dots to not overlap you're having is, but you basically need to do this:
First you pick a position. Then, you check that position against all the other positions (which you'd probably want to do using Manhattan distance). If the point is valid, you use that point and add it to the array of taken positions. Otherwise, go back to the first step.
You may want to check your syntax errors before progressing; I do not know whether you copied all of your code, but you are missing semicolons at the end of your lines. Syntactical issues aside, one possible way to achieve what you describe would be to assign the x- and y-coordinate of each point to a random number. Examination of the code reveals that only the initial value of i is assigned to the value of random(). Incrementing i will make the coordinates of future points dependent on the initial value of i, which is something you may want to take into account. But nowhere in your code do I see you changing the position of the each element based on the values you generate.
I strongly suggest that you use the HTML5 Canvas instead of attempting to move HTML elements; the latter would be cumbersome and lead to messy and inefficient code. If you still want to stick to the method you are trying to use now, check to make sure that the CSS display property is set to block for these elements. You are using the getElementById() method, which is not very useful in this circumstance, since IDs are unique in HTML files. I would suggest using getElementsByTagName() and using those returned elements with a specific class attribute instead.
You might want to look at the HTML 5 Canvas. It allows you draw arcs (aka circles) In any postion, size, and fill color.
Look here for details, here for a tutorial, and here for a demo.
To not be bound by the browser's text layout constraints, you pretty much have to absolutely position your dots:
<div style="position: absolute; top: {random number}; left: {random number}">.</div>