Implemeting raycast intro custom webgl - glmatrix based engine solution - webgl

If anyone wanna help or any type of suggestion (links) i would be satisfied. I create little engine with scene object based render.
Success with triangle but only when camera is front of triangle .
After App.camera.FirstPersonController = true you can walk behind
and try raycask click not working.
Maybe biggest problem for me is rotation .
Translation is adaptend on mvMatrix but if i change position a need to add also :
add + object.position.worldLocation[0] to input vertices and everything works perfect when i change position ...
but how to make adapt for rotation.
For example after rotation change
App.scene.MyColoredSquareRayObject.rotation.roty = -45
raycast dont catch any detection at all ....
If i dont change rotation then works fine even in first person regime (mouse gives coordinate for rotation).
Interest if i use App.scene.MyColoredSquareRayObject.rotation.rotz = 90
by z the raycast works.
In draw function [mouse oook work raycast] i expected everything (is calculated) to work but it doesn't
mat4.identity(object.mvMatrix);
this.mvPushMatrix(object.mvMatrix, this.mvMatrixStack);
if (App.camera.FirstPersonController == true) {
camera.setCamera(object);
}
mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);
mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rz), object.rotation.getRotDirZ());
mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rx), object.rotation.getRotDirX());
mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.ry), object.rotation.getRotDirY());
if (raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);
const triangle = [
[object.geometry.vertices[0 + a*3] + object.position.worldLocation[0], object.geometry.vertices[1 + a*3] + object.position.worldLocation[1], object.geometry.vertices[2 + a*3]],
[object.geometry.vertices[0 + b*3] + object.position.worldLocation[0], object.geometry.vertices[1 + b*3] + object.position.worldLocation[1], object.geometry.vertices[2 + b*3]],
[object.geometry.vertices[0 + c*3] + object.position.worldLocation[0], object.geometry.vertices[1 + c*3] + object.position.worldLocation[1], object.geometry.vertices[2 + c*3]],
];
if (rayIntersectsTriangle(myRayOrigin, ray, triangle, intersectionPoint, object.position) ) {
....
Check on demo live
project - raycast.js file
var world;
var App = matrixEngine.App;
var raycaster = matrixEngine.raycaster;
const addBtn = document.querySelector(".button1");
const regularBtn = document.querySelector(".button2");
addBtn.style.display = "none";
regularBtn.style.display = "none";
const run = () => {
var App = matrixEngine.App;
// from here you can put code from examples
world.Add("triangle", 1, "MyColoredTriangle1");
App.scene.MyColoredTriangle1.position.SetX(0);
//App.scene.MyColoredTriangle1.rotation.rotationSpeed.x = 15;
}
if ("serviceWorker" in navigator) {
window.addEventListener("load", function() {
// navigator.serviceWorker.register("worker.js");
});
} else {
console.warn("Matrix Engine: No support for web workers in this browser.");
}
function webGLStart() {
world = matrixEngine.matrixWorld.defineworld(canvas);
world.callReDraw();
// Make it async on tradicional way
setTimeout(run, 77);
canvas.addEventListener('mousedown', (ev) => {
raycaster.checkingProcedure(ev);
});
window.App = App;
window.world = world;
}
// matrixEngine.Engine.load_shaders("shaders/shaders.html");
window.matrixEngine = matrixEngine;
window.addEventListener("load", () => {
matrixEngine.Engine.initApp(webGLStart);
});
body {
color: lime;
background-color: black;
font-family: "Courier New";
font-size: 13px;
background-color: black;
margin: 0;
padding: 0;
overflow: hidden;
}
a {
font-family: "Courier New";
color: #0080ff;
}
.btnShadow {
-webkit-box-shadow: inset 0px 0px 22px 2px rgba(0, 255, 30, 1);
-moz-box-shadow: inset 0px 0px 22px 2px rgba(0, 255, 30, 1);
box-shadow: inset 0px 0px 22px 1px rgba(0, 255, 30, 1);
cursor: pointer;
cursor: hand;
color: lime;
text-shadow: 1px 0px 0px #0BFF03;
}
div.btnShadow:hover {
background-color: lime;
color: black;
text-shadow: 1px 1px 1px #0BFF03;
-webkit-border-radius: 5px 5px 5px 5px;
border-radius: 5px 5px 5px 5px;
-webkit-box-shadow: 0 0 10px 3px #47FF19;
box-shadow: 0 0 10px 3px #47FF19;
}
.debugBox {
position: absolute;
left: 0;
top: 0;
font-size: 12px;
width: 200px;
height: 15px;
-webkit-box-shadow: inset 0px 0px 22px 2px rgba(0, 255, 30, 1);
-moz-box-shadow: inset 0px 0px 22px 2px rgba(0, 255, 30, 1);
box-shadow: inset 0px 0px 22px 1px rgba(0, 255, 30, 1);
background-color: black;
color: lime;
}
.textEditor {
font-size: 10px;
width: 100%;
max-width: 850px !important;
min-width: 550px !important;
}
textarea {
-webkit-box-shadow: inset 0px 0px 22px 2px rgba(0, 255, 30, 1);
-moz-box-shadow: inset 0px 0px 22px 2px rgba(0, 255, 30, 1);
box-shadow: inset 0px 0px 22px 1px rgba(0, 255, 30, 1);
background-color: black;
color: lime;
}
.textureCanvas2d {
display: none;
position: absolute;
left: -3000px;
top: 0px;
width: 512px;
height: 512px;
}
.add-button {
background-color: #4CAF50;
/* Green */
border: none;
color: white;
padding: 16px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 2px 2px;
transition-duration: 0.4s;
cursor: pointer;
top: 1px;
left: 1px;
width: 100%;
width: -webkit-fill-available;
height: 30%;
background-color: rgb(27, 27, 27);
font-family: "Courier New";
}
.button1 {
background-color: rgb(27, 27, 27);
;
color: greenyellow;
border: 2px solid #4CAF50;
}
.button1:hover {
background-color: #4CAF50;
color: white;
}
.button2 {
background-color: rgb(27, 27, 27);
;
color: white;
border: 2px solid #4CAF50;
}
.button2:hover {
background-color: #95af4c;
color: white;
}
<script src="https://maximumroulette.com/apps/webgl-glmatrix/lib/gl-matrix-min.js"></script>
<div id="shaders"></div>
<div id="debugBox" class="debugBox" style="display:none;"></div>
<div id="fps" class="btnShadow debugBox" style="display:none;">
<button id="stopRender" type="button">stopRender</button>
<div color="white"><b id="fps"></b></div>
</div>
<button class="add-button button1">
<h1> Add to home screen </h1>
<h2> Run like PWA Application for better performance</h2>
</button>
<button class="add-button button2">
<h2> I don't wanna full PWA just play it in regular HTML5 page.</h2>
</button>
<div id="HOLDER_STREAMS" class="debugBox" style="display:none;position:absolute;left:0px;top:0px;width:512px;height:512px">
<video id="webcam_beta" autoplay width="512" height="512" style="display:none;position:absolute;left:-200px;top:-110px;"></video>
<audio id="audio_beta" src="#"></audio>
<div id="media-holder"> </div>
</div>
<script id="triangle-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; }
</script>
<script id="triangle-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; }
</script>
<!-- Square Shader -->
<script id="square-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; }
</script>
<script id="square-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; }
</script>
<!-- Cube Shader -->
<script id="cube-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; }
</script>
<script id="cube-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; }
</script>
<!-- Cube Texture Shader -->
<script id="cubeTex-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec2 vTextureCoord; uniform sampler2D uSampler; void main(void) { gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); }
</script>
<script id="cubeTex-shader-vs" type="x-shader/x-vertex">
#version 300 es #define POSITION_LOCATION 0 attribute vec3 aVertexPosition; attribute vec2 aTextureCoord; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec2 vTextureCoord; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition,
1.0); vTextureCoord = aTextureCoord; }
</script>
<!-- Filter : cubeLightTex -->
<script id="cubeLightTex-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec2 vTextureCoord; varying vec3 vLightWeighting; uniform sampler2D uSampler; uniform sampler2D uSampler1; uniform sampler2D uSampler2; uniform sampler2D uSampler3; uniform sampler2D uSampler4; uniform sampler2D uSampler5;
uniform sampler2D uSampler6; uniform sampler2D uSampler7; uniform sampler2D uSampler8; uniform sampler2D uSampler9; uniform sampler2D uSampler10; uniform sampler2D uSampler11; uniform sampler2D uSampler12; uniform sampler2D uSampler13; uniform float
numberOfsamplers; void main(void) { vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); vec4 textureColor1 = texture2D(uSampler1, vec2(vTextureCoord.s, vTextureCoord.t)); vec4 textureColor2 = texture2D(uSampler2, vec2(vTextureCoord.s,
vTextureCoord.t)); // gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a); COOL gl_FragColor = textureColor; } /* vec4 color0 = texture2D(u_image0, v_texCoord); vec4 color1 = texture2D(u_image1, v_texCoord); gl_FragColor = color0
* color1; */
</script>
<script id="cubeLightTex-shader-vs" type="x-shader/x-vertex">
//#define POSITION_LOCATION 0 // not in use // this is for drawInstance //layout(location = POSITION_LOCATION) in vec2 pos; //not in use //flat out int instance; // attribute vec3 aVertexPosition; attribute vec3 aVertexNormal; attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform mat3 uNMatrix; uniform vec3 uAmbientColor; uniform vec3 uLightingDirection; uniform vec3 uDirectionalColor; uniform bool uUseLighting; varying vec2 vTextureCoord; varying vec3 vLightWeighting; void
main(void) { //instance = gl_InstanceID; //gl_Position = vec4(aVertexPosition + vec2(float(gl_InstanceID) - 0.5, 0.0), 0.0, 1.0); gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vTextureCoord = aTextureCoord; if (!uUseLighting) { vLightWeighting
= vec3(1.0, 1.0, 1.0); } else { vec3 transformedNormal = uNMatrix * aVertexNormal; float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0); vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
} }
</script>
<!-- end of cube shader -->
<!-- Filter : cubeLightTex CLONE OF -->
<script id="obj-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec2 vTextureCoord; varying vec3 vLightWeighting; uniform sampler2D uSampler; uniform sampler2D uSampler1; uniform sampler2D uSampler2; void main(void) { vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a); }
</script>
<script id="obj-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec3 aVertexNormal; attribute vec2 aTextureCoord; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform mat3 uNMatrix; uniform vec3 uAmbientColor; uniform vec3 uLightingDirection; uniform vec3 uDirectionalColor;
uniform bool uUseLighting; varying vec2 vTextureCoord; varying vec3 vLightWeighting; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vTextureCoord = aTextureCoord; if (!uUseLighting) { vLightWeighting = vec3( 1.0,
1.0, 1.0); } else { vec3 transformedNormal = uNMatrix * aVertexNormal; float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0); vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting; } }
</script>
<!-- end of cube shader CLONE OF -->
<!-- Pyramid Shader -->
<script id="pyramid-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; }
</script>
<script id="pyramid-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec4 vColor; void main(void) { // instance = gl_InstanceID; // gl_Position = vec4(aVertexPosition + vec2(float(gl_InstanceID) - 0.5, 0.0),
0.0, 1.0); gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; }
</script>
<!-- Filter : cubeLightTex -->
<script id="squareTex-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec2 vTextureCoord; varying vec3 vLightWeighting; uniform sampler2D uSampler; uniform sampler2D uSampler1; uniform sampler2D uSampler2; uniform sampler2D uSampler3; uniform sampler2D uSampler4; uniform sampler2D uSampler5;
uniform sampler2D uSampler6; uniform sampler2D uSampler7; uniform sampler2D uSampler8; uniform sampler2D uSampler9; uniform sampler2D uSampler10; uniform sampler2D uSampler11; uniform sampler2D uSampler12; uniform sampler2D uSampler13; uniform float
numberOfsamplers; void main(void) { vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); vec4 textureColor1 = texture2D(uSampler1, vec2(vTextureCoord.s, vTextureCoord.t)); vec4 textureColor2 = texture2D(uSampler2, vec2(vTextureCoord.s,
vTextureCoord.t)); // gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a); gl_FragColor = textureColor; } /* vec4 color0 = texture2D(u_image0, v_texCoord); vec4 color1 = texture2D(u_image1, v_texCoord); gl_FragColor = color0 * color1;
*/
</script>
<script id="squareTex-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec3 aVertexNormal; attribute vec2 aTextureCoord; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform mat3 uNMatrix; uniform vec3 uAmbientColor; uniform vec3 uLightingDirection; uniform vec3 uDirectionalColor;
uniform bool uUseLighting; varying vec2 vTextureCoord; varying vec3 vLightWeighting; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vTextureCoord = aTextureCoord; if (!uUseLighting) { vLightWeighting = vec3(1.0, 1.0,
1.0); } else { vec3 transformedNormal = uNMatrix * aVertexNormal; float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0); vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting; } }
</script>
<!-- end of cube shader -->
<!-- duplicate cubeLightTex -->
<!-- Filter : sphereLightTex -->
<script id="sphereLightTex-shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec2 vTextureCoord; varying vec3 vLightWeighting; uniform sampler2D uSampler; uniform sampler2D uSampler1; uniform sampler2D uSampler2; uniform sampler2D uSampler3; uniform sampler2D uSampler4; uniform sampler2D uSampler5;
uniform sampler2D uSampler6; uniform sampler2D uSampler7; uniform sampler2D uSampler8; uniform sampler2D uSampler9; uniform sampler2D uSampler10; uniform sampler2D uSampler11; uniform sampler2D uSampler12; uniform sampler2D uSampler13; uniform float
numberOfsamplers; void main(void) { vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); vec4 textureColor1 = texture2D(uSampler1, vec2(vTextureCoord.s, vTextureCoord.t)); vec4 textureColor2 = texture2D(uSampler2, vec2(vTextureCoord.s,
vTextureCoord.t)); gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a); } /* vec4 color0 = texture2D(u_image0, v_texCoord); vec4 color1 = texture2D(u_image1, v_texCoord); gl_FragColor = color0 * color1;vertexPositionAttribute */
</script>
<script id="sphereLightTex-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; attribute vec3 aVertexNormal; attribute vec2 aTextureCoord; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform mat3 uNMatrix; uniform vec3 uAmbientColor; uniform vec3 uLightingDirection; uniform vec3 uDirectionalColor;
uniform bool uUseLighting; varying vec2 vTextureCoord; varying vec3 vLightWeighting; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vTextureCoord = aTextureCoord; if (!uUseLighting) { vLightWeighting = vec3(1.0, 1.0,
1.0); } else { vec3 transformedNormal = uNMatrix * aVertexNormal; float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0); vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting; } }
</script>
<!-- end of cube shader -->
<script src="https://maximumroulette.com/apps/matrix-engine/builds/me.lib.js"></script>
Check whole project

