Re: How to update d3 graphics if I load from external data?

47 views
Skip to first unread message

Gordon Woodhull

unread,
Apr 29, 2018, 8:01:08 AM4/29/18
to d3...@googlegroups.com
Try putting absolutely everything inside that d3.json callback - graph generation, slider callback, everything. 

On Apr 28, 2018, at 4:38 PM, Samson Liu <samso...@gmail.com> wrote:

So I haven't been able to find an example. I'm loading this huge dataset from an external file with D3, and I'm making some graph with some part of the data. When a slider is moved, I wish make the same graph with some other part of the data.

I used d3.json() for loading the data. The trouble that I'm facing is: since the d3.json() is asynchronous, it loads the dataset for once, and then I can't access it from other functions. I can't have another update function that makes a new graph since I simply can't access the data anymore.

Other people's suggestions have been "only using the data in the d3.json() function: How to store a JSON object loaded from a file?

d3.json("temp.json", function(data){
    //use data here
})
// do not use data anymore

I tried to use a variable to store the data (the second answer from the same question link above):

var DATASET; // global

d3.json("file.json", function(data) {
    DATASET = data;
    //any other functions that depend on data
});

d3.selectAll().data(DATASET).......

And I couldn't get it to work at all, since (I assume this is the reason) the data hasn't been loaded to DATASET when the last line of d3.data calls DATASET

Is there any way I could update external data in d3? Should I just load the data again in my update function? Will it affect performance since the dataset is huge?

Thank you so much for answering!

--
You received this message because you are subscribed to the Google Groups "d3-js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Samson Liu

unread,
Apr 29, 2018, 8:19:23 AM4/29/18
to d3-js
Thank you so much for replying! I was able to figure it out so I deleted the post. My bad.

My solution was to put the d3.json() in the update function again. I was initially reluctant to do so since I thought it was pretty wasteful to reload a big dataset completely every time the slider is moved. But I haven't been able to find another way. The lag is acceptable so I went with it.

I'm not sure if you can put the update function inside the initial load function. At least in my case, I generated my slider with html5's input like everyone else, and I used onchange/oninput attributes to call the update function in my javascript. I am not sure but I assumed the onchange/oninput attributes can't call asynchronous functions (and nameless functions of course). 

I understand that I might be missing something and it would be awesome if you can elaborate a little more on how to put the slider on the initial load. 

Thanks again!

gor...@woodhull.com

unread,
Apr 29, 2018, 8:50:19 PM4/29/18
to d3...@googlegroups.com
Ah, I see what you mean. Callbacks defined as HTML attributes only
have access to the global scope.

I prefer to use the d3 syntax, and only declare the callback when it
has something to do. So, inside the d3.json callback, you could define
a function which has access to the returned data, and assign that
function to onchange/oninput. The d3 syntax looks like this:

d3.json('http://whatever').then(function(data) {
// ...
d3.select('#slider').on('change', function () {
// now we have data and can respond to changes with a subset
of the data
});
});

You could also do

getElementById('sliderElem').onchange = function () {
// ...
};

inside there, it's the same thing.

If you want to use the HTML attribute, you need to declare the
function at global scope, but you can reassign it in the scope that
has the data.

<input id="slider" onchange="slide()">


<script>

var slide = function() {}; // declare slide() globally but have it do
nothing until we have data

d3.json('http://whatever').then(function(data) {
slide = function() { // assign to the global
// do cool stuff with data
};
});



Quoting Samson Liu <samso...@gmail.com>:

> Thank you so much for replying! I was able to figure it out so I deleted
> the post. My bad.
>
> My solution was to put the d3.json() in the update function again. I was
> initially reluctant to do so since I thought it was pretty wasteful to
> reload a big dataset completely every time the slider is moved. But I
> haven't been able to find another way. The lag is acceptable so I went with
> it.
>
> I'm not sure if you can put the update function inside the initial load
> function. At least in my case, I generated my slider with html5's input
> like everyone else, and I used onchange/oninput attributes to call the
> update function in my javascript. I am not sure but I assumed the
> onchange/oninput attributes can't call asynchronous functions (and nameless
> functions of course).
>
> I understand that I might be missing something and it would be awesome if
> you can elaborate a little more on how to put the slider on the initial
> load.
>
> Thanks again!
>
> On Sunday, April 29, 2018 at 8:01:08 AM UTC-4, Gordon Woodhull wrote:
>>
>> Try putting absolutely everything inside that d3.json callback - graph
>> generation, slider callback, everything.
>>
>> On Apr 28, 2018, at 4:38 PM, Samson Liu <samso...@gmail.com <javascript:>>
>> wrote:
>>
>> So I haven't been able to find an example. I'm loading this huge dataset
>> from an external file with D3, and I'm making some graph with some part of
>> the data. When a slider is moved, I wish make the same graph with some
>> other part of the data.
>>
>> I used d3.json() for loading the data. The trouble that I'm facing is:
>> since the d3.json() is asynchronous, it loads the dataset for once, and
>> then I can't access it from other functions. I can't have another update
>> function that makes a new graph since I simply can't access the data
>> anymore.
>>
>> Other people's suggestions have been "only using the data in the d3.json()
>> function: How to store a JSON object loaded from a file?
>> <https://stackoverflow.com/questions/16455194/how-to-store-a-json-object-loaded-from-a-file>
>>
>> d3.json("temp.json", function(data){
>> //use data here})// do not use data anymore
>>
>> I tried to use a variable to store the data (the second answer from the
>> same question link above):
>>
>> var DATASET; // global
>>
>> d3.json("file.json", function(data) {
>> DATASET = data;
>> //any other functions that depend on data});
>>
>> d3.selectAll().data(DATASET).......
>>
>> And I couldn't get it to work at all, since (I assume this is the reason)
>> the data hasn't been loaded to DATASET when the last line of d3.data calls
>> DATASET
>>
>> Is there any way I could update external data in d3? Should I just load
>> the data again in my update function? Will it affect performance since the
>> dataset is huge?
>>
>> Thank you so much for answering!
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "d3-js" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to d3-js+un...@googlegroups.com <javascript:>.
Reply all
Reply to author
Forward
0 new messages