Comments (19)
@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.
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.
@nstrayer the jetpack stuff looks very interesting. It seems like there are a couple of things we could do here:
-
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 anhtml_dependency_d3_jetpack()
function and have users write:r2d3(data = foo, script = "foo.js", dependencies = html_dependency_d3_jetpack()
-
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 thatconventions()
also deals with size that we'll need to be the ones calling theconventions()
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.
from r2d3.
@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.
@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.
@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.
@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.
@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.
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.
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.
@timelyportfolio What are your thoughts here?
from r2d3.
@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.
@jjallaire Here is a WIP PR to support extensions: #17
from r2d3.
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.
@jjallaire my schedule is jammed over next couple of days. I look forward to reviewing and offering thoughts after that. Great work!
from r2d3.
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.
Seems like a smart plan to me.
from r2d3.
/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)
- forcegraph.js using container = "canvas" not working
- Data passed to multiple charts HOT 1
- Render r2d3 output in rmarkdown document with `rmarkdown::knitr()` function
- Support script parameter in d3 knitr chunk
- r2d3 bubbles example is not rendering output
- Pass info from D3 back to [R] HOT 1
- Error adding multiple dependencies HOT 1
- Debugging: Rstudio D3 Preview with Full R Code HOT 1
- Why does the image produced from r2d3 is static?
- Implementing D3 6.0 HOT 4
- Question: r2d3 still maintained? HOT 2
- Inproper data join after input change HOT 1
- Width and Height parameters don't seem to work
- Quick questions about width and height HOT 1
- Move `master` branch to `main` HOT 1
- D3 preview in RStudio does not render imported SVG
- Cleanup the README formatting
- "publishing.html" documentation article has mis-rendered R code blocks
- Brush selection lost after page resize
- issues when rendering an r2d3-based package's plots in shiny
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from r2d3.