Related

How to place an image above another image using Styled Components in React Native App

I need to put an icon image above my cardVideo component. I just want to put the image above, without any action.
The path for the play icon: import image from '../../../assets/book_covers/icon-play.png';
Thank you.
My component:
import React from 'react';
import { SafeAreaView } from 'react-native';
import { Container, Capa, TextBox, Title } from './CardVideo.style';
import image from '../../../assets/book_covers/imageCollection';
const CardVideo = ({ item, first=false, last=false }) => (
<SafeAreaView>
<Container first={first} last={last}>
<Capa source={image[item.imagem_livro]} resizeMode="cover" />
<TextBox>
<Title numberOfLines={1}>{item.titulo_livro}</Title>
</TextBox>
</Container>
</SafeAreaView>
);
export default CardVideo;
VideoCard style:
import styled from 'styled-components/native';
export const Container = styled.View`
margin-left: ${props => (props.first ? '16px' : '12px')};
margin-right: ${props => (props.last ? '16px' : '0')};
justify-content: space-between;
`;
export const Capa = styled.Image`
width: 280px;
height: 160px;
margin: 0 0 12px;
opacity: 0.3;
border-radius: 10px;
background-color: #000000;
`;
export const TextBox = styled.View`
width: 280px;
height: 42px;
`;
export const Title = styled.Text`
font-family: Roboto;
font-size: 14px;
font-weight: normal;
font-style: normal;
color: #232728;
`;
export const IconPlay = styled.Image`
width: 56px;
height: 56px;
object-fit: contain;
`;
The component image without the Icon
How should it be
How it looks like in the iOS simulator
This can be achieved with Absolute Positioning in React Native or even with ImageBackground
Ex: With Absolute Positioning: position: absolute;
// VideoCard style
export const ImageContainer = styled.View`
width: 280px;
height: 160px;
border-radius: 10px;
justify-content: center;
align-items: center;
`;
export const Capa = styled.Image`
width: 280px;
height: 160px;
border-radius: 10px;
`;
export const ImageOverlayView = styled.View`
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: grey;
opacity: 0.3;
border-radius: 10px;
`;
export const IconPlay = styled.Image`
position: absolute;
width: 56px;
height: 56px;
`;
//VideoCard Component Image part:
...
<ImageContainer>
<Capa source={image[item.imagem_livro]} resizeMode="cover" />
<ImageOverlayView />
<IconPlay source={/* your image */)} />
</ImageContainer>
<TextBox>
...
Eg: ImageBackground - for placing Image above another image.
// VideoCard style
export const ImageBackground = styled.ImageBackground`
width: 280px;
height: 160px;
border-radius: 10px;
justify-content: center;
align-items: center;
`;
export const IconPlay = styled.Image`
width: 56px;
height: 56px;
`;
//VideoCard Component Image part:
...
<Container first={first} last={last}>
<ImageBackground source={image[item.imagem_livro]} resizeMode="cover">
<IconPlay source={/* your image */} />
</ImageBackground>
<TextBox>
...

