QML: add border to free form image - image

I have a free form image with transparency (let's say, a small image of a blue car). The image has transparency, so that I can place the car on the map of a game.
Now, some areas of the game map are bluish, and the car kinda blends in. Is it possible to add a white border automatically in QML? I can't use GIMP or other things to work directly on the image (and I have lots of such images to manipulate) so it would be awesome if there was a QML builtin functionality for this...

In situations like this, a drop shadow is a good way of making an item standout. You normally would make it black or white based on the opposite of the average gray level of the image content itself.
It's pretty easy to add a DropShadow to an Image. This example places a nice light black drop shadow onto an image.
import QtGraphicalEffects 1.0
Image {
source: "my_image.png"
layer.enabled: true
layer.effect: DropShadow {
verticalOffset: 3
horizontalOffset: 0
radius: 8
color: "#26000000"
}
}
For more info see: https://doc.qt.io/qt-5/qml-qtgraphicaleffects-dropshadow.html
If you want a centered box shadow instead, just use a Rectangle somewhat like this:
Rectangle {
layer.enabled: true
layer.effect: DropShadow {
radius: 8
color: "#26000000"
}
Image {
source: "my_image.png"
}
}
Or if you just want a white border only:
Rectangle {
color: "transparent"
border.color: "white"
border.width: 2
Image {
source: "my_image.png"
}
}

Related

Solving Overlapping Images when zooming in Codenameone

I have an imageviewer with a couple images, When i zoom in the first image and wanna see the right side of the image. The folowing image is overlapping the inzooming image. This is very annoying. Is there a way how i can set the zoom in image on the front.
How can i set the zoomed image always on front.
See picture https://i.stack.imgur.com/5f5JZ.jpg
My imageviewer is in a container
Image red ;
red = EncodedImage.create("/HW_Delfzijl_Waddenzee_Oost.jpg");
Image blue = Image.createImage(500, 500, 0xff0000ff);
Image red2 = Image.createImage(500, 500, 0xffff0000);
Image List1[]= new Image [3];
List1[0] = red;
List1[1] = blue;
List1[2] = red2;
iv = new ImageViewer();
iv.setWidth(500);
iv.setHeight(500);
iv.setImageList(new DefaultListModel<>(List1));
Container1 = BoxLayout.encloseY( Kaarten.AuvHW, AdvSpr,iv,
Up,progressbar);
I was able to reproduce this with the following code:
Form hi = new Form("ImageViewer", BoxLayout.y());
Image red = Image.createImage(2000, 800, 0xffff0000);
Image blue = Image.createImage(2000, 500, 0xff0000ff);
ImageViewer viewer = new ImageViewer();
viewer.setImageList(new DefaultListModel<>(red, blue));
hi.add(BoxLayout.encloseY(viewer, new Label("Dummy")));
hi.show();
The problem only happens if I stand on the blue image (the second one) scale it up and then try to move. It doesn't happen when moving from the red image to the blue.
I believe this is due to this method in the ImagaViewer code. Since background isn't painted the old image isn't cleaned up. We need to add a condition that disables that while dragging. I think changing the code in that method to this will fix the problem but it's a bit risky and might trigger flickering:
protected void paintBackground(Graphics g) {
// disable background painting for performance when zooming
if(imageDrawWidth < getWidth() || imageDrawHeight < getHeight() || panPositionX != 0) {
super.paintBackground(g);
}
}
I would suggest filing an issue so we can consider the options here as this isn't trivial. One partial workaround is to use:
viewer.setImageInitialPosition(ImageViewer.IMAGE_FILL);
Which minimizes the impact of the issue.

How to display both portrait & landscape images into a square on the grid without disturbing the aspect ratio?

I am using a GridView to create a gallery of images that I display from a certain folder on my machine. The images are of different width*height ratios. Few are portrait images where the height of the image is like 3 times more than width. Some image are landscape like where the width is approx 3 times of height. And some images are squared.
The issue with my gallery is I have a square for each Image component of my GridView as you can see below. This makes the portrait & landscape images get incorrectly stretched as each block in the Grid is a square. Thus causing the aspect ratio of the image to get skewed up.
The Question:
How can I ensure that I display both portrait & landscape images into my square without skewing the aspect ratio? I am looking at putting some black/grey background on parts of the square which go blank on a portrait or landscape image? But there might be other tricks.
The code:
import QtQuick 2.5
import Qt.labs.folderlistmodel 2.1
import QtQuick.Controls 1.1
import QtQml.Models 2.1
GridView {
cellHeight: height/2
cellWidth: width/2
clip: true
FolderListModel {
id: dir_model
folder: "/path/to/images/folder"
nameFilters: ["*.png"]
}
Component {
id: file_delegate
Image {
width: (parent.width)/2
height: (parent.width)/2
source: fileURL
}
}
model: dir_model
delegate: file_delegate
}
Just set Image fillMode property to Image.PreserveAspectFit
As the doc says:
the image is scaled uniformly to fit without cropping

React Navigation transitionConfig Color

I see there is an option for transitionConfig to enter values such as the animation style or the duration. I was wondering if there was a way to change the color of the background during the transition (the semi-transparent background that appears during the transition)? For example, I have fairly dark screens and during the transition the background kind of flashes white.
Is this either configurable directly, or is it maybe a property of the parent navigator?
Thanks
I see during the transition process the area between the focussed screen and the edge of the screen goes from white with an opacity of 1 to transparent. Is it possible to maybe begin from another color such as black?
Try adding:
cardStyle: {
backgroundColor: 'white'
},
in your StackNavigatorConfig
I solved this issue by adding this to my StackNavigator:
cardStyle: {
backgroundColor: 'rgba(0,0,0,0)',
opacity: 1,
},
Now the transition is completely transparent. I tried using only opacity: 1 as suggested but it didn't work. I'm using "react-navigation": "^1.5.11".
If you are were a TabBarNavigator component then you can have a look at this part of the documentation to fix color problems during transitions.
If you combine swipeEnabled, animationEnabled and lazy properties you will get a better result in transitions. Otherwise, a gray/transparent color will be used during screens' transitions.
const tabNavigatorConfig: TabNavigatorConfig = {
...
swipeEnabled: true,
animationEnabled: false,
lazy: false,
...
};

Xamarin.Forms - How To Achieve 45 deg. Angled Background Color

Using Xamarin.Forms, how would I achieve the following angled background without using an image:
A 100% Xamarin.Forms with no "custom renderer" involved solution:
In the example below, the solid blue portion of the semi-transparent box behind the Labels on the screen is a NControl, you can also do gradients, simple animations, etc... but in this case just a solid polygon is being drawn within a semi-transperent rectangle:
Using NGraphics via NControl you can do a lot in terms of drawing custom controls in Xamarin.Forms without custom renderers. It is not a solution in every use-case, but its clean and works cross-platform (iOS/Android/WinPhone).
var overlay = new NControlView()
{
BackgroundColor = Xamarin.Forms.Color.Black.MultiplyAlpha(.3f),
DrawingFunction = (canvas, rect) =>
{
canvas.FillPath(new PathOp[] {
new MoveTo (NGraphics.Point.Zero),
new LineTo ((rect.Width / 3), 0),
new LineTo ((rect.Width / 3) * 2, rect.Height),
new LineTo (0, rect.Height),
new ClosePath ()
}, Colors.Blue);
}
};
Rendered in Red with a heavier alpha setting so you can see the control better:
This control is embedded in an AbsoluteLayout that uses dynamic bounds so even orientation changes are handled cleanly:
AbsoluteLayout.SetLayoutFlags(overlay, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds(overlay, new Xamarin.Forms.Rectangle(0, 1, 1, 0.3));
https://github.com/praeclarum/NGraphics
https://github.com/chrfalch/NControl
There is no way to define a gradient in Xamarin Forms. Your best bet would be to use an image. However, you could also try writing a custom renderer that used the underlying platform API to draw a gradient background.
Here is a thread that discusses using the custom renderer approach.

EaselJS spritesheet animation makes background disappear

I am working on a game using EaselJS, and I am still trying the functions provided by this great library.
What I may need is Alphamaskfilter class & Spritesheet class.
Currently, I have a canvas like this:
<canvas id = 'container3' width = 320px; height = 480px;
style = 'outline: 2px solid; margin-right: 10px;float:left;'></canvas>
and in my script, I have draw a rect with blue color:
var ctx3 = document.getElementById('container3').getContext('2d');
ctx3.beginPath();
ctx3.rect(0,0,320,480);
ctx3.fillStyle = 'blue';
ctx3.fill();
So now I have a blue color 320*480 canvas. And now I have a sprite sheet to animate on it,
here is the sprite and code I wrote:
http://i.imgur.com/XumDvic.png
PS: the sprite frame is 200*200 FYI.
stage = new createjs.Stage(document.getElementById('container3'));
var test = new Image();
test.src = 'trans_blackball.png';
test.onload = function(){
var sprite = new createjs.SpriteSheet({
images: [test],
frames: {width: 200, height: 200},
animations: {
born: [0,3,0]
}
});
var animation = new createjs.BitmapAnimation(sprite);
animation.gotoAndPlay("born");
animation.x = 10;
animation.y = 10;
animation.currentFrame = 0;
stage.addChild(animation);
createjs.Ticker.addListener(window);
createjs.Ticker.useRAF = true;
createjs.Ticker.setFPS(10);
}
function tick(){
stage.update();
}
Okay, my question is: I expect an animation of an enlarging black circle on a blue background(rect), but what I got is firstly the canvas is blue, but for a certain mini-second after, the whole canvas became white, and the animation is running on the white background, what is the reason of this and how can I solve it?
Here is two points that may help:
I am working with chrome, and I check with F12 & console, the fillStyle of the canvas is still blue even it appears white after the sprite animation start
If I set the canvas background property to blue instead of drawing a blue rect on it, everything's fine!!
<canvas id = 'container3' width = 320px; height = 480px;
style = 'background: blue; outline: 2px solid; margin-right:
10px;float:left;'></canvas>
but clearly this is not what I want...
The problem can be solved as well by not using native canvas rect but use EaselJS's Shape to draw the rect:
var shape = new createjs.Shape();
shape.graphics.beginFill("#ff0000").drawRect(0, 0, 320, 480);
stage.addChild(shape);
But I still wanna know why the native rect drawing code is not working...
Please bare my bad english and thanks for reading and any attempt to help...I can elaborate more if there is anything unclear in the situation..thanks!
createjs.Stage.update() will clear the canvas-contents by default before rendering the new frame.
The reason for this is one the one hand the technical behaviour of canvas, the canvas is basically just an image of pixels, you cannot have real 'layers' and say "I just want to remove/update this one object" - you just can modify the flattened pixels of the frame or remove everything and redraw it(which is safer, easier to achieve, and actually fast enough performance-whise. And on the other hand, it makes sense to make consistent use of a framework like EaselJS, and not do some parts with the framework and some parts without it, this would result in a big mess at the end.
So, the right solution is to go with 3.
You can set myStage.autoClear = false; to prevent the Stage from autoClearing the canvas on every update() but I don't think this will suit your needs in this case.
I would recommend instead using the EaselJS Shape class to make your blue box. If it part of the EaselJS display list, it will be drawn with the other content.
javascript
var shape = new createjs.Shape();
shape.graphics.beginFill("blue").drawRect(0,0,320,480);
stage.addChild(shape);

Resources