I am working on a force layout in D3v4 which needs to update its nodes over time. I've followed Adding new nodes to Force-directed layout (D3v2) and mbostock's block (D3v3), but I'm not quite sure how to achieve the same affect in D3v4. Here's what I've got so far:
http://bl.ocks.org/danielcompton/2189f9571e306f3084e5c2a913002eaf
The problem that I'm seeing is that when I add the same data to the force layout a second time, it resets the nodes positions, and also seems to reset them with less alpha, so they don't fully expand until they are clicked. Do I need to set the alpha as well when I'm updating the nodes and links?
I've seen D3 v4: Update force layout and this is a different (but related) question.
Does anyone have any tips on how to achieve this in D3 v4?
It seems the simulation is starting off with a low alpha value the way you handle it. If I just reset the alpha value with .alpha(1) inside the handleGraph it does the trick on my side:
simulation
.nodes(graph.nodes)
.on("tick", ticked)
.alpha(1);
after you added the data , you can usesimulation.alpha(1).restart() to restart simulation layout.
Related
I would like to render DOM elements (which im otherwise using React for) onto (for example) a plane in a 3D (WebGL -> Three.js -> Three Fiber (??? so far best way to go about it as im figuring?)) environment.
So basically Id have my containing my entire app lets say rendered, as is traditional, into "root" element. Except I want to inject a layer in that utilizes Three Fiber to render and everything I might want my site (or even just a particular component) to contain onto this plane. Allowing one to make a react site as normal and behind the scenes (probably in index.js or intermediate file) would instead of being rendered "flat" against the screen i could "tilt" the entire site, give it opacity, maybe have multiple webpages all able to be shuffled like cards, sides of a dice, w/e tf.
If anybody has any suggestions im struggling with how one could go about this.
Im worried i might have to get kind of low-level (which im not totally against), but was hopeful there was some support for something of this nature. So far ive tried even having simple elements like an image element inside a material (element - via three fiber) or inside the mesh element (where the material would go) to no avail. Im just beginning to get my hands dirty but google hasnt availed me much for this project, so I turned to good ol' stack overflow for my first personal request! 🤯 😲 👹 !
Thanks in advance so much for your time and consideration - cheers,
John Thummel
this is possible using drei/Html. some impressions:
https://twitter.com/0xca0a/status/1398633764931178498
https://twitter.com/0xca0a/status/1407758860203573251
We have an application where we need to plot ~13K+ markers on a map depending on the users current filters. I have found that react-leaflet does not handle this many markers very well. I even offloaded all of the popup data to a separate query on popup to reduce the initial data load, but to no avail.
I did find that using clustering does help improve the performance, so I have enabled that (even though it is not in the following example code). But even with clustering, on the initial map load a user might have to wait 20 seconds for the map to render with the markers, but the actual data fetch from the GraphQL API is less than a second.
I am trying to find a way to only fetch the markers that are present within the bounding box of the page. I am doing this successfully, but the problem now is that all of the markers flash (re-render) when the map is moved/zoomed even if the new bounds is just a subset of the original.
CodeSandbox: https://codesandbox.io/s/graphql-markers-t409f?file=/src/App.js
Is there a way for react-leaflet to only re-render the markers that are new and not all the markers? I am providing the unique id of the marker from the api to the Marker component key field, but that doesn't seem to provide any improvements.
I am thinking that maybe the best way to handle it would be to do something to manage the map bounds to the min east, max west, max north, and min south and only refetch if the new bounds are outside of the currently fetched area. This along with a 10-20% over area fetch to not refetch if the map is only very slightly moved in any direction.
Note: I am not guaranteeing that this GraphQL backend will be available after the question has been answered. There is a 1Mb/Day data transfer limitation on this backend in case this question blows up and you cannot see the markers. See the README in the codesandbox for steps to setup the backend for free online in under 2 minutes.
Some related issues that may help if no other solution is found:
Limit rendering Popups
Not the same question as Plotting 140K points in leafletjs. I am specifically looking for an answer to how it might be possible to update markers to remove markers not in new data fetch and add new markers not present in previous data fetch without re-rendering existing markers.
Take a look at the example code and you will see the markers flash as they all get re-rendered when the new data is fetched. This might lead to a better hybrid between performance and UX as I really don't want to use the CircleMarker and I already added clustering but still have existing lag.
You should use the React Canvas Markers plugin. The poor performance is because the default behavior is to create an individual div for each marker. This avoids the performance hit by writing your map and markers to a canvas element. Here's a working example from SO.
I've got this sort of general question when it comes to requiring images in React Native. I've got this application that uses the same little red x and green check mark for form validation 6-8 times in a single form component. How it stands right now, I have a require in every 'source' prop when used.
Is it best practice to require the image once at the top of the component as a variable and just use the variable 6-8 times instead of the calling require for each one of them?
Yes, requiring it once at the top is far superior.
But hey, you can go even further. If this is an icon you need to use across the app, it might be worth making a very very simplistic component that renders this image. It's easier to reference <GreenCheck/> than to require an image and stick it into an img tag repeatedly.
So yes, apparently it is possible to have long grid with lots of rows built with angular. But then a problem comes with data updates.
You see if I just get all (let's say 10 000 rows) and render them in my grid - that works. It just takes a few seconds initially. And
a) I don't have all the date up front
b) I need the grid to be responsive immediately.
I can just do that with throwing let's say only 100 rows at the beginning, and then slowly update data as it becomes available. And that turns out to be the problem. Everytime you push new rows into $scope.data - it blocks UI. So I need to be smart about these updates.
Maybe I should set an interval and update the data only every few seconds? That seems to be not working
Maybe I should somehow watch for mouse movements and once it stops moving - start/resume adding rows, once mouse-movement detected seize adding rows and wait for another chance? - What if user never stops moving the mouse? (say some sort of a psycho)
Experimenting with _.throtle and _.debounce didn't get me anywhere.
You guys have any ideas?
UPD: here's a crazy one: what if? instead of waiting till angular updates the DOM, create entire DOM structure in memory, right before the digest cycle (with no data) and then insert that HTML chunk (that would be faster, right?) And after that let angular do its magic, data should appear. Would that work?
You are going to run into performance issues when something changes even if you can get all those rows rendered to the DOM. And your user probably isn't going to scroll through 10000 rows anyway. I would just use pagination. e.g.:
<div ng-repeat="item in items | startFrom:currentPage*itemsPerPage | limitTo:itemsPerPage"></div>
If you really want to have everything on one page you could load the rows as the user scrolls. If you are interested in that solution checkout http://binarymuse.github.io/ngInfiniteScroll/
One of the things I've noticed that I stupidly used to ignore - the container has to have fixed height. That significantly makes updates faster. Although technically it doesn't solve the problem entirely
my premise was wrong. while AngularJS was certainly slowing things down, it was not due to the problem I describe below. however, it was flim's answer to my question - how to exclude an element from an Angular scope - that was able to prove this.
I'm building a site that generates graphs using d3+Raphael from AJAX-fetched data. this results in a LOT of SVG or VML elements in the DOM, depending on what type of chart the user chooses to render (pie has few, line and stacked bar have many, for example).
I'm running into a problem where entering text into text fields controlled by AngularJS brings Firefox to a crawl. I type a few characters, then wait 2-3 seconds for them to suddenly appear, then type a few more, etc. (Chrome seems to handle this a bit better.)
when there is no graph on the page (the user has not provided enough data for one to be generated), editing the contents of these text fields is fine. I assume AngularJS is having trouble when it tries to update the DOM and there's hundreds SVG or VML elements it has to look through.
the graph, however, contains nothing that AngularJS need worry itself with. (there are, however, UI elements both before and after the graph that it DOES need to pay attention to.)
I can think of two solutions:
put the graph's DIV outside the AngularJS controller, and use CSS to position it where it's actually wanted
tell AngularJS - somehow - to nevermind the graph's DIV; to skip it over when keeping the view and model in-sync
the second option seems preferable to me, since it keeps the document layout sane/semantic. is there any way to do this? (or some, even-better solution I have not thought of?)
Have you tried ng-non-bindable? http://docs.angularjs.org/api/ng.directive:ngNonBindable
<ANY ng-non-bindable>
...
</ANY>