Problems with multiple tween animations in Flutter - Videos Included

I have a weird flutter issue with a certain animation I'm trying to create.
I am trying to animate an image onto the screen.
I want it to move on the x-axis, and I want it to slowly fade in as well.
So I figured - Positioned and Opacity, and animate their value with a tween.
Both the Positioned and Opacity widgets work great on their own, but when I combine the two - I get a weird animation, that only starts to draw after a while (about 3 seconds).
I tried printing the animation.value and it seems to be fine, slowly climbing from 0.0 to 1.0 - but the clouds suddenly appear only after like 3 seconds.
I tried separating them to different controllers, thought that maybe somehow that was the culprit, but nope.
TLDR Videos:
Opacity Animation Only
Positioned Animation Only
Both Animations Combined - NOT GOOD
Here's the widget's code:
import 'package:app/weather/widgets/CloudProperties.dart';
import 'package:flutter/widgets.dart';
class WeatherCloudWidget extends StatefulWidget {
final double sunSize;
final CloudProperties properties;
WeatherCloudWidget({Key key, this.properties, this.sunSize})
: super(key: key);
#override
State<StatefulWidget> createState() => _WeatherCloudWidget();
}
class _WeatherCloudWidget extends State<WeatherCloudWidget>
with TickerProviderStateMixin {
AnimationController controller;
AnimationController controller2;
Animation<double> position;
Animation<double> opacity;
#override
initState() {
super.initState();
_startAnimation();
}
#override
Widget build(BuildContext context) {
// screen width and height
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
final properties = widget.properties;
var vertical =
screenHeight * 0.5 + (widget.sunSize * properties.verticalOffset * -1);
var horizontal = (screenWidth * 0.5) + (widget.sunSize * position.value);
print(opacity.value);
// both Positioned & Opacity widgets
return Positioned(
left: horizontal,
top: vertical,
child: Opacity(
opacity: opacity.value,
child: Image.asset(
properties.path,
width: properties.getScaledWidth(widget.sunSize),
height: properties.getScaledHeight(widget.sunSize),
),
));
// Positioned only
return Positioned(
left: horizontal,
top: vertical,
child: Image.asset(
properties.path,
width: properties.getScaledWidth(widget.sunSize),
height: properties.getScaledHeight(widget.sunSize),
));
// Opacity only
return Positioned(
left: (screenWidth * 0.5) + (widget.sunSize * properties.tween[1]),
top: vertical,
child: Opacity(
opacity: opacity.value,
child: Image.asset(
properties.path,
width: properties.getScaledWidth(widget.sunSize),
height: properties.getScaledHeight(widget.sunSize),
),
));
}
#override
dispose() {
controller.dispose();
controller2.dispose();
super.dispose();
}
void _startAnimation() {
controller = AnimationController(
duration: const Duration(milliseconds: 5000), vsync: this);
controller2 = AnimationController(
duration: const Duration(milliseconds: 5000), vsync: this);
position = Tween(
begin: widget.properties.tween[0], end: widget.properties.tween[1])
.animate(
new CurvedAnimation(parent: controller, curve: Curves.decelerate))
..addListener(() => setState(() {}));
opacity = Tween(begin: 0.0, end: 1.0).animate(controller2)
..addListener(() => setState(() {}));
controller.forward();
controller2.forward();
}
}
Alright guys. I managed to sort this using SlideTransition and FadeTransition.
I guess we should only use Transition widgets for... transitions? while things like Positioned and Opacity are for more static widgets? Not sure...
What it looks like: https://youtu.be/hj7PkjXrgfg
Anyways, here's the replacement code, if anyone's looking for reference:
class WeatherCloudWidget extends StatefulWidget {
final double sunSize;
final CloudProperties properties;
WeatherCloudWidget({Key key, this.properties, this.sunSize})
: super(key: key);
#override
State<StatefulWidget> createState() => _WeatherCloudWidget();
}
class _WeatherCloudWidget extends State<WeatherCloudWidget>
with TickerProviderStateMixin {
AnimationController controller;
Animation<Offset> position;
Animation<double> opacity;
final alphaTween = new Tween(begin: 0.0, end: 1.0);
#override
initState() {
super.initState();
_startAnimation();
}
#override
Widget build(BuildContext context) {
// screen width and height
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
final properties = widget.properties;
var vertical = (screenHeight * 0.5) +
(widget.sunSize * properties.verticalOffset * -1);
var horizontal =
(screenWidth * 0.5) + (widget.sunSize * properties.tweenEnd);
return Positioned(
left: horizontal,
top: vertical,
child: SlideTransition(
position: position,
child: FadeTransition(
opacity: opacity,
child: Image.asset(
properties.path,
width: properties.getScaledWidth(widget.sunSize),
height: properties.getScaledHeight(widget.sunSize),
),
)),
);
}
#override
dispose() {
controller.dispose();
super.dispose();
}
void _startAnimation() {
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
position = new Tween<Offset>(
begin: new Offset(widget.properties.tweenStart, 0.0),
end: new Offset(0.0, 0.0),
).animate(new CurvedAnimation(parent: controller, curve: Curves.decelerate));
opacity = alphaTween.animate(controller);
controller.forward();
}
}

