I want to draw the different pattern in the flutter like this
Although this code is javascript is given in this link
I used ImageShader and used shader property of Paint Function
device transform is used to get the device pixel so that it can render the effect
This is my paint method look like...
final double devicePixelRatio = ui.window.devicePixelRatio;
#override
void paint(Canvas canvas, Size size) {
final Float64List deviceTransform = new Float64List(16)
..[0] = devicePixelRatio
..[5] = devicePixelRatio
..[10] = 1.0
..[15] = 2.0;
Float64List matrix = new Float64List(16);
print('matrix is $matrix');
print('image is coming in paint $image');
Paint paint = new Paint()
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..shader = ImageShader(
image, TileMode.repeated, TileMode.repeated, deviceTransform)
..strokeWidth = 40.2;
paths.forEach((path) {
canvas.drawPath(path, paint);
});
repaint = false;
}
Related
Is there some way to draw a dashed arc in Flutter?
At the moment I'm using canvas.drawArc but I don't know how to get the correct result.
canvas.drawArc(
rectangle,
startAngle,
fullArcRadius,
false,
Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke
..strokeWidth = 2.0,
);
dashed-arc
Unfortunately, flutter doesn't handle dashes all that well. There is a plugin that helps with it though: path_drawing
Using that, you can draw any path dashed simply by wrapping it in the dashPath function. That sounds simple enough, but it means that you can't use the canvas.drawArc method which complicates things a little. You have to use canvas.drawPath instead and figure out how to draw a path which is the same as that arc.
This is how I'd do it (and I've put in the code I use to draw the item fit to the canvas which you can use or ignore as you see fit):
import 'package:flutter/material.dart';
import 'package:path_drawing/path_drawing.dart';
class DashedArc extends CustomPainter {
final Color color;
DashedArc({Color color}) : color = color ?? Colors.white;
#override
void paint(Canvas canvas, Size size) {
// TODO: remove me. This makes it easier to tell
// where the canvas should be
canvas.drawRect(
Offset.zero & size,
Paint()
..color = Colors.black
..style = PaintingStyle.stroke);
var width = 520, height = 520, scale;
// this is a simple Boxfit calculation for the `cover` mode. You could
// use the applyBoxFit function instead, but as it doesn't return a
// centered rect it's almost as much work to use it as to just do it
// manually (unless someone has a better way in which case I'm all ears!)
double rw = size.width / width;
double rh = size.height / height;
double actualWidth, actualHeight, offsetLeft, offsetTop;
if (rw > rh) {
// height is constraining attribute so scale to it
actualWidth = rh * width;
actualHeight = size.height;
offsetTop = 0.0;
offsetLeft = (size.width - actualWidth) / 2.0;
scale = rh;
} else {
// width is constraining attribute so scale to it
actualHeight = rw * height;
actualWidth = size.width;
offsetLeft = 0.0;
offsetTop = (size.height - actualHeight) / 2.0;
scale = rw;
}
canvas.translate(offsetLeft, offsetTop);
canvas.scale(scale);
// parameters from the original drawing (guesstimated a bit using
// preview...)
const double startX = 60;
const double startY = 430; // flutter starts counting from top left
const double dashSize = 5;
const double gapSize = 16;
canvas.drawPath(
dashPath(
Path()
// tell the path where to start
..moveTo(startX, startY)
// the offset tells the arc where to end, the radius is the
// radius of the circle, and largeArc tells it to use the
// big part of the circle rather than the small one.
// The implied parameter `clockwise` means that it starts the arc
// and draw clockwise; setting this to false would result in a large
// arc below!
..arcToPoint(Offset(520 - startX, startY), radius: Radius.circular(260), largeArc: true),
// dash is `dashSize` long followed by a gap `gapSize` long
dashArray: CircularIntervalList<double>([dashSize, gapSize]),
dashOffset: DashOffset.percentage(0.005)),
Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = dashSize);
}
#override
bool shouldRepaint(DashedArc oldDelegate) {
return oldDelegate.color != this.color;
}
}
Here I am passing a list of the image to ImagePaint class to clip image in a circular, Its fine the images are clipping but only clipping some part of the image, If I could decrease this height and width of the image. Then it will fit the circle, Please comment if any have an idea.
void paint(Canvas canvas, Size size) {
int c = 0;
canvas.save();
canvas.translate(size.width / 2, size.height / 2);
canvas.rotate(-rotation);
for (var i = 0; i < 16; ++i) {
if (i % 2 == 0) {
canvas.drawLine(
new Offset(0.0, 0.0),
new Offset(0.0, size.width / 2 - 4.2),
tickPaint,
);
} else {
canvas.save();
canvas.translate(-0.0, -((size.width) / 2));
canvas.clipPath(path);
if (images[c] != null) {
ui.Image img = images[c];
canvas.drawImage(img, Offset(0.0, 0.0), new Paint());
}
canvas.rotate(2 * pi);
canvas.restore();
c++;
}
canvas.rotate(2 * pi / 16);
}
canvas.restore();}
This image is printed in a circular manner:
This is my app I am clipping image and printing in circular:
I just figured out how to reduce the image and send it to the painter for drawing.
The method that shrinks the image and what it returns is sent to the drawing class.
If it works for you, thank me for my reply with a thumbs up, thanks.
import 'dart:ui' as ui;
import 'package:image/image.dart' as IMG;
Future<ui.Image> loadImage( List<int> data ) async {
final IMG.Image image = IMG.decodeImage(data);
final IMG.Image resized = IMG.copyResize(image, width: 200);
final List<int> resizedBytes = IMG.encodePng(resized);
final Completer<ui.Image> completer = new Completer();
ui.decodeImageFromList(resizedBytes, (ui.Image img) => completer.complete(img));
return completer.future;
}
Drawing class.
class CustomDraw extends CustomPainter {
final ui.Image image;
const CustomDraw({this.image});
#override
void paint(Canvas canvas, Size size) {
Paint paint = new Paint();
canvas.drawImage(image, new Offset(40.0, 10.0), paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
I'm working with XNA and a have a problem.
A basic problem, but argh !!!
I want to draw a ocean, BASIC ocean, just a plane, blue and transparent.
just a plane.
I have try with Vertex, with models and textures.
How tha alpha channel work in XNA ? StencilState, DepthBuffer, nothing would work.
Can you explain how to do this ?
Use VertexPositionColor enough ?
Excuse me, but I am looking for a long time.
class Ocean
{
Effect shader0;
public Vector3 Position;
GraphicsDevice Graphics;
Camera camera;
Model Mesh;
Texture2D waterTexture;
Rectangle screen;
Texture2D test;
public Ocean(Vector3 pos, int size, GraphicsDevice gra, Camera cam, ContentManager content)
{
Graphics = gra;
shader0 = content.Load<Effect>("Ocean");
//shader0 = new BasicEffect(this.Graphics);
waterTexture = content.Load<Texture2D>("Images/shaderUnderwater");
screen = new Rectangle(0, 0, this.Graphics.Viewport.Width, this.Graphics.Viewport.Height);
Position = pos;
Mesh = content.Load<Model>("Models/ocean");
camera = cam;
foreach (ModelMesh mesh in this.Mesh.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect = shader0;
}
}
}
bool underWater;
Vector3 lightDirection = new Vector3(-1.0f, -1.0f, -1.0f);
public void Draw(SpriteBatch spriteBatch, Player player)
{
Matrix world = Matrix.CreateScale(100f) * Matrix.CreateRotationX(MathHelper.ToRadians(-90f)) * Matrix.CreateTranslation(Position);
//this.shader0.EnableDefaultLighting();
this.shader0.Parameters["World"].SetValue(world);
this.shader0.Parameters["View"].SetValue(player.Camera.View);
this.shader0.Parameters["Projection"].SetValue(player.Camera.Projection);
// Dessin du model
foreach (ModelMesh mesh in this.Mesh.Meshes)
{
foreach (Effect effect in mesh.Effects)
{
effect.CurrentTechnique = effect.Techniques["Textured"];
effect.Parameters["DiffuseColor"].SetValue(new Vector4(1f, 0.2f, 0.2f, 1f) ); // a reddish light
effect.Parameters["DiffuseLightDirection"].SetValue(new Vector3(1, 0, 0) ); // coming along the x-axis
effect.Parameters["SpecularColor"].SetValue(new Vector4(0, 1, 0 ,1f) ); // with green highlights
effect.Parameters["World"].SetValue(world);
effect.Parameters["View"].SetValue(player.Camera.View);
effect.Parameters["Projection"].SetValue(player.Camera.Projection);
}
mesh.Draw();
}
this.Graphics.BlendState = BlendState.Opaque;
//Effet
if (camera.Position.Y < Position.Y)
spriteBatch.Draw(this.waterTexture, this.screen, Color.White);
}
public void Update(GameTime gameTime)
{
}
void onWater()
{
underWater = true;
}
}
}
If you are using the BasicEffect to render the ocean, then BasicEffect has an Alpha property, which affects the transparency. Please see here: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.basiceffect.alpha.aspx
You can use BasicEffect to create transparency with any way that you are using for rendering your model.
I create stage walls and a box inside on my mobile app using starling + as3.
Ok, now when I test the app the box falls but it does not match the walls, as if there
was an offset:
https://www.dropbox.com/s/hd4ehnfthh0ucfm/box.png
Here is how I created the boxes (walls and the box).
It seems like there is an offset hidden, what do you think?
public function createBox(x:Number, y:Number, width:Number, height:Number, rotation:Number = 0, bodyType:uint = 0):void {
/// Vars used to create bodies
var body:b2Body;
var boxShape:b2PolygonShape;
var circleShape:b2CircleShape;
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = boxShape;
fixtureDef.friction = 0.3;
// static bodies require zero density
fixtureDef.density = 0;
var quad:Quad;
bodyDef = new b2BodyDef();
bodyDef.type = bodyType;
bodyDef.position.x = x / WORLD_SCALE;
bodyDef.position.y = y / WORLD_SCALE;
// Box
boxShape = new b2PolygonShape();
boxShape.SetAsBox(width / WORLD_SCALE, height / WORLD_SCALE);
fixtureDef.shape = boxShape;
fixtureDef.density = 0;
fixtureDef.friction = 0.5;
fixtureDef.restitution = 0.2;
// create the quads
quad = new Quad(width, height, Math.random() * 0xFFFFFF);
quad.pivotX = 0;
quad.pivotY = 0;
// this is the key line, we pass as a userData the starling.display.Quad
bodyDef.userData = quad;
//
body = m_world.CreateBody(bodyDef);
body.CreateFixture(fixtureDef);
body.SetAngle(rotation * (Math.PI / 180));
_clipPhysique.addChild(bodyDef.userData);
}
The SetAsBox method takes half width and half height as its parameters. I'm guessing your graphics don't match your box2d bodies. So either you will need to make your graphics twice as big or multiply your SetAsBox params by 0.5. Also the body pivot will be in the center of it, so offset your movieclip accordingly depending on its pivot position.
Note that box2d has a debugrenderer which can outline your bodies for you to see what's going on.
I used THREE.js r49 create 2 cube geometry with a directional light to cast shadow on them and got result as in the following picture.
I noticed that the shadow in the green circle should not be appeared, since the directional light is behind both of the cube. I guess that this is the material issue, I've tried changing various material parameters as well as change the material type itself, but the result still the same. I also tested the same code with r50 and r51 and got the same result.
Could anybody please give me some hint how to get rid of that shadow.
Both cube are creating using CubeGeometry and MeshLambertMaterial as following code.
The code:
// ambient
var light = new THREE.AmbientLight( 0xcccccc );
scene.add( light );
// the large cube
var p_geometry = new THREE.CubeGeometry(10, 10, 10);
var p_material = new THREE.MeshLambertMaterial({ambient: 0x808080, color: 0xcccccc});
var p_mesh = new THREE.Mesh( p_geometry, p_material );
p_mesh.position.set(0, -5, 0);
p_mesh.castShadow = true;
p_mesh.receiveShadow = true;
scene.add(p_mesh);
// the small cube
var geometry = new THREE.CubeGeometry( 2, 2, 2 );
var material = new THREE.MeshLambertMaterial({ambient: 0x808080, color: Math.random() * 0xffffff});
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0, 6, 3);
mesh.castShadow = true;
mesh.receiveShadow = true;
// add small cube as the child of large cube
p_mesh.add(mesh);
p_mesh.quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), 0.25 * Math.PI );
// the light source
var light = new THREE.DirectionalLight( 0xffffff );
light.castShadow = true;
light.position.set(0, 10, -8); // set it light source to top-behind the cubes
light.target = p_mesh // target the light to the large cube
light.shadowCameraNear = 5;
light.shadowCameraFar = 25;
light.shadowCameraRight = 10;
light.shadowCameraLeft = -10;
light.shadowCameraTop = 10;
light.shadowCameraBottom = -10;
light.shadowCameraVisible = true;
scene.add( light );
Yes, this is a known, and long-standing, WebGLRenderer issue.
The problem is that the dot product of the face normal and the light direction is not taken into consideration in the shadow calculation. As a consequence, "shadows show through from the back".
As a work-around, you could have a different material for each face, with only certain materials receiving shadows.
three.js r.71