How come this image won't resize to fit the sprite? - apache-flex

I have this snippet of ActionScript code that is supposed to resize an image to fit the sprite: (as in rescale the image not just clip it)
package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.Event;
public class Main extends Sprite
{
[Embed(source = 'img.png')]
private var TheImage:Class;
public static const TheImageWidth:Number = 1300;
public static const TheImageHeight:Number = 1300;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var image:Bitmap = new TheImage();
addChild(image);
image.scaleX = width / TheImageWidth;
image.scaleY = height / TheImageHeight;
}
}
}
Why isn't it working? The image isn't getting the right dimensions.

try
image.image.content.width = TheImageWidth;
image.image.content.height = TheImageHeight;

I had to do the something like this for imagery. We had issue with using MapImage and the MapImageLayer using ArcGIS for Flex 2.5. It seems to be fix in 3.5, Anyways I had to put an image into a sprite and paint the image based on the sprites width. If you want to scale the image to the sprite's dimensions you will need to use the Matrix API and use the scale method. The values passed into this should be the sprite's width divided by the image's width assuming the image is bigger than your sprite. Do the same with the height. Here is the code I used to accomplish the task.
const point:MapPoint = geometry as MapPoint;
sprite.x = toScreenX(map, point.x);
sprite.y = toScreenY(map, point.y);
// grab left x point for upper left then for lower right
// actua
var bottomLeftX:Number = toScreenX(map, geomertyWrapper.extent.xmin);
var topRightX:Number = toScreenX(map, geomertyWrapper.extent.xmax);
var bottomLeftY:Number = toScreenY(map, geomertyWrapper.extent.ymin);
var topRightY:Number = toScreenY(map, geomertyWrapper.extent.ymax);
iconWidth = Math.abs(topRightX - bottomLeftX);
iconHeight = Math.abs(topRightY - bottomLeftY);
sprite.width = iconWidth;
sprite.height = iconHeight;
var scaleX:Number = iconWidth/bitmapData.width;
var scaleY:Number = iconHeight/bitmapData.height;
m_matrix.a = 1.0;
m_matrix.d = 1.0;
m_matrix.scale(scaleX, scaleY);
m_matrix.tx = -iconWidth / 2;
m_matrix.ty = -iconHeight / 2;
//Values needed for drawing AlertNotificationInstance
sprite.graphics.beginBitmapFill(m_bitmapData, m_matrix, false, false);
sprite.graphics.drawRect(m_matrix.tx, m_matrix.ty,
iconWidth,
iconHeight);
sprite.graphics.endFill();
Hope this helps.

Related

Scaling start screen with fullscreen JavaFX