Extends UnderlineInputBorder class in Google Flutter

I'm trying to modify the behavior of the UnderlineInputBorder in Flutter by extending it. But the Flutter always called the draw() method of the superclass (UnderlineInputBorder) instead of my _PremiseInputBorder as bellow.
Code for the TextField widget:
TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
border: _PremiseInputBorder()),
)
Code for my custom border class:
class _PremiseInputBorder extends UnderlineInputBorder {
const _PremiseInputBorder() : super();
#override
void paint(Canvas canvas, Rect rect, {
double gapStart,
double gapExtent = 0.0,
double gapPercentage = 0.0,
TextDirection textDirection,}) {
if (borderRadius.bottomLeft != Radius.zero ||
borderRadius.bottomRight != Radius.zero)
canvas.clipPath(getOuterPath(rect, textDirection: textDirection));
Offset leftRect = Offset(rect.left, rect.bottom - 5.0);
Offset rightRect = Offset(rect.right, rect.bottom - 5.0);
canvas.drawLine(leftRect, rightRect, borderSide.toPaint());
}
}
UnderlineInputBorder has
#override
UnderlineInputBorder copyWith({ BorderSide borderSide, BorderRadius borderRadius }) {
return UnderlineInputBorder(
borderSide: borderSide ?? this.borderSide,
borderRadius: borderRadius ?? this.borderRadius,
);
}
which returns an UnderlineInputBorder even when you extend the class.
If you add to _PremiseInputBorder
#override
UnderlineInputBorder copyWith(
{BorderSide borderSide, BorderRadius borderRadius}) {
return _PremiseInputBorder();
}
it will call your paint() method.
There are other methods that do similar things like scale(), lerpFrom(), lerpTo() but they were not called in your simple example.
You need to override these as well to make it all scenarios.

