React Cytoscape JS : All nodes are accumulated in one position - javascript

When creating a path using dagre, the whole nodes accumulate in one position. How can we set default positions for nodes ( Cytoscape js without react works fine) instead of setting position separately using position attribute for nodes.
const layout = {
name: "dagre",
rankDir: "LR"
}
pageData = < CytoscapeComponent
elements = {
CytoscapeComponent.normalizeElements({
nodes: nodess,
edges: edgess,
layout: layout,
})
}
pan = {
{
x: 200,
y: 200
}
}
autounselectify = {
true
}
userZoomingEnabled = {
false
}
boxSelectionEnabled = {
false
}
style = {
{
width: "1200px",
height: "1000px"
}
}
/>
return (
< div
{
pageData
}
< /div>
);
Expected result:
Current result:

There is a way to force the calculation of node positions as they are added. This is also useful when the elements of the graph change dynamically with the state of the component and the graph has to be rendered again with updated node positions.
<CytoscapeComponent
cy={(cy) => {
this.cy = cy
cy.on('add', 'node', _evt => {
cy.layout(this.state.layout).run()
cy.fit()
})
}}
/>

Here is what worked for me:
cytoscape.use(fcose)
//..then in my render...
<CytoscapeComponent
elements={elements1}
layout={{
animate: true,
animationDuration: undefined,
animationEasing: undefined,
boundingBox: undefined,
componentSpacing: 40,
coolingFactor: 0.99,
fit: true,
gravity: 1,
initialTemp: 1000,
minTemp: 1.0,
name: 'fcose',
nestingFactor: 1.2,
nodeDimensionsIncludeLabels: false,
nodeOverlap: 4,
numIter: 1000,
padding: 30,
position(node) {
return { row: node.data('row'), col: node.data('col') }
},
randomize: true,
refresh: 20,
}}
style={{ width: '600px', height: '300px' }}
/>

You may try "Euler" layout instead of "Dagre" layout

Related

How do I make object fall on impact in Matter.js?

I'm using Matter.js for some graphics and want this rectangle
let title = Bodies.rectangle(w / 2.4, height / 1.8, 300, 100, {
isStatic: true,
})
to get isStatic: false and fall when it's hit by some circles that are raining down on it. I've done some extensive Googling, but haven't really found anything else but this:
Events.on(engine, 'collisionStart', function (event) {
event.pairs.forEach(function (obj) {
console.log(
'BodyA is static: ' + obj.bodyA.isStatic + '. BodyB is static: ' + obj.bodyB.isStatic
)
})
})
This gives me all the collisions happening, but I haven't figured out how to set isStatic: false when something hits. Appreciate your help!
You can call Matter.Body.setStatic(body, false) on the body in question to make it active.
Here's an example:
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine,
options: {width: 400, height: 400, wireframes: false},
});
const fallingBody = Matter.Bodies.rectangle(
200, 0, 20, 20, {
frictionAir: 0.1,
density: 0.8,
render: {fillStyle: "red"},
},
);
const wall = Matter.Bodies.rectangle(
200, 150, 400, 20, {
frictionAir: 0.05,
isStatic: true,
render: {fillStyle: "green"}
},
);
Matter.Composite.add(engine.world, [fallingBody, wall]);
Matter.Events.on(engine, "collisionStart", event => {
if (
wall.isStatic &&
event.pairs.some(e => Object.values(e).includes(wall))
) {
Matter.Body.setStatic(wall, false);
}
});
Matter.Render.run(render);
Matter.Runner.run(Matter.Runner.create(), engine);
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>

How can i make a child animation happen every time the parent animation is beginning using framer motion & react

