Подтвердить что ты не робот

Связывание javascript (d3.js) с блестящим

Во-первых, я довольно незнакома с javascript и его библиотекой d3.js, но я знаком с R. Создание информационных панелей с использованием Shiny было забавным и легким (благодаря stackoverflow). Теперь я хочу расширить его, подключив к нему элементы d3.

Я ищу источники информации о том, как фактически привязывать javascript к Shiny (панель инструментов R) и объяснять, что происходит на самом деле.

Фон: Я сделал учебник по js и jquery на w3schools и немного узнал о d3, используя книгу Скотта Мюррея (интерактивная визуализация данных для Интернета). Я надеялся, что этого будет достаточно, чтобы заставить меня понять примеры и объяснения относительно того, как создавать пользовательские привязки ввода/вывода на веб-сайте Shiny:

http://shiny.rstudio.com/articles/building-inputs.html

Но, к сожалению, я этого не делаю, и я не могу найти примеров, которые находятся в минимальном рабочем коде. Множество примеров на github для меня сложнее рассеять, скорее всего, из-за моего небольшого опыта работы с javascript. Ниже приведены примеры привязки пользовательского ввода к javascript:

https://github.com/jcheng5/shiny-js-examples/tree/master/input

Вот пример привязки ввода и вывода, который я пытаюсь развернуть:

<script src="http://d3js.org/d3.v3.js"></script>
<script type="text/javascript">
(function(){
  // Probably not idiomatic javascript.

  this.countValue=0;

  // BEGIN: FUNCTION
  updateView = function(message) {

    var svg = d3.select(".d3io").select("svg")

    svg.append("text")
      .transition()
      .attr("x",message[0])
      .attr("y",message[1])
      .text(countValue)
      .each("end",function(){
        if(countValue<100) {
          countValue+=1;
          $(".d3io").trigger("change");
        }
      })
  }
  // END: FUNCTION

  //BEGIN: OUTPUT BINDING
  var d3OutputBinding = new Shiny.OutputBinding();
  $.extend(d3OutputBinding, {
    find: function(scope) {
      return $(scope).find(".d3io");
    },
    renderError: function(el,error) {
      console.log("Foe");
    },
    renderValue: function(el,data) {
      updateView(data);
      console.log("Friend");
    }
  });
  Shiny.outputBindings.register(d3OutputBinding);
  //END: OUTPUT BINDING

  //BEGIN: INPUT BINDING
  var d3InputBinding = new Shiny.InputBinding();
  $.extend(d3InputBinding, {
    find: function(scope) {
      return $(scope).find(".d3io");
    },
    getValue: function(el) {
      return countValue;
    },
    subscribe: function(el, callback) {
      $(el).on("change.d3InputBinding", function(e) {
        callback();
      });
    }
  });
  Shiny.inputBindings.register(d3InputBinding);
 //END: OUTPUT BINDING

})()
</script>

Где "d3io" является элементом div в ui, updateView() является функцией. Вот ui:

#UI
library(shiny)

d3IO <- function(inputoutputID) {
  div(id=inputoutputID,class=inputoutputID,tag("svg","")) #; eerst zat ; erbij, maar werkt blijkbaar ook zonder
}

# Define UI for shiny d3 chatter application
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("D3 Javascript chatter",
              "Demo of how to create D3 I/O and cumulative data transfer"),

  sidebarPanel(
    tags$p("This widget is a demonstration of how to wire shiny direct to javascript, without any input elements."),
    tags$p("Each time a transition ends, the client asks the server for another packet of information, and adds it
            to the existing set"),
    tags$p("I can't claim this is likely to be idiomatic javascript, because I'm a novice, but it allows d3 apps
            to do progressive rendering.  In real use, a more complex request/response protocol will probably be
            required.  -AlexBBrown")
  ),

  mainPanel(
    includeHTML("d3widget.js"),
    d3IO("d3io") #Creates div element that d3 selects
    )
))

Вот файл сервера:

# SERVER
library(shiny)
# Define server logic required to respond to d3 requests
shinyServer(function(input, output) {

  # Generate a plot of the requested variable against mpg and only 
  # include outliers if requested
  output$d3io <- reactive(function() {
    if (is.null(input$d3io)) {
      0;
    } else {
      list(rnorm(1)*400+200,rnorm(1)*400+200);
    }
  })
})

Конкретные вопросы:

1) Сервер .r, кажется, получает вход, называемый "d3io" (ввод $d3io), поскольку это не определено в ui.r, я полагал, что он должен поступать из файла javascript. На какой элемент он действительно ссылается?

2) У меня возникли проблемы с пониманием пользовательской связующей части:

var d3OutputBinding = new Shiny.OutputBinding();
  $.extend(d3OutputBinding, {
    find: function(scope) {
      return $(scope).find(".d3io");
    },
    renderError: function(el,error) {
      console.log("Foe");
    },
    renderValue: function(el,data) {
      updateView(data);
      console.log("Friend");
    }
  });
  Shiny.outputBindings.register(d3OutputBinding);