Flutter custom animated dialog

I'm trying to animate a custom dialog box in dart so that when it pops up it create some animations. There is a library in Android that is having animated dialog boxes, is there any similar library in Flutter Sweet Alert Dialog
how can we achieve the same functionality in flutter?
To create dialog boxes you can use the Overlay or Dialog classes. If you want to add animations like in the given framework you can use the AnimationController like in the following example. The CurvedAnimation class is used to create the bouncing effect on the animation.
Update: In general it is better to show dialogs with the showDialog function, because the closing and gesture are handled by Flutter. I have updated the example, it is now running with showDialog and you are able to close the dialog by tapping on the background.
You can copy & paste the following code into a new project and adjust it. It is runnable on it's own.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(title: 'Flutter Demo', theme: ThemeData(), home: Page());
}
}
class Page extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton.icon(
onPressed: () {
showDialog(
context: context,
builder: (_) => FunkyOverlay(),
);
},
icon: Icon(Icons.message),
label: Text("PopUp!")),
),
);
}
}
class FunkyOverlay extends StatefulWidget {
#override
State<StatefulWidget> createState() => FunkyOverlayState();
}
class FunkyOverlayState extends State<FunkyOverlay>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> scaleAnimation;
#override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 450));
scaleAnimation =
CurvedAnimation(parent: controller, curve: Curves.elasticInOut);
controller.addListener(() {
setState(() {});
});
controller.forward();
}
#override
Widget build(BuildContext context) {
return Center(
child: Material(
color: Colors.transparent,
child: ScaleTransition(
scale: scaleAnimation,
child: Container(
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0))),
child: Padding(
padding: const EdgeInsets.all(50.0),
child: Text("Well hello there!"),
),
),
),
),
);
}
}
Just use 'showGeneralDialog()' No need use extra lib or widget.
You can get more animatated dialog reference from This Link
void _openCustomDialog() {
showGeneralDialog(barrierColor: Colors.black.withOpacity(0.5),
transitionBuilder: (context, a1, a2, widget) {
return Transform.scale(
scale: a1.value,
child: Opacity(
opacity: a1.value,
child: AlertDialog(
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0)),
title: Text('Hello!!'),
content: Text('How are you?'),
),
),
);
},
transitionDuration: Duration(milliseconds: 200),
barrierDismissible: true,
barrierLabel: '',
context: context,
pageBuilder: (context, animation1, animation2) {});
}
I tried to do the animation shown in your gif. Gonna post the code to help people who want it, its not perfect so if anyone wants to help improving it go for it.
How it looks:
Code:
import 'package:flutter/material.dart';
import 'package:angles/angles.dart';
import 'dart:math';
import 'dart:core';
class CheckAnimation extends StatefulWidget {
final double size;
final VoidCallback onComplete;
CheckAnimation({this.size, this.onComplete});
#override
_CheckAnimationState createState() => _CheckAnimationState();
}
class _CheckAnimationState extends State<CheckAnimation>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> curve;
#override
void initState() {
// TODO: implement initState
super.initState();
_controller =
AnimationController(duration: Duration(seconds: 2), vsync: this);
curve = CurvedAnimation(parent: _controller, curve: Curves.bounceInOut);
_controller.addListener(() {
setState(() {});
if(_controller.status == AnimationStatus.completed && widget.onComplete != null){
widget.onComplete();
}
});
_controller.forward();
}
#override
Widget build(BuildContext context) {
return Container(
height: widget.size ?? 100,
width: widget.size ?? 100,
color: Colors.transparent,
child: CustomPaint(
painter: CheckPainter(value: curve.value),
),
);
}
#override
void dispose() {
// TODO: implement dispose
_controller.dispose();
super.dispose();
}
}
class CheckPainter extends CustomPainter {
Paint _paint;
double value;
double _length;
double _offset;
double _secondOffset;
double _startingAngle;
CheckPainter({this.value}) {
_paint = Paint()
..color = Colors.greenAccent
..strokeWidth = 5.0
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
assert(value != null);
_length = 60;
_offset = 0;
_startingAngle = 205;
}
#override
void paint(Canvas canvas, Size size) {
// Background canvas
var rect = Offset(0, 0) & size;
_paint.color = Colors.greenAccent.withOpacity(.05);
double line1x1 = size.width / 2 +
size.width * cos(Angle.fromDegrees(_startingAngle).radians) * .5;
double line1y1 = size.height / 2 +
size.height * sin(Angle.fromDegrees(_startingAngle).radians) * .5;
double line1x2 = size.width * .45;
double line1y2 = size.height * .65;
double line2x1 =
size.width / 2 + size.width * cos(Angle.fromDegrees(320).radians) * .35;
double line2y1 = size.height / 2 +
size.height * sin(Angle.fromDegrees(320).radians) * .35;
canvas.drawArc(rect, Angle.fromDegrees(_startingAngle).radians,
Angle.fromDegrees(360).radians, false, _paint);
canvas.drawLine(Offset(line1x1, line1y1), Offset(line1x2, line1y2), _paint);
canvas.drawLine(Offset(line2x1, line2y1), Offset(line1x2, line1y2), _paint);
// animation painter
double circleValue, checkValue;
if (value < .5) {
checkValue = 0;
circleValue = value / .5;
} else {
checkValue = (value - .5) / .5;
circleValue = 1;
}
_paint.color = const Color(0xff72d0c3);
double firstAngle = _startingAngle + 360 * circleValue;
canvas.drawArc(
rect,
Angle.fromDegrees(firstAngle).radians,
Angle.fromDegrees(
getSecondAngle(firstAngle, _length, _startingAngle + 360))
.radians,
false,
_paint);
double line1Value = 0, line2Value = 0;
if (circleValue >= 1) {
if (checkValue < .5) {
line2Value = 0;
line1Value = checkValue / .5;
} else {
line2Value = (checkValue - .5) / .5;
line1Value = 1;
}
}
double auxLine1x1 = (line1x2 - line1x1) * getMin(line1Value, .8);
double auxLine1y1 =
(((auxLine1x1) - line1x1) / (line1x2 - line1x1)) * (line1y2 - line1y1) +
line1y1;
if (_offset < 60) {
auxLine1x1 = line1x1;
auxLine1y1 = line1y1;
}
double auxLine1x2 = auxLine1x1 + _offset / 2;
double auxLine1y2 =
(((auxLine1x1 + _offset / 2) - line1x1) / (line1x2 - line1x1)) *
(line1y2 - line1y1) +
line1y1;
if (checkIfPointHasCrossedLine(Offset(line1x2, line1y2),
Offset(line2x1, line2y1), Offset(auxLine1x2, auxLine1y2))) {
auxLine1x2 = line1x2;
auxLine1y2 = line1y2;
}
if (_offset > 0) {
canvas.drawLine(Offset(auxLine1x1, auxLine1y1),
Offset(auxLine1x2, auxLine1y2), _paint);
}
// SECOND LINE
double auxLine2x1 = (line2x1 - line1x2) * line2Value;
double auxLine2y1 =
((((line2x1 - line1x2) * line2Value) - line1x2) / (line2x1 - line1x2)) *
(line2y1 - line1y2) +
line1y2;
if (checkIfPointHasCrossedLine(Offset(line1x1, line1y1),
Offset(line1x2, line1y2), Offset(auxLine2x1, auxLine2y1))) {
auxLine2x1 = line1x2;
auxLine2y1 = line1y2;
}
if (line2Value > 0) {
canvas.drawLine(
Offset(auxLine2x1, auxLine2y1),
Offset(
(line2x1 - line1x2) * line2Value + _offset * .75,
((((line2x1 - line1x2) * line2Value + _offset * .75) - line1x2) /
(line2x1 - line1x2)) *
(line2y1 - line1y2) +
line1y2),
_paint);
}
}
double getMax(double x, double y) {
return (x > y) ? x : y;
}
double getMin(double x, double y) {
return (x > y) ? y : x;
}
bool checkIfPointHasCrossedLine(Offset a, Offset b, Offset point) {
return ((b.dx - a.dx) * (point.dy - a.dy) -
(b.dy - a.dy) * (point.dx - a.dx)) >
0;
}
double getSecondAngle(double angle, double plus, double max) {
if (angle + plus > max) {
_offset = angle + plus - max;
return max - angle;
} else {
_offset = 0;
return plus;
}
}
#override
bool shouldRepaint(CheckPainter old) {
return old.value != value;
}
}
I used angles package
Whenever you want to show Dialog with some Animation, the best way is to use showGeneralDialog()
NOTE: ALL PARAMETERS MUST BE PROVIDED OTHERWISE SOME ERROR WILL OCCUR.
showGeneralDialog(
barrierColor: Colors.black.withOpacity(0.5), //SHADOW EFFECT
transitionBuilder: (context, a1, a2, widget) {
return Center(
child: Container(
height: 100.0 * a1.value, // USE PROVIDED ANIMATION
width: 100.0 * a1.value,
color: Colors.blue,
),
);
},
transitionDuration: Duration(milliseconds: 200), // DURATION FOR ANIMATION
barrierDismissible: true,
barrierLabel: 'LABEL',
context: context,
pageBuilder: (context, animation1, animation2) {
return Text('PAGE BUILDER');
});
}, child: Text('Show Dialog'),),
If you need more customization, then extend PopupRoute and create your own _DialogRoute<T> and showGeneralDialog()
EDIT
Edited answer of Niklas with functionality to close Overlay :)
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(title: 'Flutter Demo', theme: ThemeData(), home: Page());
}
}
class Page extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton.icon(
onPressed: () {
OverlayEntry overlayEntry;
overlayEntry = OverlayEntry(builder: (c) {
return FunkyOverlay(onClose: () => overlayEntry.remove());
});
Overlay.of(context).insert(overlayEntry);
},
icon: Icon(Icons.message),
label: Text("PopUp!")),
),
);
}
}
class FunkyOverlay extends StatefulWidget {
final VoidCallback onClose;
const FunkyOverlay({Key key, this.onClose}) : super(key: key);
#override
State<StatefulWidget> createState() => FunkyOverlayState();
}
class FunkyOverlayState extends State<FunkyOverlay>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> opacityAnimation;
Animation<double> scaleAnimatoin;
#override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 450));
opacityAnimation = Tween<double>(begin: 0.0, end: 0.4).animate(
CurvedAnimation(parent: controller, curve: Curves.fastOutSlowIn));
scaleAnimatoin =
CurvedAnimation(parent: controller, curve: Curves.elasticInOut);
controller.addListener(() {
setState(() {});
});
controller.forward();
}
#override
Widget build(BuildContext context) {
return Material(
color: Colors.black.withOpacity(opacityAnimation.value),
child: Center(
child: ScaleTransition(
scale: scaleAnimatoin,
child: Container(
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0))),
child: Padding(
padding: const EdgeInsets.all(50.0),
child: OutlineButton(onPressed: widget.onClose, child: Text('Close!'),),
),
),
),
),
);
}
}
Add the below function in your code which shows a animated Dialog with Scale and Fade transition
void _openCustomDialog(BuildContext context) {
showGeneralDialog(
barrierColor: Colors.black.withOpacity(0.5),
transitionBuilder: (context, a1, a2, widget) {
return ScaleTransition(
scale: Tween<double>(begin: 0.5, end: 1.0).animate(a1),
child: FadeTransition(
opacity: Tween<double>(begin: 0.5, end: 1.0).animate(a1),
child: const AboutPasteLog(
title: 'About',
),
));
},
transitionDuration: const Duration(milliseconds: 300),
barrierDismissible: true,
barrierLabel: '',
context: context,
pageBuilder: (context, animation1, animation2) {
return Container();
});
}
And invoke it as below
onPressed:(){
_openCustomDialog(context);
}
The final result

