How to animate component repositioning on recomposition in Jetpack Compose? - animation

I have two squares. The green one is constrained to the top, and the blue one is constrained between the green one and the bottom of the screen. When clicking on the blue square, the green square doubles in size. Since the size of the green square increases, the blue square moves downwards because of its constraints.
How do I animate the position change of the blue square? Do I have to manually calculate and animate the offset? This feels very hacky. I feel like this should be doable declaratively, since the new position is automatically calculated by the updated constraints.
Edit: Basically, I'm looking for android:animateLayoutChanges, but for Compose.
Here is my code:
#Composable
fun AnimationTest() {
ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (block1, block2) = createRefs()
var blockSize by remember { mutableStateOf(20.dp) }
Surface(
color = Color.Green,
modifier = Modifier
.size(blockSize)
.constrainAs(block1) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
) {}
Surface(
color = Color.Blue,
modifier = Modifier
.size(50.dp)
.constrainAs(block2) {
top.linkTo(block1.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.clickable {
blockSize *= 2
}
) {}
}
}

Try wrapping it inside the AnimatedContent composable. Though it is ConstraintLayout so I don't think it would work, but it just might. Give it a try and let me know. Otherwise, it is a very simple scenario, and can be easily achieved with the Layout composable, inside which you can use lerp() to achieve the animation

Related

Display Mesh On Top Of Another | Remove Overalapping | Render Order | Three.js

I have 2 obj meshes.
They both have some common areas but not completely.
I displayed them both by adding them to screen ..
Just like a mesh on top of another.
But the lower mesh overlaps the top mesh
But what I want to acheive is the lower mesh should always stay below without overlapping and giving the space to the entire top mesh.
I went through this fiddle..Fiddle with renderorder
And I tried something with this like..
var objLoader1 = new OBJLoader2();
objLoader1.load('assets/object1.obj', (root) => {
root.renderOrder = 0;
scene.add(root);
});
var objLoader2 = new OBJLoader2();
objLoader2.load('assets/object2.obj', (root) => {
root.renderOrder = 1;
scene.add(root);
});
But I don't know for what reason the overlap still stays ..
I tried...
var objLoader1 = new OBJLoader2();
objLoader1.load('assets/object1.obj', (root) => {
objLoader1.renderOrder = 0;
scene.add(root);
});
var objLoader2 = new OBJLoader2();
objLoader2.load('assets/object2.obj', (root) => {
objLoader2.renderOrder = 1;
scene.add(root);
});
Then I tried going through this Fiddle .. Another Fiddle
But when I run in I get only the lower or the upper mesh .
But I want to see both without any overlaps..
var layer1 = new Layer(camera);
composer.addPass(layer1.renderPass);
layer1.scene.add(new THREE.AmbientLight(0xFFFFFF));
var objLoader1 = new OBJLoader2();
objLoader1.load('assets/object1.obj', (root) => {
layer1.scene.add(root);
});
var layer2 = new Layer(camera);
composer.addPass(layer2.renderPass);
layer2.scene.add(new THREE.AmbientLight(0xFFFFFF));
var objLoader2 = new OBJLoader2();
objLoader2.load('assets/object2.obj', (root) => {
layer2.scene.add(root);
});
I made the material depthTest to False
But Nothing Helped..
Can anyone help me achieve what I wanted ..
If anyone couldn't figure what I mean by overlapping see the image below..
And Thanks to anyone who took time and effort to go through and help me...
You can use polygonOffset to achieve your goal, which modifies the depth value right before a fragment is written to help move polygons off of eachother without visually changing the position:
material.polygonOffset = true;
material.polygonOffsetUnit = 1;
material.polygonOffsetFactor = 1;
Here is a fiddle demonstrating the solution:
https://jsfiddle.net/5s8ey0ad/1/
Here is what the OpenGL Docs have to say about polygon offset:
When GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_LINE, or GL_POLYGON_OFFSET_POINT is enabled, each fragment's depth value will be offset after it is interpolated from the depth values of the appropriate vertices. The value of the offset is factor×DZ+r×units, where DZ is a measurement of the change in depth relative to the screen area of the polygon, and r is the smallest value that is guaranteed to produce a resolvable offset for a given implementation. The offset is added before the depth test is performed and before the value is written into the depth buffer.
You're experiencing z-fighting, which is when two or more planes occupy the same space in the depthBuffer, so the renderer doesn't know which one to render on top of the other. Render order alone doesn't fix this because they're both still on the same plane, regardless of which one gets drawn first. You have a few options to resolve this:
Move one of the beams ever so slightly up in the y-axis. A tiny fraction would give one priority over the other, and this distance may not be noticeable to the eye.
I saw your fiddle, and you forgot to add depthTest: false to your material. However, this will cause issues when depth-testing the rest of the shape, since some white is on top of the red, but also some red is on top of the white. The approach in the fiddle works only when it's a simple plane, not more complex geometries.
You can use a boolean operation that removes one shape from the other, like CSG.
I think you'd save yourself a lot of headache by using approach #1.

create a spiral UI bar in Unity

Is it possible to create a bar like this one in Unity?
The default components seem to work primitive only. I can have a rectangle as a bar or a radial bar.
This spiral bar would need to have access to a path because the color has to know how to move along the sprite.
I would use a custom shader with a sprite containing the "fill information" as the alpha channel.
On the image below, you will see your original sprite, and an other one with a gradient alpha (sorry, I'm not an expert with photoshop).
You can download the Unity shaders on their website, and pick the UI-Default.shader inside DefaultResourcesExtra/UI and tweak it a little bit so as to fill the sprite according to the alpha value of the sprite.
Something like this (not tested)
Shader "UI/FillAlpha"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_FillAmount ("Fill amount", Float) = 1
// ...
}
SubShader
{
// ...
sampler2D _MainTex;
fixed _FillAmount;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
color.a = color.a > _FillAmount ? 1 : 0 ;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
// ...
return color;
}
ENDCG
}
}
}
Then, you will be able to change the FillAmount parameter using myMaterial.SetFloat
You can use Line Renderer component to create your bar.
See documentation and examples here:
https://docs.unity3d.com/Manual/class-LineRenderer.html
https://docs.unity3d.com/352/Documentation/Components/class-LineRenderer.html
Note that Line Renderer works in a 3D space.