Мое понимание:

Создайте новую блестящую выходную привязку, сначала найдите класс .d3io (элемент div), если ошибка записывается в консоль "Foe" (это специальный код?), если не ошибка, то renderValue использует функцию updateView с использованием данных (Where получает ли это значение от?) и пишет в консоль "Друг". Наконец, зарегистрируйте выход.

Надеюсь, что вы, ребята, можете помочь! Я создаю документ с шагами "Необходимые шаги, чтобы узнать, как реализовать javascript в блестящем, когда вы не знаете javascript", мне бы это понравилось!:)

Cheers, Длинные

4b9b3361

Ответ 1

Привет, Sweetbabyjesus (так весело сказать). У вас было два вопроса:

1) Сервер .r, кажется, получает вход, называемый "d3io" (ввод $d3io), поскольку это не определено в ui.r, я полагал, что он должен поступать из файла javascript. На какой элемент он действительно ссылается?

Эта фраза input$d3io имеет следующие компоненты:

  • input - это параметр, переданный в функцию - это список, который сохраняет текущие значения всех виджетов в приложении.
  • $ - это селектор элементов.
  • d3io относится к содержимому элемента div с этим идентификатором ('d3IO ( "d3io" )') в mainPanel пользовательского интерфейса.

2) У меня возникли проблемы с пониманием пользовательской связующей части:

var d3OutputBinding = new Shiny.OutputBinding();

Правильно, это создает экземпляр Shiny.OutputBinding и назначает его переменной d3OutputBinding.

$.extend(d3OutputBinding, {
  find: function(scope) {
    return $(scope).find(".d3io");
  },
  renderError: function(el,error) {
    console.log("Foe");
  },
  renderValue: function(el,data) {
    updateView(data);
    console.log("Friend");
  }
});

Этот код расширяет поведение d3OutputBinding с помощью трех функций, называемых find, renderError и renderValue. Эти три функции необходимы для Shiny.OutputBinding.

find - это ключ, потому что он возвращает список элементов, которые должны быть переданы в две функции рендеринга через их параметр el. Обратите внимание, что они возвращают элементы, класс css которых "d3io" - тот же самый div, о котором упоминалось ранее.

Обратите внимание, что extend() является функцией jQuery javascript library, а $ в этом контексте является псевдонимом для объекта jQuery.

Shiny.outputBindings.register(d3OutputBinding);

Позволяет Shiny знать, что этот новый сконфигурированный объект следует использовать сейчас.

Приветствия, Ник

Ответ 2

Я собираюсь сделать шаг назад и предположить, что вы хотите, чтобы удивительные результаты D3 были способны, но не обязательно связаны с D3. По сути, я отвечу на этот вопрос:

Каковы необходимые шаги, чтобы узнать, как реализовать JavaScript в Shiny, когда вы не знаете какой-либо JavaScript?

В то время как D3 поразительно силен, его также трудно освоить - даже для многих людей, которые вполне довольны JavaScript. Хотя я люблю D3 и использую его почти каждый день, я бы рекомендовал против этого в этом случае. Вместо этого есть библиотека под названием Plotly, которая использует D3 в фоновом режиме, но построена специально для научного сообщества и ученых-ученых, поэтому она очень дружит с сообществом R.

У них есть подробное руководство по подключению к Shiny и даже есть ggplot2 converter, если вы уже знакомый с этим синтаксисом, так как многие в мире R. Если ваши потребности не очень необычны, Plotly, скорее всего, будет удовлетворять ваши потребности так же, как и писать непосредственно в D3, с гораздо более дружественной кривой обучения.

Ответ 3

Вы знакомы с пакетом rCharts? Он отлично работает с Shiny, и большинство выходных параметров основаны на вариантах D3. Два примеры.

Ответ 4

Очень занят работой, у меня не было возможности опубликовать его. Обратите внимание, что это временное решение, использующее customMessageHandler (и я не использую настраиваемую привязку ввода/вывода). Здесь:

Цель: отправка данных из фрейма данных для создания дерева D3JS с помощью customMessageHandler.

Путь: мне удалось отправить данные в формате data.frame в дерево d3js. После того, как вы нажмете кнопку action, она изменит данные в фрейме данных в формате JSON, а затем отправит их в файл js, который создает дерево. Данные дерева жестко закодированы на "server.r".

Где код? На моем github! https://github.com/SweetBabyJesus/shiny-d3js-simple-binding

Оригинал: я создал алгоритм дерева, основанный на CHAID, для создания представлений из больших наборов данных. Люди могут загружать свои csv на панель управления, которая затем выплевывает дерево d3js:). Код несколько длинный, поэтому я отключил его для вас и создал минимальный пример кода.

Надеюсь, вам понравится.

Cheers, Длинные