Does anyone know how I can ensure only the cuboid animation is used on my slider? I don't particularly love the slicing action but do like the rotating cube options both left to right and top to bottom. I have checked the docs but can only see how to change orientation of the slicing animation or set to random.
The JS settings referred to in the docs are here:
JS
$.Slicebox.defaults = {
// (v)ertical, (h)orizontal or (r)andom
orientation : 'h',
// perspective value
perspective : 1200,
// number of slices / cuboids
// needs to be an odd number 15 => number > 0 (if you want the limit higher, change the _validate function).
cuboidsCount : 5,
// if true then the number of slices / cuboids is going to be random (cuboidsCount is overwitten)
cuboidsRandom : false,
// the range of possible number of cuboids if cuboidsRandom is true
// it is strongly recommended that you do not set a very large number :)
maxCuboidsCount : 5,
// each cuboid will move x pixels left / top (depending on orientation). The middle cuboid doesn't move. the middle cuboid's neighbors will move disperseFactor pixels
disperseFactor : 0,
// color of the hidden sides
colorHiddenSides : '#222',
// the animation will start from left to right. The left most cuboid will be the first one to rotate
// this is the interval between each rotation in ms
sequentialFactor : 150,
// animation speed
// this is the speed that takes "1" cuboid to rotate
speed : 600,
// transition easing
easing : 'ease',
// if true the slicebox will start the animation automatically
autoplay : true,
// time (ms) between each rotation, if autoplay is true
interval: 3000,
// the fallback will just fade out / fade in the items
// this is the time fr the fade effect
fallbackFadeSpeed : 300,
// callbacks
onBeforeChange : function( position ) { return false; },
onAfterChange : function( position ) { return false; },
onReady : function() { return false; }
};
I haven't copied all the js code as there's lots!
You just need to change number of slices to 1
cuboidsCount : 1
Related
I am creating a network graph using Cytoscape JS with the cose layout. The issue I am running into is that when i am animating my graph, it eases into its end position and then it snaps into a different position.
I have tried turning of the fit, defining boundingBox, increasing and decreasing the minTemp as well as increasing the coolingFactor.
The following is what layout variables are:
export default {
name: 'cose',
// Called on `layoutready`
ready: function(){},
// Called on `layoutstop`
stop: function(){},
// Whether to animate while running the layout
// true : Animate continuously as the layout is running
// false : Just show the end result
// 'end' : Animate with the end result, from the initial positions to the end positions
animate: 'end',
// Easing of the animation for animate:'end'
// Options: 'ease', 'linear'(default if undefined), ... potentially more options but need to find them
animationEasing: 'ease',
// The duration of the animation for animate:'end'
animationDuration: 3000,
// A function that determines whether the node should be animated
// All nodes animated by default on animate enabled
// Non-animated nodes are positioned immediately when the layout starts
animateFilter: function ( node, i ){ return true; },
// The layout animates only after this many milliseconds for animate:true
// (prevents flashing on fast runs)
animationThreshold: 1000,
// Number of iterations between consecutive screen positions update
refresh: 10,
// Whether to fit the network view after when done
fit: true,
// Padding on fit
padding: 20,
// Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
boundingBox: undefined,
// Excludes the label when calculating node bounding boxes for the layout algorithm
nodeDimensionsIncludeLabels: true,
// Randomize the initial positions of the nodes (true) or use existing positions (false)
randomize: true,
// Extra spacing between components in non-compound graphs
componentSpacing: 10,
// Node repulsion (non overlapping) multiplier
nodeRepulsion: function( node ){ return 1000000000; },
// Node repulsion (overlapping) multiplier
// NOTE: effects spacing of nodes
nodeOverlap: 100000000,
// Ideal edge (non nested) length
idealEdgeLength: function( edge ){ return 50; },
// Divisor to compute edge forces
edgeElasticity: function( edge ){ return 1; },
// Nesting factor (multiplier) to compute ideal edge length for nested edges
nestingFactor: 0.1,
// Gravity force (constant)
gravity: -1000,
// Maximum number of iterations to perform
numIter: 20000,
// Initial temperature (maximum node displacement)
initialTemp: 100,
// Cooling factor (how the temperature is reduced between consecutive iterations
coolingFactor: 0.999,
// Lower temperature threshold (below this point the layout will end)
minTemp: 10.0,
};
If you want a more sophisticated force-directed layout, you should use COSE Bilkent or fCOSE. The bundled COSE is fast and small in file size but it has less features.
Is it possible to configure this to display a vertical tree instead of a horizontal tree? What I mean by vertical is something similar to Windows Explorer.
We have some users that would prefer to work with it that way.
The dagre layout extension has a github page with some useful default values for the layout:
var defaults = {
nodeSep: undefined, // the separation between adjacent nodes in the same rank
edgeSep: undefined, // the separation between adjacent edges in the same rank
rankSep: undefined, // the separation between adjacent nodes in the same rank
rankDir: undefined // 'TB' for top to bottom flow, 'LR' for left to right,
ranker: undefined, // Type of algorithm to assign a rank to each node in the input graph. Possible values: 'network-simplex', 'tight-tree' or 'longest-path'
minLen: function( edge ){ return 1; }, // number of ranks to keep between the source and target of the edge
edgeWeight: function( edge ){ return 1; }, // higher weight edges are generally made shorter and straighter than lower weight edges
// general layout options
fit: true, // whether to fit to viewport
padding: 30, // fit padding
spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up
nodeDimensionsIncludeLabels: false, // whether labels should be included in determining the space used by a node
animate: false, // whether to transition the node positions
animateFilter: function( node, i ){ return true; }, // whether to animate specific nodes when animation is on; non-animated nodes immediately go to their final positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
transform: function( node, pos ){ return pos; }, // a function that applies a transform to the final node position
ready: function(){}, // on layoutready
stop: function(){} // on layoutstop
}
The important part here is the rankDir, you can define LR there :)
I can initialize the object just fine:
ngOnInit() {
this.cy = cytoscapeService.cytoscape( Object.assign( {
container : this.el.nativeElement,
}, DATA_FLOW_CYTOSCAPE_CONFIG ) );
this.cy.panzoom( Object.assign(
{ minZoom : 0, maxZoom : 10 }, // arbitrary numbers
relateConfig.panzoomDefaults,
) );
However, no matter what numbers I use, or as my graph changes views, I can't seem to update the max/min appearance of the zoom slider. What I mean is, if the view can only be zoomed from, let's say, 1-2, the entire slider should slide between the min (1) and the max (2).
private runLayout() {
this.cy.minZoom( 1e-50 );
const layout = this.cy.layout( DATA_FLOW_LAYOUT_CONFIG );
layout.on( 'layoutstop', () => {
this.cy.minZoom( this.cy.zoom() );
this.cy.panzoom( 'destroy' );
this.cy.panzoom( Object.assign(
{ minZoom : this.cy.zoom() },
relateConfig.panzoomDefaults,
) );
} );
This adjusts the zoom limits, but also just restricts the amount of movement the slider has, it doesn't recalculate the min and max slider positions.
Does this make sense? Any thoughts?
Ex:
Initial slider movement range -
[|----------[]----------|]
View changed, bounds limited -
[--|--[]---|-------------]
The problem here is with Object.assign.
this.cy.panzoom( Object.assign(
{ minZoom : this.cy.zoom() },
relateConfig.panzoomDefaults,
) );
If you keep the defaults for panZoom stored somewhere (relateConfig.panzoomDefaults in my case), they won't get overwritten with Object.assign. Removing the values I wanted to be able to change immediately allowed me to change them as needed using Object.assign.
I'm having some trouble while creating a camera Tween in THREE.js, specifically at the end and beginning of the animation, there always seems to be a camera 'jump', meaning that the camera flickers once the animation starts and once the animation ends. For reference, what I'm doing is :
Camera is overlooking a scenario from above.
When user clicks on an element of the scenario, the camera zooms on it (by a TWEEN) and when it's close enough, the OrbitControls target change to the centroid of the selected element, and autorotate starts, so the user sees the element rotating in the center of the screen.
When user clicks again, the camera zooms out to its initial position (by a TWEEN) and goes back to the original controls.
I'm experiencing 'jumps/flickers' at the beginning and end of each TWEEN.
This is my tween function :
var origpos = new THREE.Vector3().copy(camera.position); // original position
var origrot = new THREE.Euler().copy(camera.rotation); // original rotation
camera.position.set(x, y+500, z+variation);
camera.lookAt(new THREE.Vector3(x,y,z));
var dstrot = new THREE.Euler().copy(camera.rotation)
// reset original position and rotation
camera.position.set(origpos.x, origpos.y, origpos.z);
camera.rotation.set(origrot.x, origrot.y, origrot.z);
options = {duration: 3000};
//
// Tweening
//
// position
new TWEEN.Tween(camera.position).to({
x: x,
y: y+500,
z: z
}, options.duration).easing(TWEEN.Easing.Cubic.Out).onUpdate(function () {
camera.lookAt(new THREE.Vector3(x,y,z));
}).onComplete(function () {
controls.autoRotate = true;
controls.autoRotateSpeed = 5.0;
controls.target = new THREE.Vector3(x, y, z);
}).start();
// rotation (using slerp)
(function () {
var qa = camera.quaternion; // src quaternion
var qb = new THREE.Quaternion().setFromEuler(dstrot); // dst quaternion
var qm = new THREE.Quaternion();
var o = {t: 0};
new TWEEN.Tween(o).to({t: 1}, options.duration).onUpdate(function () {
THREE.Quaternion.slerp(qa, qb, qm, o.t);
camera.quaternion.set(qm.x, qm.y, qm.z, qm.w);
}).start();
}).call(this);
OK, it seems that the issue was in itself with the method I was using to rotate the camera, using quaternions and SLERP.
I found that the best way (easier and without flicker/jump) would be to interpolate the parameters of camera.rotation instead of interpolating the quaternions.
So, a Tween of camera.rotation.the_axis_where_you_want_to_rotate works perfectly, and done concurrently with a Tween on the position, achieves the effect I was looking for.
I am not sure how best to utilize the edge weight (e.g. strength of interaction between two interacting proteins) while generating a force directed layout using the CoSE plugin in cytoscape.js. Could someone provide any pointers. Should it be "idealEdgeLength" or "edgeElasticity"?
(EDIT) Following is a figure showing what I currently get (A) and what I am trying to achieve (B). Also below are the parameters I used for generating the layout.
Thanks,
Datta.
PS: Click to view a figure showing the current (labelled "A") and expected (labelled "B") layouts. Following are layout options for "A".
var options = {
name: 'cose',
// Called on `layoutready`
ready: function () { },
// Called on `layoutstop`
stop: function () { },
// Whether to animate while running the layout
animate: true,
// Number of iterations between consecutive screen positions update (0 -> only updated on the end)
refresh: 20,
// Whether to fit the network view after when done
fit: true,
// Padding on fit
padding: 30,
// Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
boundingBox: undefined,
componentSpacing: 100,
// Whether to randomize node positions on the beginning
randomize: true,
// Whether to use the JS console to print debug messages
debug: false,
// Node repulsion (non overlapping) multiplier
nodeRepulsion: 400000,
// Node repulsion (overlapping) multiplier
nodeOverlap: 10,
// Ideal edge (non nested) length
idealEdgeLength: 10,
// Divisor to compute edge forces
edgeElasticity: 100,
// Nesting factor (multiplier) to compute ideal edge length for nested edges
nestingFactor: 5,
// Gravity force (constant)
gravity: 80,
// Maximum number of iterations to perform
numIter: 10000,
// Initial temperature (maximum node displacement)
initialTemp: 100,
// Cooling factor (how the temperature is reduced between consecutive iterations
coolingFactor: 0.95,
// Lower temperature threshold (below this point the layout will end)
minTemp: 1.0
};
You can specify functions instead of static numbers for some key CoSE layout settings. The functions take edges (or nodes, in some cases), so you can tailor the layout based on edge properties.
So you could do something like this:
idealEdgeLength: function (edge) {
// Default is: 10
// Instead, base it on "weight"
return edge.data().weight * .5
},
edgeElasticity: function (edge) {
// Default is: 100
// Instead, base it on "weight"
return edge.data().weight * 4
},
You'll have to experiment with ranges that work with the layout engine and the range of weight you are expecting as input, but that approach should work AOK.
The ideal edge length specifies a default-like value, whereas the elasticity specifies one of the forces that determine the final length. In general for physics simulation layouts, you will need to experiment with different values and evaluate the results for your specific graphs.