I'm trying to make a squeezing bubble animation on repeat, using framer motion & react, but I cant make the squeeze animation happen every time the movement animation is beginning.
instead only the first time the animations run it works but after that only the movement animation repeats itself, if I try to repeat the squeeze animation it just gets out of order
import React from "react";
import styled from "styled-components";
import { motion } from "framer-motion";
const Bubble = () => {
const shapeVariants = {
hidden: {
height: 450,
width: 50,
},
visible: {
height: 250,
width: 250,
transition: {
type: "spring",
bounce: 1,
stiffness: 700,
ease: "easeIn",
},
},
};
const MoveVariants = {
hidden: {
y: 1300,
},
visible: {
y: -280,
transition: {
duration: 2,
ease: "easeIn",
repeat: Infinity,
},
},
};
return (
<motion.div variants={MoveVariants} initial={"hidden"} animate={"visible"}>
<RoundDiv
onAnimationComplete={(definition) => console.log(definition)}
variants={shapeVariants}
/>
</motion.div>
);
};
const RoundDiv = styled(motion.div)`
height: 250px;
width: 250px;
background-color: #05386b;
border-radius: 50%;
`;
export default Bubble;
You just needed to add to your shapeVariants transition to get them to sync up.
import React from "react";
import styled from "styled-components";
import { motion } from "framer-motion";
const Bubble = () => {
const shapeVariants = {
hidden: {
height: 450,
width: 50,
},
visible: {
height: 250,
width: 250,
transition: {
type: "spring",
bounce: 1,
stiffness: 700,
ease: "easeIn",
duration: 2, /* new */
repeat: Infinity, /* new */
},
},
};
const MoveVariants = {
hidden: {
y: 1300,
},
visible: {
y: -280,
transition: {
duration: 2,
ease: "easeIn",
repeat: Infinity,
},
},
};
return (
<motion.div
variants={MoveVariants}
initial={"hidden"}
animate={"visible"}
>
<RoundDiv
onAnimationComplete={(definition) => console.log(definition)}
variants={shapeVariants}
/>
</motion.div>
);
};
const RoundDiv = styled(motion.div)`
height: 250px;
width: 250px;
background-color: #05386b;
border-radius: 50%;
`;
export default Bubble;
I would also recommend using originX and originY to manipulate the spring transition on the bubble otherwise it will animate the bounce based on the top left corner. I would use percentage values such as originX: "50%" but it depends on the effect you are looking for.
The cascading animation in framer-motion is powered by the variant being propagated through the children.
You are running into this setback because you are only animating to the `visible variant once. Thus the variant propagation only happens once.
Potential Solutions
Dumb solution: include a duration into the shapeVariant and make it also repeat then manually time your animation to where you need it. This isn't optimal because you probably want your bubble animation to be type spring?
const shapeVariants = {
hidden: {
height: 450,
width: 50,
},
visible: {
height: 250,
width: 250,
transition: {
type: "spring",
bounce: 1,
stiffness: 700,
ease: "easeIn",
duration: 2,
repeat: Infinity
},
},
};
Alternatively you could control your animation with an effect that would use setTimeout or something to change the variant of the parent over and over to get the cascading effect

To resize and make the Violin chart of PotlyJS responsive

I want the violin chart (I'm using plotlyjs library) to be responsive. But also don't want it to compress so much (it is compressing according to the div it is kept in).
I have tried to turn the autosize property of violin to be false and then set the height and width. In this case the chart does not compress (stays the way I want it to be), but it loses its responsiveness. Is there a way to make this chart responsive yet no so compressed?
Here is my code:
<Plot
config = {{ displayModeBar: false }}
data={[
{
type: 'violin',
y: this.props.data,
points: 'none',
box: {
visible: true
},
boxpoints: false,
line: {
color: 'red'
},
opacity: 0.6,
meanline: {
visible: true
},
x0: "OEE"
}
]}
layout={{
title: "Comparison",
yaxis: {
zeroline: false
},
// autosize: false,
// height: 300,
// width: 500,
// responsive: true
}}
useResizeHandler= {true}
style= {{width: "100%", height: "100%"}}
/>
The div inside which violin is kept:
<div className="chart-wrapper" style={{ height: "35vh" }}>
<ViolinChart data={this.state.violinChartData} />
</div>
I got the solution to the above question.
PlotlyJS also provides a "margin" property for its charts. So providing margins will let you adjust the chart the way you want it to be
var layout = {
margin: {
l: 25,
r: 25,
b: 25,
t: 25
}
};
This is what i added to my code. Setting automargin = true will automatically increase the margin size.
More about this can be found here.

Rex UI Scrollable Panel: Unable to understand how it works

I'm working on a game in Phaser 3 and I need to use some sort of scrollable panel, so I chose to use Rex UI (if you know any alternatives, please tell me. At first I wanted to use phaser-list-view from npm but it's only in phaser 2). It seems like these plugins do not have much documentation. The docs are on this site: Notes of Phaser 3.
So I have my game configuration and I'm loading like this (oversimplified):
import UIPlugin from '../plugins/ui-plugin.js';
const config = {
// ...
plugins: {
scene: [{
key: 'rexUI',
plugin: UIPlugin,
mapping: 'rexUI'
}]
}
// ...
};
const game = new Phaser.Game(config);
And in a scene I try to use it:
export default class MyScene extends Phaser.Scene {
create() {
this.rexUI.add.scrollablePanel({
x: 0, y: 0,
width: innerWidth,
height: innerHeight/2,
scrollMode: 'horizontal',
panel: {
child: this.add.container().setSize(2 * innerWidth, innerHeight/2)
.add(this.itemImage(1))
.add(this.itemImage(2))
// ...
// (I'm actually using for-loop and save this container in a
// separate variable, but I'm over simplifying this snippet)
mask: false
},
slider: {
track: this.add.graphics({x: 0, y: innerHeight/2 + 10})
.fillRect(0, 0, innerWidth, 30).fillStyle(SOME_LIGHT_COLOR)
.setInteractive(
new Phaser.Geom.Rectangle(0, 0, innerWidth, 30),
Phaser.Geom.Rectangle.Contains
),
thumb: this.add.graphics({x: 0, y: innerWidth/2 + 10})
.fillRect(0, 0, 50, 30).fillStyle(SOME_DARK_COLOR)
.setInteractive(
new Phaser.Geom.Rectangle(0, 0, 50, 30),
Phaser.Geom.Rectangle.Contains
)
}
}).layout()
}
itemImage(n) {
return this.add.image((innerHeight/2 + 30) * (n-1), 0, 'item' + n)
.setDisplaySize(innerHeight/2, innerHeight/2)
}
}
There are many problems. Firstly with the above code I get the error:
Uncaught TypeError: this.child.getAllChildren is not a function
at e.Xo [as resetChildPosition] (<anonymous>:1:205731)
at e.layout (<anonymous>:1:206243)
at e.layout (<anonymous>:1:126859)
at e.layout (<anonymous>:1:126859)
at e.value (<anonymous>:1:172299)
at MyScene.create (MyScene.js:117)
at initialize.create (phaser.min.js:1)
at initialize.loadComplete (phaser.min.js:1)
at initialize.h.emit (phaser.min.js:1)
at initialize.loadComplete (phaser.min.js:1)
The error goes away if I just remove .layout(). But however, the thumb on the scroller is not anywhere in the scene and I can't even scroll the container.
The docs don't say what exacly should go in panel.child, scrolller.track and scroller.thumb
Can someone help me out of this?
try this, just call createTable():
me.createTable({
x: 390,
y: 410,
width: 350,
height: 220,
rank: [{"score":1520,"userID":1,"userName":"Augustus Nico"},{"score":360,"userID":"_2hzxb91byxw","userName":"lipão"},{"score":250,"userID":3,"userName":"Sarão"},{"score":200,"userID":5,"userName":"Bruna Santini"},{"score":160,"userID":4,"userName":"Paulo Junior"},{"score":100,"userID":2,"userName":"Vilasboas"}]
});
const COLOR_PRIMARY = 0x4e342e;
const COLOR_LIGHT = 0x7b5e57;
const COLOR_DARK = 0x260e04;
const COLOR_WHITE = 0xffffff;
export const createTable = ({ x, y, width, height, rank }) => {
var scrollablePanel = this.rexUI.add
.scrollablePanel({
x: x,
y: y,
width: width,
height: height,
scrollMode: 0,
background: this.rexUI.add.roundRectangle(0, 0, 2, 2, 10, COLOR_WHITE),
panel: {
child: createGrid(this, rank),
mask: {
mask: true,
padding: 1
}
},
slider: {
track: this.rexUI.add.roundRectangle(0, 0, 20, 10, 10, COLOR_LIGHT),
thumb: this.rexUI.add.roundRectangle(0, 0, 0, 0, 13, COLOR_DARK)
},
space: {
left: 10,
right: 10,
top: 10,
bottom: 10,
panel: 10,
header: 10,
footer: 10
}
})
.layout();
};
const createGrid = (scene, rank) => {
var sizer = scene.rexUI.add.gridSizer({
column: 2,
row: rank.length,
columnProportions: 1
});
rank.forEach((player, index) => {
sizer.add(
scene.createItem(scene, 0, index, player.userName), // child
0, // columnIndex
index, // rowIndex
"center", // align
0, // paddingConfig
true // expand
);
sizer.add(
scene.createItem(scene, 1, index, player.score), // child
1, // columnIndex
index, // rowIndex
"center", // align
0, // paddingConfig
true // expand
);
});
return sizer;
};
const createItem = (scene, colIdx, rowIdx, text) => {
var item = scene.rexUI.add
.label({
background: scene.rexUI.add
.roundRectangle(0, 0, 0, 0, 0, undefined)
.setStrokeStyle(2, COLOR_DARK, 1),
text: scene.add.text(0, 0, text, {
fontSize: 18,
fill: "#000"
}),
space: {
left: 10,
right: 10,
top: 10,
bottom: 10,
icon: 10
}
})
.setDepth(3);
var press = scene.rexUI.add.press(item).on("pressstart", function() {
console.log(`press ${text}`);
});
return item;
};

Draggable does not work in extjs6.5

I am using the below code -
afterListeners: function(thisEl, eOpts) {
sliderSprite = Ext.create('Ext.draw.sprite.Rect', {
width: spriteWidth, // half year width height : 20, x : 16, y : 0, draggable : true, floatable : true, 'stroke-width' : 2, fill : '#FCE5C5', stroke : '#C6B395' });
sliderSprite.show(true);
thisEl.getSurface().add(sliderSprite);
alert("before source");
new Ext.drag.Source({
element: sliderSprite,
constrain: {
// Drag only horizontal in 30px increments
horizontal: true, // snap: { // y: 30 // }
},
onDragMove: function() {
alert("inside source");
spriteHighlighter.remove();
me.onDragSprite(e, this, chartWidth, spriteWidth);
},
onDragEnd: function() {
me.refreshCharts(xPlots, bigChart, sliderSprite, firstYear, lastYear, chartWidth);
}
});
alert("outside source");
},
}
}
Now, the issue is, control doesn't go inside the Ext.drag.Source(). I get 2 alert messages ,before source and outside source. and because it doesn't go inside Ext.drag.Source().
The drag-able functionality of the element is not working. What should I do ?
First you need to be clear on which component you want to use. After that you need to put afterrender event on that component and inside of that event you can use Ext.drag.Source.
In this FIDDLE, I have created a demo using button and Ext.drag.Source.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
var buttons = [],
rendomColor = () => {
return "#" + ((1 << 24) * Math.random() | 0).toString(16);
};
for (var i = 0; i < 10; i++) {
buttons.push({
text: `Button ${i+1}`,
margin: 10,
style: `background:${rendomColor()}`
});
}
Ext.create({
xtype: 'panel',
height: window.innerHeight,
title: 'Ext.drag.Source Example',
defaults: {
xtype: 'button'
},
items: buttons,
renderTo: Ext.getBody(),
listeners: {
afterrender: function (panel) {
panel.items.items.forEach(item => {
new Ext.drag.Source({
element: item.el,
constrain: {
// Drag only vertically in 30px increments
//vertical: true,
snap: {
y: 1,
x: 1
}
}
})
})
}
}
});
}
});

Categories