How to hide a html overlay label on a sphere object

I have a sphere model along with html text labels overlayed onto it at fixed positions. How can I hide them when they are behind the object when i am rotating my sphere using orbit controls?
Anyone knows about any references on stackoverflow or any examples which can solve my issue?
See this example how you could do it: http://jsfiddle.net/L0rdzbej/194/
I have put the relevant code in the updateLabelVisibility()-function, it looks like this:
var meshPosition = mesh.getWorldPosition();
var eye = camera.position.clone().sub( meshPosition );
var dot = eye.clone().normalize().dot( meshPosition.normalize() );
//IS TRUE WHEN THE MESH IS OCCLUDED BY THE SPHERE = dot value below 0.0
var ocluded = dot < -0.2;
if ( ocluded ) {
// HIDE LABEL IF CAMERA CANT SEE IT (I.E. WHEN IT IS BEHIND THE GLOBE)
label.style.visibility = "hidden";
}
else {
// DISPLAY LABEL IF MESH IS VISIBLE TO THE CAMERA
label.style.visibility = "visible";
}
Where mesh is the marker where your label is attached to. The dot is basically telling you how far around the sphere it is, within a certain distance of 90 degree. Simply said by values below zero the label is longer visible by going further around the back.
To be fair I based this off some code from: https://zeitgeist-globe.appspot.com/

How to make a menu with this effect in unity3d?

Sorry, I'll try to explain better.
I want to make a sliding menu where you can select a character. I want the character that is at the center increases in size to know that this is the current character. The effect can be seen in the game of Crossy Road when you want to select a character.
Sorry but I can't upload a imagen because i am new in the forum
I think I might be able to help you without needing too much borrowed code. There are two possibilities here:
You have a perspective camera so the "selected" item can just be closer to the camera.
You have an orthographic camera so you will have to scale things.
For perspective:
List<GameObject> characters; //contains all character.
int selectedIndex = 0; //index to the selected character.
float spacing = 10; //space between chars
void Update()
{
if(Input.GetKeyDown("RightArrow"))
{
selectIndex++;
ApplyChanges();
}
if(Input.GetKeyDown("LeftArrow"))
{
selectIndex--;
ApplyChanges();
}
}
void ApllyChanges()
{
// Make sure the selected index is within range and then space the characters.
selectedIndex = selectedIndex % character.Count();
SpaceCharacters();
}
void SpaceCharacters()
{
for(int i = 0; i < characters.Count(); ++i)
{
// characters on the left will have a negative spacing and so will be placed to the left and vice versa for characters on the right.
int offset = i - selectedIndex;
characters[i].transform.position = new Vector3(offset * spacing, 0, 0);
}
// Move the selected character closer.
characters[selectedIndex].transform.position = new Vector3(0,0,spacing);
}
For orthographic camera you will need to set the select characters transform.scale to a larger vector.
This won't animate anything or look cool. This code will just snap your characters into position.
The solution I adopted was to attach objects to the transparent buttons in a scrool rect, so as to manage 3d objects with the convenient of scrool rect interface.
Here you can find the official documentation for use scrool rect: http://docs.unity3d.com/Manual/script-ScrollRect.html
Maybe my assets can serve you ;)
https://www.assetstore.unity3d.com/en/#!/content/60233

d3 autospace overlapping tick labels

Is there a way in d3 to not draw overlapping tick labels? For example, if I have a bar chart, but the bars are only 5 pixels wide and the labels are 10 pixels wide, I end up with a cluttered mess. I'm currently working on an implementation to only draw the labels when they do not overlap. I can't find any existing way to do that, but wasn't sure if anyone else had dealt with this problem.
There is no way of doing this automatically in D3. You can set the number of ticks or the tick values explicitly (see the documentation), but you'll have to figure out the respective numbers/values yourself. Another option would be to rotate the labels such that there is less chance of them overlapping.
Alternatively, like suggested in the other answer, you could try using a force layout to place the labels. To clarify, you would use the force layout on the labels only -- this is completely independent of the type of chart. I have done this in this example, which is slightly more relevant than the one linked in the other answer.
Note that if you go with the force layout solution, you don't have to animate the position of the labels. You could simply compute the force layout until it converges and then plot the labels.
I've had a similar problem with multiple (sub-)axis, where the last tick overlaps my vertical axis in some situations (depending on the screen width), so I've just wrote a little function that compares the position of the end of the text label with the position of the next axis. This code is very specific to my use case, but could adapted easily to your needs:
var $svg = $('#svg');
// get the last tick of each of my sub-axis
$('.tick-axis').find('.tick:last-of-type').each(function() {
// get position of the end of this text field
var endOfTextField = $(this).offset().left + $(this).find('text').width();
// get the next vertical axis
var $nextAxis = $('line[data-axis="' + $(this).closest('.tick-axis').attr('data-axis') + '"]');
// there is no axis on the very right, so just use the svg width
var positionOfAxis = ($nextAxis.length > 0) ? $nextAxis.offset().left : $svg.offset().left + $svg.width();
// hide the ugly ones!
if (endOfTextField > positionOfAxis) {
$(this).attr('class', 'tick hide');
}
});
The ticks with color: aqua are the hidden ones:

Resources