Git Product home page Git Product logo

Comments (19)

jjallaire avatar jjallaire commented on July 4, 2024 2

@javierluraschi and I just talked realtime. There is one change that we need to make which will enable inclusion of jetpack via the dependencies argument to r2d3(). We aren't going to create a full-scale extensions mechanism with built-in jetpack b/c we don't want to bake in something that is the flavor-of-the-month/year then later regret it. dependencies = "d3-jetpack.js" will be it for now.

from r2d3.

edgararuiz-zz avatar edgararuiz-zz commented on July 4, 2024 1

Hi Nick,

The following script worked for me. I followed the pattern from the sample D3 bar plot code in the package examples, the sample takes the full height and divide by the number of discrete values. I just divided the width and height by half to get it to be placed in the middle of the viewer:

// !preview r2d3 data=NULL
//
// r2d3: https://rstudio.github.io/r2d3
//
svg.append('circle')
  .attr('r', 50)
  .attr('cx', width / 2)
  .attr('cy', height / 2)
  .attr('fill', 'orangered');

from r2d3.

jjallaire avatar jjallaire commented on July 4, 2024 1

@nstrayer the jetpack stuff looks very interesting. It seems like there are a couple of things we could do here:

  1. Include jetpack by default for versions of D3 that support it (do all of them?) and then add a jetpack argument to disable the default behavior. If we think that's too aggressive we could just export an html_dependency_d3_jetpack() function and have users write:

    r2d3(data = foo, script = "foo.js", dependencies = html_dependency_d3_jetpack()
  2. Some sort of integration with the conventions() function. My worry here is that in order to make things convenient for users we create the svg element (then handle re-creating it, re-sizing it, etc.). It seems like to the extent that conventions() also deals with size that we'll need to be the ones calling the conventions() function.

One other concern I have about conventions() is that if we do it by default we'll actually make it harder to port examples from the D3 gallery. So it needs to be:

  • Opt-in
  • Something that we call rather than the user
  • Integrated with our auto-resizing logic

Not sure if all of this is possible, would be interesting to get your take @nstrayer

from r2d3.

edgararuiz-zz avatar edgararuiz-zz commented on July 4, 2024

dot

from r2d3.

nstrayer avatar nstrayer commented on July 4, 2024

@edgararuiz I apologize, what I unclearly was trying to show is that, when appending a shape to the current svg object directly and placing it near the boundaries, the circle in my example is clipped. If the g container is inset in the visualization like I mentioned the clipping would be avoided.

Personally, I find It makes the code cleaner and easier to reason about when not having to deal with remembering when to add a margin.left etc to things. Much like how ggplot2 defaults to having expand = c(1,1).

This isn't an 'issue' in the traditional sense, just a potential feature addition (adding a pre-padded container to the svg.)

from r2d3.

javierluraschi avatar javierluraschi commented on July 4, 2024

@nstrayer htmlwidgets already include padding by themselves, is this padding not sufficient? Notice that this is also customizable with the sizing parameter in r2d3.

from r2d3.

javierluraschi avatar javierluraschi commented on July 4, 2024

@nstrayer from reading your second comment, looks like you like to use the padding as optional, correct? As in, you add padding with a g entry but if the visualization happens to go beyond the boundaries, at least you get the right clipping behavior? There are various examples that do use margins in the SVG and I do agree with you that making this easier to read would be nice.

One option would be to introduce an svg.g container type that removes the htmlwidget padding and gives you a g element with margin presets instead.

from r2d3.

javierluraschi avatar javierluraschi commented on July 4, 2024

@nstrayer Actually, one way to do this would be to create a margins.js script with something like:

var pagePadding = options && options.margin !== null ? options.margin : 50;

svg = svg.append("g")
   .attr('transform', 'translate(' + pagePadding + ',' + pagePadding + ')');

width = width - pagePadding * 2;
height = height - pagePadding * 2;

which then you could include by default...

// !preview r2d3 data = c(0.3, 0.6, 0.8, 0.95, 0.40, 0.20), dependencies = c("margins.js")
//
// r2d3: https://rstudio.github.io/r2d3
//

var barHeight = Math.ceil(height / data.length);

svg.selectAll('rect')
  .data(data)
  .enter().append('rect')
    .attr('width', function(d) { return d * width; })
    .attr('height', barHeight)
    .attr('y', function(d, i) { return i * barHeight; })
    .attr('fill', 'steelblue');

However, there are probably more elegant ways to do this in D3, for instance, by creating a proper D3 extension since this is common functionality. This makes me believe there should be a d3.margin() package/helper function to assist adding marging to SVG with ease from JavaScript and not necessarily from the R interface itself.

I'll keep this issue open to consider other options and get more feedback about this.

from r2d3.

nstrayer avatar nstrayer commented on July 4, 2024

@javierluraschi in response the first post: the padding/margins in htmlwidgets is div itself but like my little example shows this will still cut off periphery datapoints in your plot because the svg doesn't inherit those margins.

For the second post: I think making it optional would not be a bad idea. Obviously sometimes people may want to take a little more control and having the padding would just get in the way, but for a large portion of situations (at least in my anecdotal experiences) you want the padded g as your main plot-to object.

For the third comment: That is a good idea. Perhaps it could be added as an option to the package? I am more than willing to poke around the file structure until I figure out how and then I can submit a PR as a demo of how it would work if desired.

There, in fact, is a library that does this already: d3jetpack and more specifically the conventions function which sets up your svg for you and gives you back g that has been padded. I think jetpack has been implemented as an option in d3r.

from r2d3.

nstrayer avatar nstrayer commented on July 4, 2024

Another potential implementation could be along these routes where if in options padded was set to TRUE it would do this, otherwise, it would default to what is there now.

// !preview r2d3 data=data.frame(x = c(0,1,2,3,4,5,3.1415), y = c(10,9,1,5,6.28, 5,0)), options=list(padded = TRUE)

const pagePadding = 10;
const radius = 10;

if(options.padded){
  height = height - 2*pagePadding;
  width = width - 2*pagePadding;
  svg = svg.append('g')
    .attr('transform', 'translate(' + pagePadding + ',' + pagePadding + ')');
}

const x = d3.scaleLinear()
  .domain(d3.extent(data, d => d.x))
  .range([0, width]);
  
const y = d3.scaleLinear()
  .domain(d3.extent(data, d => d.y))
  .range([0, height]);
  
svg.selectAll("circle")
    .data(data)
    .enter().append("circle")
    .attr("cx", d => x(d.x))
    .attr("cy", d => y(d.y))
    .attr("r", radius)
    .attr('fill', options.color);

from r2d3.

jjallaire avatar jjallaire commented on July 4, 2024

Yes, I noticed that d3r had support for d3jetpack -- @javierluraschi I wonder if this is convenient enough that we should make jetpack a built-in option? Perhaps enabled by default?

from r2d3.

jjallaire avatar jjallaire commented on July 4, 2024

@timelyportfolio What are your thoughts here?

from r2d3.

javierluraschi avatar javierluraschi commented on July 4, 2024

@jjallaire I was looking at D3 extensions, there are many useful ones: crossfilter, d3-jetpack, d3-starterkit and many more that can be found here: https://github.com/wbkd/awesome-d3

I think it would make sense to enable them all by creating an extensions.csv file that contains a mapping of names/urls that the community can update with ease and then use through something like:

d3_available_extension()
Extension      Description
crossfilter    Library for exploring large multivariate datasets  
d3-jetpack     Nifty convenience wrappers that speed up your daily work
d3-starterkit  Helper functions simplifying common and verbose d3 patterns

Which then can be used as dependencies...

r2d3(data = c(1, 3, 4), script = "foo.js", dependencies = d3_extension("d3-jetpack"))

from r2d3.

javierluraschi avatar javierluraschi commented on July 4, 2024

@jjallaire Here is a WIP PR to support extensions: #17

from r2d3.

jjallaire avatar jjallaire commented on July 4, 2024

Awesome! I added some discussion there about an alternate approach to consider.

Based on looking at your example it seems like the conventions() function can be initialized with our existing svg, width, height context so we don't need to do anything special there other than document this usage pattern.

from r2d3.

timelyportfolio avatar timelyportfolio commented on July 4, 2024

@jjallaire my schedule is jammed over next couple of days. I look forward to reviewing and offering thoughts after that. Great work!

from r2d3.

nstrayer avatar nstrayer commented on July 4, 2024

All of these sound great. I didn't think about the point @jjallaire brought up about the adding this custom padding behavior making it difficult to port d3 examples wholescale as they usually handle this stuff themselves and so we'd have paddings on paddings.

I feel guilty that I bring up these minor points and you do all this amazing work on it! Let me know if there's any way I can help in the process that won't get in the way in terms of the impressive development flow you've built up.

from r2d3.

nstrayer avatar nstrayer commented on July 4, 2024

Seems like a smart plan to me.

from r2d3.

javierluraschi avatar javierluraschi commented on July 4, 2024

/r2d3/pull/19 with support for dependencies = "d3-jetpack.js" is now merged. Closing this issue, worth opening a new one if we find out later on we have more suggestions in this space.

from r2d3.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.