I'm stuck on full scaling for my JavaFX application. I'm in the process of making a full screen feature for the application and I'm running into issues on trying to get the aspect ratio and positioning right without manually editing the values.
With the way I've been trying, the values butcher the game's start screen making the positioning change making the designs of the game offset from the center of the application. I can understand the reasoning behind it with the way I set it up. My problem is wondering how to scale the start screen and keep it's original position without having to manually edit the values.
What I thought of was trying to input the value and having it scale according to that value then putting the result in the position of objects X and Y.
if (fullscreen) {
WIDTH = (Enter aspect ratio here) * 1.5;
HEIGHT = (Enter aspect ratio here) * 1.5;
} else {
WIDTH = 990;
HEIGHT = 525;
}
with Obvious flaws this butchers the start screen.
My solution was to make a double() that you just enter the value of the application WIDTH/HEIGHT then entering the amount you want to divide by (since I couldn't come up with exact cords, I grabbed the WIDTH and divided by specific value for it to align in the center) following with a boolean to state whether it's full screened or not. Though my only issue with this theory is that it'll only work with 1920x1080 monitors so I'd assume I would have to manually enter all types of aspect ratios to make it fit otherwise the start screen would be butchered.
I've seen a way of scaling here:
JavaFX fullscreen - resizing elements based upon screen size
Though I'm not sure how to correctly implement it.
public static boolean fullscreen = false;
public static double WIDTH = 990;
public static double HEIGHT = 525;
public static Pane pane = new Pane();
public static void StartScreen() {
pane.setPrefSize(WIDTH, (HEIGHT - 25)); // the 25 is for the text field/input.
pane.setStyle("-fx-background-color: transparent;");
Group sGroup = new Group();
Image i = new Image("file:start/So7AA.png");
ImageView outer = new ImageView(i);
// outer.setX(Ce.WIDTH/4.75); //4.75 // The functioning code for the snippit
// outer.setY(-10); //-10
outer.setX(Ce.WIDTH/position(3.60, fullscreen)); //4.75 // The non functioning code.
outer.setY(position(-1, Ce.fullscreen)); //-10
outer.setFitWidth(550);
outer.setFitHeight(550);
outer.setOpacity(.3);
GaussianBlur gBlur = new GaussianBlur();
gBlur.setRadius(50);
ImageView seal = new ImageView(i);
// seal.setX(Ce.WIDTH/3.83); //247.5 - 3.83
// seal.setY(39); //39
seal.setX(Ce.WIDTH/position(3.83, fullscreen)); //247.5 - 3.83
seal.setY(position(32, Ce.fullscreen)); //39
seal.setFitWidth(450);
seal.setFitHeight(450);
ImageView sealBlur = new ImageView(i);
// sealBlur.setX(Ce.WIDTH/3.83); //247.5 - 3.83
// sealBlur.setY(39); //39
sealBlur.setX(Ce.WIDTH/position(3.83, fullscreen)); //247.5 - 3.83
sealBlur.setY(position(32, Ce.fullscreen));
sealBlur.setFitWidth(450);
sealBlur.setFitHeight(450);
sealBlur.setEffect(gBlur);
}
For getting the values of the WIDTH and HEIGHT:
public static double getWidth(double W, boolean fs) {
if (fs) {
return WIDTH = Screen.getPrimary().getBounds().getMaxX();
} else {
return WIDTH = W;
}
}
public static double getHeight(double H, boolean fs) {
if (fs) {
return HEIGHT = Screen.getPrimary().getBounds().getMaxY();
} else {
return HEIGHT = H;
}
}
I know there's a way around this, I'm just not sure how to pull it off.
I'm not sure exactly what the requirements are here, but it looks like you have three images, which you want centered, and you want them all scaled by the same amount so that one of the images fills the available space in its container. (Then, you just need to make sure its container grows to fill all the space, and you can call stage.setFullScreen(true) or stage.setMaximized(true) as needed.)
You can do this with a pretty simple custom pane that manages the layout in the layoutChildren() method:
public class ImagePane extends Region {
private final Image image1;
private final ImageView imageView1;
private final Image image2;
private final ImageView imageView2;
private final Image image3;
private final ImageView imageView3;
public ImagePane(Image image1, Image image2, Image image3) {
this.image1 = image1;
this.image2 = image2;
this.image3 = image3;
imageView1 = new ImageView(image1);
imageView2 = new ImageView(image2);
imageView3 = new ImageView(image3);
getChildren().addAll(imageView1, imageView2, imageView3);
}
#Override
protected void layoutChildren() {
double xScale = getWidth() / image1.getWidth();
double yScale = getHeight() / image1.getHeight();
double scale = Math.min(xScale, yScale);
for (ImageView view : List.of(imageView1, imageView2, imageView3) {
scaleAndCenter(view, scale);
}
}
private void scaleAndCenter(ImageView view, scale) {
double w = scale * view.getImage().getWidth();
double h = scale * view.getImage().getHeight();
view.setFitWidth(w);
view.setFitHeight(h);
view.relocate((getWidth()-w) / 2, (getHeight()-h) / 2);
}
}
The rest of your layout looks something like:
Label label = new Label("Type in 'start'.\nType in 'options' for options.\n(Demo)");
TextField textField = new TextField();
ImagePane imagePane = new ImagePane(new Image(...), new Image(...), new Image(...));
AnchorPane anchor = new AnchorPane(imagePane, label);
AnchorPane.setTopAnchor(imagePane, 0.0);
AnchorPane.setRightAnchor(imagePane, 0.0);
AnchorPane.setBottomAnchor(imagePane, 0.0);
AnchorPane.setLeftAnchor(imagePane, 0.0);
AnchorPane.setTopAnchor(label, 5.0);
AnchorPane.setLeftAnchor(label, 5.0);
BorderPane root = new BorderPane();
root.setCenter(anchor);
root.setBottom(textField);
Now everything should just respond to whatever size is assigned to the root pane, so setting full screen mode should "just work".

Issue while setting slider thumb at a particular point if slider maximum value is too high?

I am working in xamarin forms. I have slider whose maximum value is more than 200. I want to move the slider thumb at particular point on slider for example at 120, but it becomes very tough to put the thumb at particular point. This happens with large maximum values. If values are less then its working fine.
So is there any solution so that we can move the slider's thumb easily at any point if slider's maximum value is very large?
You can set the increase value like this GIF.
Here is code.I set the StepValue to 20
public partial class MainPage : ContentPage
{
private double StepValue;
private Slider SliderMain;
public MainPage()
{
InitializeComponent();
StepValue = 20.0;
BindingContext = new HslColorViewModel();
SliderMain = new Slider
{
Minimum = 0.0f,
Maximum = 200.0f,
Value = 0.0f,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand
};
SliderMain.BackgroundColor = Color.Black;
SliderMain.ValueChanged += OnSliderValueChanged;
Content = new StackLayout
{
Children = { SliderMain },
Orientation = StackOrientation.Vertical,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs e)
{
var newStep = Math.Round(e.NewValue / StepValue);
SliderMain.Value = newStep * StepValue;
}
}

AutoSizing Flex Mobile spark textarea component

I want to make my mobile spark textarea component to wrap all content. I found out mx_internal way of doing this but I'm not able to call mx_internal::getTextField().numLines method - there's no such... Anybody who has done this before?
Here is a solution for mobile:
for(var i:int=0; i < StyleableTextField(txt_genel.textDisplay).numLines; i++) {
ta_height += StyleableTextField(txt_genel.textDisplay).getLineMetrics(i).height;
}
txt_genel.height = ta_height;
Here a solution with little custom TextArea class, there's comments to explain a little more.
package
{
import mx.events.FlexEvent;
import spark.components.TextArea;
import spark.components.supportClasses.StyleableStageText;
import spark.events.TextOperationEvent;
public class CustomTextArea extends TextArea
{
private var _lineNumber:int = 1;
private var _padding:int;
private var _minHeight:int;
public function CustomTextArea()
{
super();
addEventListener(FlexEvent.CREATION_COMPLETE, function setBehaviour(event:FlexEvent):void
{
//minHeight to prevent textarea to be too small
_minHeight = height;
//padding between textarea and text component inside to calculate line number
_padding = ((textDisplay as StyleableStageText).x - x) + (width - (textDisplay as StyleableStageText).width);
//listener for text changing
addEventListener(TextOperationEvent.CHANGE, setHeight);
});
}
private function setHeight(event:TextOperationEvent):void
{
//line number is textwidth divided by component width
_lineNumber = (((textDisplay as StyleableStageText).measureText(text).width + _lineNumber * _padding) / width) + 1;
//text height is line number * text height
var newHeight:int = _lineNumber * (textDisplay as StyleableStageText).measureText(text).height;
//if new height > min height, set height
if (newHeight > _minHeight)
height = newHeight;
}
}
}
Hope this will help.
EDIT : With a big number of lines, the TextArea's height is rising too much. Should be manage.

How to distort images (or FXG) in Flex?

I want to distort images (or FXGs) in Flex.
Basically just want to modify the edges of an image like the image below. I know how to make simple distortions but I can't find a way of doing that.
The answers were right... what you need is a DisplacementMapFilter!!
The displacementImage should be grey in general -> means no distortion, and add a white and a gray radial gradient to each lower and upper edgelike this:
And with the Map you go like this:
package {
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.Point;
import flash.net.URLRequest;
public class DistortImage extends Sprite
{
private var sourceImage:Loader;
private var distortMap:Loader;
public function DistortImage()
{
super();
// Loading the Image to be distorted
sourceImage = new Loader();
var requ: URLRequest = new URLRequest("text.jpg");
sourceImage.contentLoaderInfo.addEventListener(Event.COMPLETE, loadMap);
sourceImage.load(requ);
}
private function loadMap( E:Event = null ):void{
// loading distortion map ( grayscale )
distortMap = new Loader();
var requ: URLRequest = new URLRequest("distortMap.jpg");
distortMap.contentLoaderInfo.addEventListener(Event.COMPLETE, applyDistortion);
distortMap.load(requ);
}
private function applyDistortion( E:Event = null ):void{
// get jpg as BitmapData
var bmpData:BitmapData = new BitmapData( distortMap.content.width,distortMap.content.height);
bmpData.draw(distortMap);
// create the filter - notice gray(128,128,128) means no distortion white is negative black is positive distortion
var offsetOfMap:Point = new Point(0,0);
var redChannelCode:uint = BitmapDataChannel.RED; // is not important cause you just need oneway distortion
var yDistortion:int = 20; // strength
var distortFilter:DisplacementMapFilter = new DisplacementMapFilter(bmpData,offsetOfMap,0,redChannelCode,0,yDistortion,DisplacementMapFilterMode.COLOR,0xffffff,0);
// filters need to be included in an array to add on display Object
var filters:Array = new Array();
filters.push(distortFilter);
// adding filter to image
sourceImage.filters = filters;
addChild(sourceImage);
}
}
}

Best way to get the color where a mouse was clicked in AS3

I have an image (mx) and i want to get the uint of the pixel that was clicked.
Any ideas?
A few minutes on the BitmapData LiveDoc Page will take you where you need to go. Once you have your image loaded into a Bitmap variable, you can access its BitmapData property. Add a Mouse Click Event Listener to the image and then use BitmapData::getPixel. The example for getPixel shows how to convert the uint response to an rgb hex code.
Here's a modification of the Example given on the BitmapData page that worked for me (using mxmlc - YMMV):
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
public class BitmapDataExample extends Sprite {
private var url:String = "santa-drunk1.jpg";
private var size:uint = 200;
private var image:Bitmap;
public function BitmapDataExample() {
configureAssets();
}
private function configureAssets():void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
var request:URLRequest = new URLRequest(url);
loader.load(request);
addChild(loader);
}
private function completeHandler(event:Event):void {
var loader:Loader = Loader(event.target.loader);
this.image = Bitmap(loader.content);
this.addEventListener(MouseEvent.CLICK, this.clickListener);
}
private function clickListener(event:MouseEvent):void {
var pixelValue:uint = this.image.bitmapData.getPixel(event.localX, event.localY)
trace(pixelValue.toString(16));
}
}
}
Here's an even simpler implementation. All you do is take a snapshot of the stage using the draw() method of bitmapData, then use getPixel() on the pixel under the mouse. The advantage of this is that you can sample anything that's been drawn to the stage, not just a given bitmap.
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.*;
stage.addEventListener(MouseEvent.CLICK, getColorSample);
function getColorSample(e:MouseEvent):void {
var bd:BitmapData = new BitmapData(stage.width, stage.height);
bd.draw(stage);
var b:Bitmap = new Bitmap(bd);
trace(b.bitmapData.getPixel(stage.mouseX,stage.mouseX));
}
Hope this is helpful!
Edit:
This edited version uses a single BitmapData, and removes the unnecessary step of creating a Bitmap. If you're sampling the color on MOUSE_MOVE then this is essential to avoid memory issues.
Note: if you're using a custom cursor sprite you'll have to use an object other than 'state' or else you'll be sampling the color of the custom sprite instead of what's under it.
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.*;
private var _stageBitmap:BitmapData;
stage.addEventListener(MouseEvent.CLICK, getColorSample);
function getColorSample(e:MouseEvent):void
{
if (_stageBitmap == null) {
_stageBitmap = new BitmapData(stage.width, stage.height);
}
_stageBitmap.draw(stage);
var rgb:uint = _stageBitmap.getPixel(stage.mouseX,stage.mouseY);
var red:int = (rgb >> 16 & 0xff);
var green:int = (rgb >> 8 & 0xff);
var blue:int = (rgb & 0xff);
trace(red + "," + green + "," + blue);
}
This is not specific to Flex or mx:Image, and allows you to grab a pixel color value from any bitmap drawable object (provided you have permission):
private const bitmapData:BitmapData = new BitmapData(1, 1);
private const matrix:Matrix = new Matrix();
private const clipRect:Rectangle = new Rectangle(0, 0, 1, 1);
public function getColor(drawable:IBitmapDrawable, x:Number, y:Number):uint
{
matrix.setTo(1, 0, 0, 1, -x, -y)
bitmapData.draw(drawable, matrix, null, null, clipRect);
return bitmapData.getPixel(0, 0);
}
You could easily grab a pixel from the stage or your mx:Image instance. It's a lot more efficient than drawing the entire stage (or drawable object), and should be fast enough to hook up to MouseEvent.MOUSE_MOVE for instant visual feedback.

Resources