Загрузка локальных данных для визуализации с использованием D3.js
Я работаю над проектом, который требует, чтобы я визуализировал довольно сложный тип данных (см. этот старый вопрос). Короче говоря, у меня есть большой кусок данных, которые я могу экспортировать в JSON, CSV или какой-либо другой произвольный формат, хотя я предпочитаю избегать XML, если это возможно (см. Связанный вопрос выше для подробного объяснения базовых данных).
Я начал работать над визуализацией с использованием D3, макет, который я написал, кажется, работает нормально до сих пор, когда я тестирую его с помощью очень простых данных, которые я жестко кодирует в Javascript как массив. Учебники, которые я прочитал о привязке данных в D3, были немного запутанными в том смысле, что некоторые используют JSON, а некоторые используют формат TXT/CSV, а некоторые другие используют жестко заданные массивы/матрицы.
В случае JSON я просмотрел учебник, в котором рассказчик твердо советует размещать файл JSON на веб-сервере и получать его с использованием HTTP-запроса вместо локального файла. Я понимаю, что это связано с ограничениями, связанными с перекрестными доменами, и я считаю, что мне нужно как-то обойтись. На данный момент я не уверен, как действовать, начиная с:
-
Визуализация, основанная на D3, будет представлена в серии отчетов HTML, которые создаются в качестве результатов инструмента анализа, который я написал. Анализ выполняется на компьютере пользователя, а отчеты HTML также создаются локально на стороне клиента.
-
Предполагаемые пользователи наиболее определенно не разбираются в технологиях, поэтому не обязательно указывать им запускать веб-сервер на своем компьютере, чтобы иметь возможность обслуживать JSON или любой другой тип или ресурс через localhost
Для записи я попытался запустить модуль python SimpleHTTPServer, чтобы попробовать, и снова все работает нормально. Затем я попытался жестко закодировать данные в сгенерированных отчетах HTML, а затем вызвать объект JSON из моего script, который использует D3,
//d3.json("mydata.json", function(json){
d3.json(myjson, function(json){
nodeData = json.elements;
....
}
так как в этом случае я заканчиваю отправку в объект JSON, а D3.js ожидает URL.
Что я могу сделать, чтобы избежать/решить эту проблему?
Ответы
Ответ 1
Чтобы загрузить локальные файлы данных без использования сервера, добавьте тег script в тело с исходными данными, назначенными переменной или объекту, который вы ожидаете. В приведенном ниже примере я загружаю данные для определенной страны из файла [COUNTRY_ISO3CODE].js. В частности, файл данных Афганистана может содержать содержимое в формате:
data[AFG] = {"name": "Afghanistan", "estimate": 9.003, ... }
В вызывающем файле будет что-то вроде:
if (!data[iso3]) { //only load the needed data-script as needed
// if using jQuery
$('body').append("<script type='text/javascript' src='jdb/"+ iso3 +".js'></script>")
//If not using jQuery
/*var script = document.createElement("script");
script.type = "text/javascript";
script.src = "jdb/"+iso3+".js"; //?_="+ (new Date()); URL might have to be randomized to avoid cached data
document.body.appendChild(script);
*/
// call the data-handling function only after
// the desired data has fully loaded
// in this case, I check every 100 milliseconds
var intervalId = setInterval( function () {
if (data[iso3]) { //once data is detected, process data
clearInterval(intervalId); //stop checking for data
prepData(mainWrapper, iso3)
drawCharts(mainWrapper, iso3)
}
}, 100)
}
else drawCharts(mainWrapper, iso3)
Ответ 2
Для JSON:
var data = JSON.parse(JavascriptStringVariableThatContainsJSON);
Для CSV:
var data = d3.csv.parseRows(JavascriptStringVariableThatContainsMyCSVdata);
//затем добавьте данные в график и вызовите enter, что-то вроде:
var dataEnter = svg.selectAll("rect").data(data).enter();
Ответ 3
Итак, вы хотите загрузить локальные данные с помощью вызова FileReader, материал ниже берется из Чтение локальных файлов в JavaScript. Однако, опираясь на пример сверху, этот код загружает файл изображения в svg без связывания файла, но фактически вставляет растровые данные в svg. И не стесняйтесь заменять растровые данные любыми другими данными, просто добавляйте к нему правильную обработку...
Сначала откройте поддерживающие html-элементы в разделе <body>
:
<input type="file" id="files" name="files[]" multiple />
Затем вы хотите связать элемент <input ... />
с некоторым кодом в разделе <script>
:
document.getElementById('files').addEventListener('change', handleFileSelect, false);
Теперь код за файлом, прочитанным в коде обработки событий (теперь в этом случае я хочу загрузить локальное изображение в D3JS svg):
function handleFileSelect(evt) {
reader = new FileReader();
reader.onabort = function(e) {alert('File read cancelled');};
var imageObj = new Image(); //image object to hold the local file contents.
//and given the asynchronous nature, set up the event so that when the image is loaded, do something with it:
imageObj.onload = function() {image.datum(imageObj.src).attr("xlink:href", function(d) {return d})};
//similarly for the file reading:
reader.onload = function(e) {imageObj.src = reader.result};
//With all the events set up, lets start reading the file in.
//the secret sauce is the DataURL
reader.readAsDataURL(evt.target.files[0]);
}
И для полноты соус D3JS за изображением:
var svg = d3.select("body").append("svg");
var image = svg.append("defs")
.append("pattern")
.attr("id", "venus")
.attr('patternUnits', 'userSpaceOnUse')
.attr("width", 200)
.attr("height", 200)
.append("image")
.attr("width", 200)
.attr("height", 200);
var image2 = svg.append("rect")
.attr("x", "0")
.attr("y", "0")
.attr("width", 200)
.attr("height", 200)
.attr("fill", "url(#venus)");
Ответ 4
Если вы каждый раз генерируете HTML-код, вы можете поместить данные как JSON либо прямо в свой HTML файл, либо в .js файл, который вы можете ссылаться на HTML, возможно, через сгенерированный уникальный URL-адрес.
Ответ 5
У D3 есть отличные инструменты для импорта данных и управления им. Всегда служил json в прошлом (и это иногда сложно создать). Я собираюсь больше обслуживать csv и манипулировать им в javascript/d3, но было бы интересно посмотреть, как другие отвечают на ваш вопрос.
Это простой пример, показывающий csv для вложенного json здесь: https://gist.github.com/3053667
Также имеется множество инструментов для управления данными: https://github.com/mbostock/d3/wiki/Arrays
И тогда есть Crossfilter, если вы хотите нарезать кубиками. Выглядит хорошо, чтобы справиться с этим, но я жду, когда манекен выйдет! http://square.github.com/crossfilter/
Ответ 6
d3.json загружает внешние json файлы через ajax-вызовы - переменная myjson
в вашем примере уже является объектом javascript, поэтому вам не нужно ее загружать, просто используйте ее непосредственно в назначении nodeData
.
nodeData = myjson.elements;