Consider the following code:
<div class="red-square"
*ngIf="someCondition"
[#showHideAnimation]
></div>
Is there a way to cause aforementioned div to disappear with random animation?
Random animation being, for example, rotation of the object by any number of degrees between, say, 30 and 150.
I have an idea, but it's not randomized per se.
given your animation
animations: [
trigger('animationName', [
state('void', style({
// hidden case
})),
state('*', style({
// visible case
})),
transition(':enter', animate('TIME [DELAY] EASING')),
transition(':leave', animate('TIME [DELAY] EASING'))
])
]
What you could do is make a global function like so
function randomizeAnimation(propertiesNumber: number, state: number) {
let properties = ['borderBottom', 'opacity', 'All of the properties you want to animate here'];
let randomIndex = () => Math.random() * properties.length;
let style = {};
for (let i = 0; i < propertiesNumber; i++) {
let index = randomIndex();
let voidValue = '0';
let showValue = '*';
// Why it's not "randomized" : you need to make custom rules here. Example : colors
if (properties[index].toLowerCase().includes('color')) {
let RdmOct = () => Math.random() * 256;
let generateRandomColor = () => `rgb(${RdmOct()}, ${RdmOct()}, ${RdmOct()})`;
voidValue = generateRandomColor();
showValue = generateRandomColor();
}
style[properties[index]] = state ? voidValue : showValue;
}
return style;
}
What this function does is that it takes a number of properties to animate, and an animation state (boolean, or 0/1). It then choses random properties in its array, making it "random". If the properties have a special use case, such as colors (the wildcard '*' won't work), then you have to handle it. Once it has created the random style, it returns it to be used in the animate function. It's not "randomized" like a Math.random(), but it could do the trick !
In your component, you can now call this function in your animate :
animations: [
trigger('animationName', [
state('void', style(randomizeAnimation(1, 0))),
state('void', style(randomizeAnimation(1, 1))),
transition(':enter', animate('275ms ease-out')),
transition(':leave', animate('275ms ease-in'))
])
]
I'm not sure it would work, but that's close enought for your need I guess !
EDIT you could even go further by setting an Interval in your animate, changing the animation every minute or so. But if this method doesn't even work ... I won't lose more time to write this one ahah
For animations with random values you will need to create animations that accept parameters. This will allow you to provide different values in the animation so that you can get random behavior. You will need to setup one or more animations depending on what you want to animate and set parameters on the values like so:
animations: [
trigger('randomAnimation', [
transition('* => colorFade', [
animate("500ms ease-in", keyframes([
style({'background-color': "{{color}}"}),
style({'opacity': "{{opacity}}"}),
]))
], {params : { color: "yellow", opacity: "0" }}),
transition('rotateFade', [
animate("{{time}}ms ease-in", keyframes([
style({'transform': 'rotate({{rotate}}deg);'}),
style({'opacity': "{{opacity}}"}),
]))
], {params : { time: "500", rotate: "45", opacity: "0.6 }})
])
]
And then in the view you can bind the animation to an animation object that has the random values in it.
<div class="red-square" [#randomAnimation]="animationConfig"></div>
And in your component you can create the object that will make the animation random.
public setRandomAnimation() {
this.animationConfig = {
value: Math.random() > 0.5 ? 'colorFade' : 'rotateFade',
params: {
time: Math.floor(Math.random() * 5000) + 200,
color: `#${(Math.floor(Math.random() * 255)).toString(16)}${(Math.floor(Math.random() * 255)).toString(16)}${(Math.floor(Math.random() * 255)).toString(16)}`,
opacity: Math.random(),
rotate: Math.floor(Math.random() * 360),
};
}
The above method is just an example you could expand this much further and not cram it all into one method. The parameters that are not used by the animation will be ignored so it is okay to specify rotate even though it is not used in colorFade for example.
PREVIOUS ANSWER
You can define any number of animation states and then set up transitions so that when they go from any state to a specific state a certain animation will occur. Here is an example of what the animation states might look like:
animations: [
trigger('randomAnimation', [
transition('* => yellowDisappear', [
animate(300, keyframes([
style({'background-color': 'yellow'}),
style({opacity: 0})
])),
transition('* => rotateFade', [
animate(300, keyframes([
style({'transform': 'rotate(45deg);'}),
style({opacity: 0.6})
]))
])
]
You can then specify the animation that you want to apply in the template.
<div class="red-square" [#randomAnimation]="'yellowDisappear'"></div>
<div class="red-square" [#randomAnimation]="'rotateFade'"></div>
If you want to have it occur randomly I would set up some kind of Observable that would change the animation randomly and if you want it to occur on certain conditions then I would make a method in the component to set the current state of the animation based on certain conditions.
Animations in Angular are a little tricky but there is good information in the tutorial and Matias Niemelä (one of the lead developers of the Angular animation module) wrote a good article on it as well. I would recommend checking these out if your project is going to make use of animations
I'm not sure if this will work, but you can add a state to the animated div like so:
<div class="red-square"
*ngIf="someCondition"
[#showHideAnimation]="getRandomState()"
></div>
The getRandomState method can return a couple of predefined strings randomly.
Next you only need to create transitions for each of these strings to void, for example:
transition('yellowFirstState => void',[
style({'background-color':'yellow'}),
animate(100)
])
Related
I want to test if a particular Matter body is a circle or not, as in:
const compounds = Matter.Composite.allBodies(engine.world)
compounds.forEach(compound => compound.parts.forEach(part => {
const isCircle = ???
if (isCircle) console.log(part.id, 'is a circle')
else console.log(part.id, 'is not a circle')
})
I can't find an official way to test if a Matter body was created as a circle. How can I test if a body was created with new Matter.Body.Circle versus another Body constructor?
You can console.log(a_circle) and check for something to identify a circle by.
I think you can check for a_circle.circleRadius or a_circle.label=='Circle Body'
EDIT: I have looked at the source code before posting this. It's a safe bet (for now as there is no documentation) because you can see that otherwise is just a polygon.
Matter.Bodies.circle = function(x, y, radius, options, maxSides) {
options = options || {};
var circle = {
label: 'Circle Body',
circleRadius: radius
};
// approximate circles with polygons until true circles implemented in SAT
maxSides = maxSides || 25;
var sides = Math.ceil(Math.max(10, Math.min(maxSides, radius)));
// optimisation: always use even number of sides (half the number of unique axes)
if (sides % 2 === 1)
sides += 1;
return Bodies.polygon(x, y, sides, radius, Common.extend({}, circle, options));
}
The other answer suggests looking for circle-specific properties. One problem is, these can change in future Matter.js releases. Also, it doesn't make for readable, intuitive code, and can lead to surprising bugs when additional body types wind up containing a property unexpectedly.
Better is to use the internal label property (also suggested in that answer), which should be stable and defaults to the seemingly-useful "Rectangle Body" and "Circle Body". For simple use cases, this works. Since it's possible to set the label to an object to store arbitrary custom data on the body, it's tempting to go further and use labels for just about everything.
However, I generally ignore labels. The reason is that it pushes too much of the client logic into a physics library that's not really designed for entity management. Furthermore, either of these approaches (labels or body-specific properties) involves iterating all of the bodies to filter out the type you're interested in.
Although no context was provided about the app, having to call allBodies often seems like a potential antipattern. It might be time to consider a redesign so you don't have to. What if you have 5 circles and 500 other bodies? Recursively iterating all 500 on every frame just to find the 5 is a huge waste of resources to achieve something that should be easy and efficient.
My preferred solution for entity management is to simply keep track of each type upon creation, putting them into data structures that are tuned to application-specific needs.
For example, the following script shows a method of efficiently determining body type by presenting the body as a key to a pre-built types map.
const engine = Matter.Engine.create();
engine.gravity.y = 0; // enable top-down
const map = {width: 300, height: 300};
const render = Matter.Render.create({
element: document.querySelector("#container"),
engine,
options: {...map, wireframes: false},
});
const rnd = n => ~~(Math.random() * n);
const rects = [...Array(20)].map(() => Matter.Bodies.rectangle(
rnd(map.width), // x
rnd(map.height), // y
rnd(10) + 15, // w
rnd(10) + 15, // h
{
angle: rnd(Math.PI * 2),
render: {fillStyle: "pink"}
}
));
const circles = [...Array(20)].map(() => Matter.Bodies.circle(
rnd(map.width), // x
rnd(map.height), // y
rnd(5) + 10, // r
{render: {fillStyle: "red"}}
));
const walls = [
Matter.Bodies.rectangle(
0, map.height / 2, 20, map.height, {
isStatic: true, render: {fillStyle: "yellow"}
}
),
Matter.Bodies.rectangle(
map.width / 2, 0, map.width, 20, {
isStatic: true, render: {fillStyle: "yellow"}
}
),
Matter.Bodies.rectangle(
map.width, map.height / 2, 20, map.height, {
isStatic: true, render: {fillStyle: "yellow"}
}
),
Matter.Bodies.rectangle(
map.width / 2, map.height, map.width, 20, {
isStatic: true, render: {fillStyle: "yellow"}
}
),
];
const rectangle = Symbol("rectangle");
const circle = Symbol("circle");
const wall = Symbol("wall");
const types = new Map([
...rects.map(e => [e, rectangle]),
...circles.map(e => [e, circle]),
...walls.map(e => [e, wall]),
]);
const bodies = [...types.keys()];
const mouseConstraint = Matter.MouseConstraint.create(
engine, {element: document.querySelector("#container")}
);
Matter.Composite.add(engine.world, [
...bodies, mouseConstraint
]);
const runner = Matter.Runner.create();
Matter.Events.on(runner, "tick", event => {
const underMouse = Matter.Query.point(
bodies,
mouseConstraint.mouse.position
);
if (underMouse.length) {
const descriptions = underMouse.map(e =>
types.get(e).description
);
document.querySelector("#type-hover").textContent = `
${descriptions.join(", ")} hovered
`;
}
else {
document.querySelector("#type-hover").textContent = `
[hover a body]
`;
}
if (mouseConstraint.body) {
document.querySelector("#type-click").textContent = `
${types.get(mouseConstraint.body).description} selected
`;
}
else {
document.querySelector("#type-click").textContent = `
[click and drag a body]
`;
}
});
Matter.Render.run(render);
Matter.Runner.run(runner, engine);
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
<h3 id="type-click">[click and drag a body]</h3>
<h3 id="type-hover">[hover a body]</h3>
<div id="container"></div>
If creating and destroying bodies can happen dynamically, a function would need to be written to handle data structure bookkeeping.
Another approach that might work well for some apps is to have a few type-specific sets or maps. This allows you to quickly access all entities of a particular type. This becomes particularly useful once you begin composing bodies as properties of custom classes.
There's no reason you can't have both structures--a reverse lookup that gives the type or custom class given a MJS body, and a structure that contains references to all entities or MJS bodies of a particlar type.
The reverse lookup could enable logic like "on click, take an action on a specific MJS body depending on its type" or "on click, locate my custom class/model associated with this MJS body", while collections support logic like "destroy all enemies".
Ideally, code shouldn't be doing much type-checking. With proper OOP design, you can implement classes that respond correctly to methods regardless of their type. For example, if you have Enemy and Ally classes that each respond to a click, you might create a method called handleClick in each class. This allows you to use code like clickedEntity.handleClick(); without having to know whether clickedEntity is an Enemy or Ally, thereby avoiding the need for a "get type" operation entirely.
For more design suggestions for Matter.js projects, see:
How do you access a body by its label in MatterJS?
My own model in matter.js
In my training set, my classes are not represented equally. Therefore, I'm trying to use the classWeight option of the model.fit function. Quote from the docs:
classWeight ({[classIndex: string]: number}) Optional dictionary mapping class indices (integers) to a weight (float) to apply to the model's loss for the samples from this class during training. This can be useful to tell the model to "pay more attention" to samples from an under-represented class.
So this seems to be exactly what I'm looking for, but I'm not able to figure out how to use it. The classIndex is nowhere else present in the documentation and I don't understand how a class can be written as an index. As my code is one-hot encoded I even tried to use the index of that (0 for [1,0,0], etc.), but it did not work (see below).
Here is a minimal code sample:
const xs = tf.tensor2d([ [1,2,3,4,5,6], /* ... */ ]); // shape: [1000,6]
const ys = tf.tensor2d([ [1,0,0], /* ... */ ]); // shape: [1000,3] (one-hot encoded classes)
const model = tf.sequential();
// ... some layers
await model.fit(xs, ys, {
/* ... */
classWeight: {
0: 10000, // doesn't do anything
1: 1,
2: 1,
},
});
I would expect my model to pay "more attention" to my first class ([1,0,0]) and therefore predict it more often. But it seems Tensorflow.js is just ignoring the parameter.
Is there a way to change the column widths in an Ext.dashboard.Dashboard after it has been rendered? It is created with a config value of:
columnWidths: [
0.35,
0.40,
0.25
]
I want to dynamically change it to:
columnWidths: [
0.5,
0.25,
0.25
]
Changing the columnWidths property directly or with setConfig does not update the dashboard. It doesn't appear to have a method for "refresh" or anything else that obviously serves the same purpose. The individual dashboard-columns have a setWidth function but that doesn't seem to do anything either.
I couldn't find anything in the API that managed this automatically but you can manually update the columnWidth values of each child component in the dashboard and then call updateLayout:
function setColumnWidths(dashboard, columnWidths){
var i = 0;
dashboard.items.each(function(item){
if(item instanceof Ext.resizer.Splitter)
return; // ignore
item.columnWidth = columnWidths[i++] || 1;
});
dashboard.updateLayout();
}
» Fiddle
If I have an image that I apply a filter to, e.g. Lomo filter, is there way to make that the current Caman instance?
Meaning, if I then want to then play about with the brightness on the image that I applied the filter to, and use this.revert(); to reset the brightness, I want it to revert to the canvas with the filter on it that I just applied.
Is this possible?
I'm having a nightmare with trying to apply many effects, only one at once (except for preset filters), and carry the state through...
If i understand, you want to apply filter ("Lomo") as shown on their example page and then fiddle with some properties (like brightness) and then revert changes back to "Lomo" filter?
Why not just click on filter ("Lomo") again?
EDIT:
You should probably take a look at guide and implement your own method with default values like in filters.
u.Filter.register("lomo", function (D) {
if (D == null) {
D = true
}
this.brightness(15);
this.exposure(15);
this.curves("rgb", [0, 0], [200, 0], [155, 255], [255, 255]);
this.saturation(-20);
this.gamma(1.8);
if (D) {
this.vignette("50%", 60)
}
return this.brightness(5)
});
I dont think your requirement comes "out of the box".
If i understand you correctly , You want to apply a filter and play with other effects like brightness and contrast etc.,
I made some code which will work according to your need
Caman('#canvas-camanImage',"./../media/caman.png", function () {
this.revert(false);
for(var i = 0 ;i<selectedPresets.length;i++){
this[selectedPresets[i]]();
}
for(var key in effect){
this[key](effect[key].value);
}
this.render(function () {
});
in the above code i am storing all effects like brightness contrast in effect variable like effect = {
brightness : {
min : -100,
max: 100,
value : 0
},
contrast : {
min : -100,
max: 100,
value : 0
},
saturation : {
min : -100,
max: 100,
value : 0
}
};
and presets in an array
presets = [
{filter:'vintage',name : 'Vintage'},
{filter:'lomo',name:'Lomo'},
{filter: 'clarity', name:'Clarity'},
{filter:'sinCity', name:'Sin City'}
];
So every time you add any preset or change any effect value i am changing the values in variable and rendering canvas again
It is working very fine for me Let me know if your concern is something else
I have a list of colors, that needs to be animated as a document body background-color.
var bgs = [
"BlanchedAlmond",
"Blue",
"BlueViolet",
"Brown",
"BurlyWood",
"CadetBlue",
"Chartreuse",
"Chocolate",
"Coral",
"CornflowerBlue",
"Cornsilk",
"Crimson",
"Cyan",
"DarkBlue",
"DarkCyan"
];
Now, using colorToHex() custom function for mootools, I ended up with the following code:
window.addEvent('domready', function() {
var current;
(function() {
selected = ~~(Math.random() * bgs.length);
// is it a right way to avoid the repetition?
current = (selected == current) ? ((bgs.length-1) % (selected+1)) : selected;
// -1 is to avoid the edge case,
// +1 is to avoid the NaN in case select is 0
$(document.body).set('tween', {duration: '1500'})
.tween("background-color",bgs[current].colorToHex());
}).periodical(1000);
});
Questions
(optimization of the aforementioned chunks of code) From the performance optimization perspective, is there a better way to perform this animation?
(vs. jQuery) Would the jQuery counterpart be more efficient and elegant?
Ok, I had 2 minutes to check it and try to make it better :)
..here is the working example : http://jsbin.com/evofuw/2 (and the code here http://jsbin.com/evofuw/2/edit#javascript)
..btw, I found some problems in your version:
selected = ~~(Math.random() * bgs.length); you haven't defined selected, + there is a built in getRandom() method available for Arrays in MooTools.
to avoid repetition and all that 'mess' you did, delete that random element from that array ;)
Why you're not using the onComplete tween callback? Using periodical (setInterval) is never the same as using callbacks (and most of the times is not correct).
Each time you're running that anonym function you're retrieving (by $) the body that is not cached. Ok, it's the body but it's a good habit to cache elements :)
About q#2, definitely not. :)
Here is my version:
// a namespace, more elegant :)
var app = {};
// the array with colors
app.bgs = [
"BlanchedAlmond",
"Blue",
"BlueViolet",
"Brown",
"BurlyWood",
"CadetBlue",
"Chartreuse",
"Chocolate",
"Coral",
"CornflowerBlue",
"Cornsilk",
"Crimson",
"Cyan",
"DarkBlue",
"DarkCyan"
];
// the function to change bg color
app.changeBGColor = function( b ){
// random select element
var selected = app.bgs.getRandom();
// delete that element from the array
app.bgs.erase(selected);
// tween background color
b.tween('background-color',selected.colorToHex());
}
window.addEvent('domready', function() {
// cache body element
var b = $(document.body);
// set tween stuff
b.set('tween', {
duration : 1500,
onComplete : function(){
if( app.bgs.length ) { // if the array contains elements, change color
app.changeBGColor(b);
} else { // otherwise do nothing
console.log('array empty! end!');
}
}
});
// start 1st time
app.changeBGColor(b);
});
ps. if you want to animate 'forever', just use another array (where to push the deleted values) and then swap array when the other one is empty
Answer 1:
I agree with stecb; You can cache the values and make use of getRandom(). But in order to continue the animation indefinitely, you don't want to delete the element from array. Therefore, to avoid the duplicate selection consecutively, you just need to switch the places of (cached_length-1) and (selected+1).
Also, the method colorToHex suggested by csuwldcat (the one you cited) is most costly in the entire animation in terms of performance. I would highly suggest you use Hex code in the bgs array. If that is not an option, the you must use colourNameToHex() function by Greg on the same page.
Finally periodical( _interval ) is for setting the delay between the adjacent tween ops whereas duration is the time taken by one color transition. Mootools also provides a delay() function to pause the sequential flow. But in this case, use of priodical() to fire the transition after fixed interval makes sense.
Here is another version of your code:
window.addEvent('domready', function() {
var cached_length = bgs.length;
var myElement = new Fx.Tween(document.body, {duration: '1500'});
var current, selected;
(function() {
selected = ~~(Math.random() * bgs.length);
current = (selected == current) ?
((selected + 1) % (cached_length - 1)) : selected;
/* console.info("current: "+bgs[current]); */
myElement.start("background-color",bgs[current]); // if you use Hex codes
// instead of color names
}).periodical(1000);
});
Answer 2:
Since jQuery would require a plugin jQuery.Color to animate the background-color, that kind of an extra layered complexity may effect the performance, but it cannot compete the performance of Mootools (which is an extended Javascript core as opposed to a layered framework).