How to make the coordinates on image dynamic and responsive with respect to the device screen in flutter?

Following is the image of Game I am trying to build using flutter for android:
Male body with tags naming body parts
Following is the code I have written and right now it's hardcoded for the Google Pixel, for portrait mode
Map _decoded;
List oldData=[];
int i=0;
class IdentifyGame extends StatefulWidget {
Function onScore;
Function onProgress;
Function onEnd;
int iteration;
bool isRotated;
IdentifyGame(
{key,
this.onScore,
this.onProgress,
this.onEnd,
this.iteration,
this.isRotated = false})
: super(key: key);
#override
State createState() => new _IdentifyGameState();
}
class _IdentifyGameState extends State
with SingleTickerProviderStateMixin {
double x1 = 0.0,
y1 = 0.0,
x2 = 0.0,
y2 = 0.0,
x3 = 0.0,
y3 = 0.0,
x4 = 0.0,
y4 = 0.0,
x5 = 0.0,
y5 = 0.0,
x6 = 0.0,
y6 = 0.0,
String paste1 = '',
paste2 = '',
paste3 = '',
paste4 = '',
paste5 = '',
paste6 = '',
AnimationController _imgController;
Animation animateImage;
Future _loadGameAsset() async {
return await rootBundle.loadString("assets/imageCoordinatesInfoBody.json");
}
Future _loadGameInfo() async {
String jsonGameInfo = await _loadGameAsset();
print(jsonGameInfo);
this.setState(() {
_decoded = json.decode(jsonGameInfo);
});
print((_decoded["parts"] as List));
}
#override
void initState() {
super.initState();
this._loadGameInfo();
_imgController = new AnimationController(
duration: new Duration(
milliseconds: 800,
),
vsync: this);
animateImage =
new CurvedAnimation(parent: _imgController, curve: Curves.bounceInOut);
_imgController.forward();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
}
_renderChoice1(String text, double X, double Y) {
setState(() {
paste1 = text;
x1 = X;
y1 = Y;
});
}
_renderChoice2(String text, double X, double Y) {
setState(() {
paste2 = text;
x2 = X;
y2 = Y;
});
}
_renderChoice3(String text, double X, double Y) {
setState(() {
paste3 = text;
x3 = X;
y3 = Y;
});
}
_renderChoice4(String text, double X, double Y) {
setState(() {
paste4 = text;
x4 = X;
y4 = Y;
});
}
_renderChoice5(String text, double X, double Y) {
setState(() {
paste5 = text;
x5 = X;
y5 = Y;
});
}
_renderChoice6(String text, double X, double Y) {
setState(() {
paste6 = text;
x6 = X;
y6 = Y;
});
}
Widget _builtButton(BuildContext context, double maxHeight, double maxWidth) {
print((_decoded["parts"] as List).length);
int j = 0;
int r = ((_decoded["parts"] as List).length / 5 +
((((_decoded["parts"] as List).length % 5) == 0) ? 0 : 1))
.toInt();
print(r);
return new ResponsiveGridView(
rows: r,
cols: 5,
children: (_decoded["parts"] as List)
.map((e) => _buildItems(j++, e, maxHeight, maxWidth))
.toList(growable: false),
);
}
List _buildPartsList() {
List partsName = [];
for (var i = 0; i (i),
part: part,
);
}
_onDragStart(BuildContext context, DragStartDetails start) {
print(start.globalPosition.toString());
}
_onDragUpdate(BuildContext context, DragUpdateDetails update) {
print(update.globalPosition.toString());
}
#override
void dispose() {
_imgController.dispose();
SystemChrome.setPreferredOrientations([]);
super.dispose();
}
#override
Widget build(BuildContext context) {
print(_buildPartsList());
Size media = MediaQuery.of(context).size;
double _height = media.height;
double _width = media.width;
print("height of screen from media is $_height ");
print("width of screen from media is $_width");
return new LayoutBuilder(builder: (context, constraint) {
return new Scaffold(
body: new Flex(
direction: Axis.vertical,
children: [
new GestureDetector(
onHorizontalDragStart: (DragStartDetails start) =>
_onDragStart(context, start),
onHorizontalDragUpdate: (DragUpdateDetails update) =>
_onDragUpdate(context, update),
onVerticalDragStart: (DragStartDetails start) =>
_onDragStart(context, start),
onVerticalDragUpdate: (DragUpdateDetails update) =>
_onDragUpdate(context, update),
child: new Container(
height: (constraint.maxHeight) * 3 / 4,
width: constraint.maxWidth,
decoration: new BoxDecoration(
color: Theme.of(context).backgroundColor,
),
child: new Stack(
fit: StackFit.passthrough,
children: [
new ScaleTransition(
scale: animateImage,
child: new Image(
image: AssetImage('assets/' + _decoded["id"]),
fit: BoxFit.contain,
),
),
new RepaintBoundary(
child: new CustomPaint(
painter: new Stickers(
text: paste1,
x: x1,
y: y1,
height: _height,
width: _width),
),
),
new RepaintBoundary(
child: new CustomPaint(
painter: new Stickers(
text: paste2,
x: x2,
y: y2,
height: _height,
width: _width),
),
),
new RepaintBoundary(
child: new CustomPaint(
painter: new Stickers(
text: paste3,
x: x3,
y: y3,
height: _height,
width: _width),
),
),
new RepaintBoundary(
child: new CustomPaint(
painter: new Stickers(
text: paste4,
x: x4,
y: y4,
height: _height,
width: _width),
),
),
new RepaintBoundary(
child: new CustomPaint(
painter: new Stickers(
text: paste5,
x: x5,
y: y5,
height: _height,
width: _width),
),
),
new RepaintBoundary(
child: new CustomPaint(
painter: new Stickers(
text: paste6,
x: x6,
y: y6,
height: _height,
width: _width),
),
),
],
)),
),
new Container(
height: (constraint.maxHeight) / 4,
width: constraint.maxWidth,
decoration: new BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor),
child: _builtButton(
context, constraint.maxHeight, constraint.maxWidth)),
],
),
);
});
}
}
class DragBox extends StatefulWidget {
var part;
double maxHeight;
double maxWidth;
Function render1;
Function render2;
Function render3;
Function render4;
Function render5;
Function render6;
Function onScore;
Function onEnd;
DragBox(
{this.onEnd,
this.onScore,
this.maxHeight,
this.maxWidth,
Key key,
this.part,
this.render1,
this.render2,
this.render3,
this.render4,
this.render5,
this.render6,})
: super(key: key);
#override
DragBoxState createState() => new DragBoxState();
}
class DragBoxState extends State with TickerProviderStateMixin {
AnimationController controller, shakeController;
Animation animation, shakeAnimation, noanimation;
// Color draggableColor;
// String draggableText;
var part;
int _flag = 0;
double maxHeight;
double maxWidth;
Function render1;
Function render2;
Function render3;
Function render4;
Function render5;
Function render6;
static List _buildPartsList() {
List partsName = [];
for (var i = 0; i data = _buildPartsList();
_onDragStart(BuildContext context, DragStartDetails start) {
RenderBox getBox = context.findRenderObject();
var local = getBox.globalToLocal(start.globalPosition);
print(local.dx.toString() + "|" + local.dy.toString());
}
_onDragUpdate(BuildContext context, DragUpdateDetails update) {
RenderBox getBox = context.findRenderObject();
var local = getBox.globalToLocal(update.globalPosition);
print(local.dx.toString() + "|" + local.dy.toString());
}
void toAnimateFunction() {
animation.addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
controller.forward();
}
void toAnimateButton() {
shakeController.forward();
}
#override
void initState() {
super.initState();
shakeController = new AnimationController(
duration: new Duration(milliseconds: 800), vsync: this);
controller = new AnimationController(
duration: new Duration(milliseconds: 80), vsync: this);
animation = new Tween(begin: -3.0, end: 3.0).animate(controller);
animation.addListener(() {
setState(() {});
});
shakeAnimation =
new CurvedAnimation(parent: shakeController, curve: Curves.easeOut);
noanimation = new Tween(begin: 0.0, end: 0.0).animate(shakeController);
part = widget.part;
maxHeight = widget.maxHeight;
maxWidth = widget.maxWidth;
render1 = widget.render1;
render2 = widget.render2;
render3 = widget.render3;
render4 = widget.render4;
render5 = widget.render5;
render6 = widget.render6;
toAnimateButton();
}
#override
void dispose() {
controller.dispose();
shakeController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Size media = MediaQuery.of(context).size;
double _height = media.height;
double _width = media.width;
return new ScaleTransition(
scale: shakeAnimation,
child: new GestureDetector(
onHorizontalDragStart: (DragStartDetails start) =>
_onDragStart(context, start),
onHorizontalDragUpdate: (DragUpdateDetails update) =>
_onDragUpdate(context, update),
onVerticalDragStart: (DragStartDetails start) =>
_onDragStart(context, start),
onVerticalDragUpdate: (DragUpdateDetails update) =>
_onDragUpdate(context, update),
child: new Draggable(
data: part["name"],
child: new AnimatedDrag(
animation: (_flag == 0) ? noanimation : animation,
draggableColor: Theme.of(context).buttonColor,
draggableText: part["name"]),
feedback: new AnimatedFeedback(
animation: animation,
draggableColor: Theme.of(context).disabledColor,
draggableText: part["name"]),
onDraggableCanceled: (velocity, offset) {
double hRatio = ((3 * maxHeight) / (4 * part["data"]["height"]));
double wRatio = (maxWidth / part["data"]["width"]);
if (part["name"] == "face" &&
(offset.dx > 360.0 && offset.dx 140.0 && offset.dy 336.0 && offset.dx 250.0 && offset.dy 260.0 && offset.dx 300.0 && offset.dy 430.0 && offset.dx 300.0 && offset.dy 392.0 && offset.dx 620.0 && offset.dy 220.0 && offset.dx 620.0 && offset.dy animation,
this.draggableColor,
this.draggableText})
: super(key: key, listenable: animation);
final Color draggableColor;
final String draggableText;
Widget build(BuildContext context) {
Size media = MediaQuery.of(context).size;
double _height = media.height;
double _width = media.width;
final Animation animation = listenable;
return new Container(
// width: _width * 0.15,
// height: _height * 0.06,
padding: new EdgeInsets.all(
(_width > _height) ? _width * 0.01 : _width * 0.015),
color: draggableColor.withOpacity(0.5),
child: new Center(
child: new Text(
draggableText,
style: new TextStyle(
color: Theme.of(context).highlightColor,
decoration: TextDecoration.none,
fontSize: (_width > _height) ? _width * 0.015 : _width * 0.03,
),
),
),
);
}
}
class AnimatedDrag extends AnimatedWidget {
AnimatedDrag(
{Key key,
Animation animation,
this.draggableColor,
this.draggableText})
: super(key: key, listenable: animation);
final Color draggableColor;
final String draggableText;
Widget build(BuildContext context) {
Size media = MediaQuery.of(context).size;
double _height = media.height;
double _width = media.width;
final Animation animation = listenable;
double translateX = animation.value;
print("value: $translateX");
return new Transform(
transform: new Matrix4.translationValues(translateX, 0.0, 0.0),
child: new Container(
// width: _width * 0.15,
// height: _height * 0.06,
padding: new EdgeInsets.all(
(_width > _height) ? _width * 0.01 : _width * 0.015),
margin: new EdgeInsets.symmetric(
vertical: (_width > _height) ? _width * 0.005 : _width * 0.005,
horizontal: (_width > _height) ? _width * 0.005 : _width * 0.005,
),
color: draggableColor,
child: new Center(
child: new Text(
draggableText,
style: new TextStyle(
color: Theme.of(context).hintColor,
decoration: TextDecoration.none,
fontSize: (_width > _height) ? _width * 0.015 : _width * 0.03,
),
),
),
),
);
}
}
class Stickers extends CustomPainter {
Stickers({this.text, this.x, this.y, this.height, this.width});
final String text;
final double x;
final double y;
final double width;
final double height;
#override
void paint(Canvas canvas, Size size) {
TextSpan span = new TextSpan(
text: text,
style: new TextStyle(
color: Colors.black,
fontSize: (width > height) ? width * 0.015 : width * 0.03,
fontWeight: FontWeight.bold));
TextPainter tp = new TextPainter(
text: span,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr);
tp.layout();
tp.paint(canvas, new Offset(x, y));
//canvas.restore();
canvas.save();
// canvas.saveLayer(rect, new Paint());
}
#override
bool shouldRepaint(Stickers oldDelegate) {
// TODO: implement shouldRepaint
if (oldDelegate.text != text) {
return true;
} else {
return false;
}
}
}
I am new to flutter and building a game for dragging and dropping the tag with the name of a body part on it to the correct location on the shown image, images will come from the database and it will change after successful completion and submission. Now here I am struggling with making it responsive for every image that will get loaded from the database. Right now it's hardcoded for the shown image. Any help would be highly appreciated. Thanks!

Resources