Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 2k
bar transitions#4180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
bar transitions #4180
Changes from all commits
f49828abda810f495d036cc871cd16c88f8709ee2fFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -51,7 +51,28 @@ function getXY(di, xa, ya, isHorizontal) { | ||||||||||||||||||||||||||||||
| return isHorizontal ? [s, p] : [p, s]; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| function plot(gd, plotinfo, cdModule, traceLayer, opts) { | ||||||||||||||||||||||||||||||
| function transition(selection, opts, makeOnCompleteCallback) { | ||||||||||||||||||||||||||||||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clean wrapper! It's a little different than what plotly.js/src/traces/scatter/plot.js Lines 67 to 73 in 46866fd
@antoinerg have you noticed "out of order" transitions? Your wrapper plays better with Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One drawback from your pattern:
| ||||||||||||||||||||||||||||||
| functiontransition(selection){ | |
| returnhasTransition ? selection.transition() : selection; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is non-blocking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So here, you trying to get the "untransformed" bounding box, correct? Nice catch!
I guess that's what we have to do in the current bar text svg structure:
where the transform is attached to the <text> element.
Compare this to scatter text:
which then can benefit from this piece of logic in Drawing.bBox:
plotly.js/src/components/drawing/index.js
Lines 921 to 934 in 46866fd
| if(!transform){ | |
| // in this case, just varying x and y, don't bother caching | |
| // the final bBox because the alteration is quick. | |
| varinnerBB=drawing.bBox(innerNode,false,hash); | |
| if(x){ | |
| innerBB.left+=x; | |
| innerBB.right+=x; | |
| } | |
| if(y){ | |
| innerBB.top+=y; | |
| innerBB.bottom+=y; | |
| } | |
| returninnerBB; | |
| } |
and not have to worry about removing and adding back the transform.
Oh well, @antoinerg nothing to do here for now, I just wanted to write this down for future reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is non-blocking
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| { | ||
| "data": [{ | ||
| "type": "bar", | ||
| "x": ["A", "B", "C"], | ||
| "y": [24, 5, 8], | ||
| "error_y": {"array": [3, 2, 1]} | ||
| }], | ||
| "layout": { | ||
| "width": 400, | ||
| "height": 400, | ||
| "yaxis": {"range": [0, 30]} | ||
| }, | ||
| "frames": [ | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. | ||
| {"data": [{"y": [12, 15, 10]}]}, | ||
| {"data": [{"error_y": {"array": [5, 4, 1]}}]}, | ||
| {"data": [{"marker": {"color": ["red", "blue", "green"]}}]}, | ||
| {"data": [{"width": 0.25}]}, | ||
| {"data": [{"marker": {"line": {"width": 10}}}]}, | ||
| {"data": [{"marker": {"line": {"color": ["orange", "yellow", "blue"]}}}]}, | ||
| {"layout": {"yaxis": {"range": [0, 20]}}} | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| 'use strict'; | ||
| var Plotly = require('@lib/index'); | ||
| var Lib = require('@src/lib'); | ||
| var d3 = require('d3'); | ||
| var delay = require('./delay.js'); | ||
| var reNumbers = /([\d\.]+)/gm; | ||
| function promiseSerial(funcs, wait) { | ||
| return funcs.reduce(function(promise, func) { | ||
| return promise.then(function(result) { | ||
| return func().then(Array.prototype.concat.bind(result)).then(delay(wait)); | ||
| }); | ||
| }, Promise.resolve([])); | ||
| } | ||
| function clockTick(currentNow, milliseconds) { | ||
| Date.now = function() { | ||
| return currentNow + milliseconds; | ||
| }; | ||
| d3.timer.flush(); | ||
| } | ||
| // Using the methodology from http://eng.wealthfront.com/2017/10/26/testing-d3-transitions/ | ||
| module.exports = function checkTransition(gd, mock, animateOpts, transitionOpts, tests) { | ||
| if(!transitionOpts) { | ||
| transitionOpts = { | ||
| transition: { | ||
| duration: 500, | ||
| easing: 'linear' | ||
| }, | ||
| frame: { | ||
| duration: 500 | ||
| } | ||
| }; | ||
| } | ||
| // Prepare chain | ||
| var now = Date.now; | ||
| var startTime; | ||
| var currentTime; | ||
| var p = [ | ||
| function() { | ||
| return Plotly.newPlot(gd, mock) | ||
| .then(function() { | ||
| // Check initial states if present | ||
| for(var i = 0; i < tests.length; i++) { | ||
| if(tests[i][0] === 0) assert(tests[i]); | ||
| } | ||
| }); | ||
| }, | ||
| function() { | ||
| // Hijack Date.now | ||
| startTime = Date.now(); | ||
| currentTime = 0; | ||
| clockTick(startTime, 0); | ||
| Plotly.animate(gd, animateOpts, transitionOpts); | ||
| return Promise.resolve(true); | ||
| } | ||
| ]; | ||
| var checkTests = tests.map(function(test) { | ||
| return function() { | ||
| if(test[0] === 0) return Promise.resolve(true); | ||
| if(test[0] !== currentTime) { | ||
| clockTick(startTime, test[0]); | ||
| currentTime = test[0]; | ||
| } | ||
| return assert(test); | ||
| }; | ||
| }); | ||
| // Run all tasks | ||
| return promiseSerial(p.concat(checkTests)) | ||
| .catch(function(err) { | ||
| Date.now = now; | ||
| return Promise.reject(err); | ||
| }) | ||
| .then(function() { | ||
etpinard marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Date.now = now; | ||
| }); | ||
| }; | ||
| // A test array is made of | ||
| // [ms since start of transition, selector, (attr|style), name of attribute, array of values to be found] | ||
| // Ex.: [0, '.point path', 'style', 'fill', ['rgb(31, 119, 180)', 'rgb(31, 119, 180)', 'rgb(31, 119, 180)']] | ||
| function assert(test) { | ||
| var msg = 'at ' + test[0] + 'ms, selection ' + test[1] + ' has ' + test[3]; | ||
| var cur = []; | ||
| d3.selectAll(test[1]).each(function(d, i) { | ||
| if(test[2] === 'style') cur[i] = this.style[test[3]]; | ||
| if(test[2] === 'attr') cur[i] = d3.select(this).attr(test[3]); | ||
| }); | ||
| switch(test[3]) { | ||
| case 'd': | ||
| assertEqual(cur, test[4], round, msg); | ||
| break; | ||
| case 'transform': | ||
| assertCloseTo(cur, test[4], 3, extractNumbers, msg); | ||
| break; | ||
| default: | ||
| assertEqual(cur, test[4], Lib.identity, msg); | ||
| } | ||
| return Promise.resolve(true); | ||
| } | ||
| function assertEqual(A, B, cb, msg) { | ||
| var a = cb(A); | ||
| var b = cb(B); | ||
| expect(a).withContext(msg + ' equal to ' + JSON.stringify(a)).toEqual(b); | ||
| } | ||
| function assertCloseTo(A, B, tolerance, cb, msg) { | ||
| var a = cb(A).flat(); | ||
| var b = cb(B).flat(); | ||
| expect(a).withContext(msg + ' equal to ' + JSON.stringify(A)).toBeWithinArray(b, tolerance); | ||
| } | ||
| function extractNumbers(array) { | ||
| return array.map(function(d) { | ||
| return d.match(reNumbers).map(function(n) { | ||
| return parseFloat(n); | ||
| }); | ||
| }); | ||
| } | ||
| function round(array) { | ||
| return array.map(function(cur) { | ||
| return cur.replace(reNumbers, function(match) { | ||
| return Math.round(match); | ||
| }); | ||
| }); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.



Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great - tests are passing. Looks like this didn't break @archmoj's
isBlankwork from #4056 🎉