[OpenFL] How to set backgroundImage ( for button) for not embedded images?

I try to use HaxeUI [ openfl version with html5 target ] and setting a background image for the button. As the images are not embedded in the app I couldn’t set as a string with path.
Is it possible directly to add Bitmap ( or BitmapData ) as a background for the class Button ( method .backgroundImage ) ?

Hmmm, im not entirely sure tbh, my instinct is “no its not possible” (at the moment), you can use backend specific image data (BitmapData for openfl) for various things in haxeui (button icons, image resources, etc), but im not sure you can do the same for background images, which i think is a css only property.

Do you happen to have a minimal test app of what you are trying to do? It sounds like a reasonable addition, but having an app (that doesnt work) feels like a nice place to start (rather than me having to guess functionality)

Cheers,
Ian

Here is a example project: https://drive.google.com/file/d/1K4c7ebCmTEDHN5qPFcLUsFHgCSaCDI1l/view?usp=sharing

The idea here is to set button.backgroundImage with BitmapData after load it from the web ( for that in project.xml embed="false" )

I have a few more questions:

  1. How to remove the default button bellow the background image ? ( without using style)
  2. How to set width/height for the background image ?
  3. How to simulate 2-3 px offset of the background image when clicking the button?

what do you mean “without using style”?

Without using styleName and declaration in css file i.e. is there something like button.hideOriginalButton = true; ?

At example I want to declare button in this way : var button = new Button(); without settings styleName , and I don’t want to use css file and this type of declaration <button text="Bitmap" styleName="bitmap-button" />

Well, you are going to have problems “unstyling” a button without using css (since it, and everything else, is styled with css)… i mean, haxeui is built on css. Any reason you dont want to use css?

EDIT: also, no there is no “hideOriginalButton”, i mean, that would mean there should also be “hideOriginalSlider”, “hideOriginalCheckBox”, “hideOriginalStepper”, etc? Which doesnt really make sense, when you can just unstyle / restyle all this with haxeui css (which is exactly what its for :slight_smile: )

You could do something like this:

var bitmapData = openfl.display.BitmapData.fromFile("C:\\Temp\\buttonBackground.png");
var testButton = new Button();
testButton.width = 200;
testButton.height = 100;
testButton.customStyle = {
    backgroundColor: -1,
    borderTopSize: 0,
    borderLeftSize: 0,
    borderBottomSize: 0,
    borderRightSize: 0,
    backgroundImageSliceTop: 15,
    backgroundImageSliceLeft: 15,
    backgroundImageSliceBottom: 71,
    backgroundImageSliceRight: 180,
    backgroundImage: bitmapData,
    fontSize: 20,
    color: 0xffffff
}

(ive used the “slice” attributes to have a nice slice-9 background image):

image

So that will work, though i dont really understand why you would go through all that effort when the css does the exact same thing and (imo) is much easier to maintain. also, you are going to have problems styling the different “states” in code (like over, down, active, etc, etc).

In your example backgroundImage: bitmapData doesn’t work.
Give a error :
openfl.display.BitmapData should be Null

About css, I have a bad memories using xml and css in Adobe Flex, but yes you a right.
Maybe I could use separate css for easy styling on different states ( down state mostly).
One problem maybe will be with the resizing the background image. At example for mobile I will manually resize image from 200x100px to 100x50x and this will require to recalculate backgroundImageSliceXXXX and set it for each button without using customStyle.

Would it be possible ,on down state, to move the background image some pixels down-right (as the example where on click button is moved some px down and right ):

buttonClick

You might need to update haxeui-core / haxeui-openfl, ive only recently (today) added the ability of bitmap data to be used for backgroundImage

background image some pixels down-right
something like

#myButton:down {
    background-position: 5px 5px;
}

(i also added this today)

Thank you Ian ! This is a nice addition.

1 Like

I did some tests with HaxeUI, but maybe I can’t use HaxeUI for what I want.
My use case is that. I want to create a button with a background image for different mobile devices.
Each device can have a different screen resolution, and for that reason, I should change the size of the button ( and the background image, respectively).
For example, my main background image is size 500x200, and I want to create a button 100x40 ( and keep the same proportion). Example button image:
btExample

Using background-image-slice gives very bad results; it’s not so usable for scaling images with different sizes. Example:
image

One solution will be to redraw the bitmap data with other sizes ( same proportion using matrix ).
The other solution will be to put bitmapData in a bitmap and set the width and height on the bitmap, but is impossible because you could not set the bitmap in HaxeUI.
I also tried to add bitmap data directly to the button ( addChild(buttonBitmap and set width and height), but this does not hide the button below. Example:
image

Then I set for background-image empty pixel ( backgroundImage: “img/emptyPx.png” , backgroundImageSlice:1) , which helps, but it’s more like a hack. Example with empty px background:
image

Can you show your css / code. Slice-9 should be working just fine.

EDIT: so i think the problem you are finding with slice-9 is that the button you are creating is smaller that the image (alot smaller), so the calculations of the “slices” overlap

Also, btw, not sure if you know, but haxeui should autoscale based on the mobile device dpi.

So i think these are your options:

slice-9, but scale input image first (noticed im scaling the image and the slice 9 co-ords by 25%):

var bitmapData2 = openfl.display.BitmapData.fromFile("buttonBackground2.png");
testButton2.customStyle = {
    backgroundColor: -1,
    borderTopSize: 0,
    borderLeftSize: 0,
    borderBottomSize: 0,
    borderRightSize: 0,
    backgroundImageSliceTop: 58 * .25,
    backgroundImageSliceLeft: 75 * .25,
    backgroundImageSliceBottom: 110 * .25,
    backgroundImageSliceRight: 400 * .25,
    backgroundImage: scaleBitmap(bitmapData2, .25),
    color: 0xffffff,
    cursor: "pointer"
}

use full image but stretch the background:

testButton4.customStyle = {
    backgroundColor: -1,
    backgroundImage: bitmapData2,
    backgroundImageRepeat: "stretch",
    color: 0xffffff,
    borderTopSize: 0,
    borderLeftSize: 0,
    borderBottomSize: 0,
    borderRightSize: 0,
    cursor: "pointer"
}

The problem with the second method is that the aspect ratio of the button has to be the same as the original image, which is obviously crappy.

Heres the results with the default Toolkit.scale (ie, 1 on desktop):

bitmap_buttons

and here are the results with Toolkit.scale = 2:

bitmap_buttons_scale_2

fyi, ive also used a bit of css to make things look a little nicer:

#testButton2 .label, #testButton4 .label {
    margin-top: -5px;
}

#testButton2:down, #testButton4:down {
    background-position: 1px 1px;
}

#testButton2:down .label, #testButton4:down .label {
    margin-top: -4px;
    margin-left: 1px;
}

Hopefully this helps somewhat?

Cheers,
Ian

… … So another thing around this :slight_smile:

I realise you arent a fan of css, but as ive mentioned previously, its kinda key, especially when styling states. However, the problem with the methods above is that they are using a bitmap data directly, and there is (was!) no easy way in haxeui css to reference that bitmap data (for example, if you wanted to use a different bitmap data for the over). Well, this is possible now!

Ive come up with a new css function “lookup”, which is basically just a map lookup, however, you can put anything into the map, and that, crucially, includes bitmap data. So, you can no do this:

var scale = .25;
StyleLookupMap.instance.set("bitmap-button-normal", scaleBitmap(BitmapData.fromFile("buttonBackground2.png"), scale));
StyleLookupMap.instance.set("bitmap-button-over", scaleBitmap(BitmapData.fromFile("buttonBackground2_over.png"), scale));
StyleLookupMap.instance.set("bitmap-button-slice-top", 58 * scale);
StyleLookupMap.instance.set("bitmap-button-slice-left", 75 * scale);
StyleLookupMap.instance.set("bitmap-button-slice-bottom", 110 * scale);
StyleLookupMap.instance.set("bitmap-button-slice-right", 400 * scale);

and then you can reference those items in haxeui css:

.bitmap-button {
    color: #ffffff;
    background-color: none;
    border: none;
    padding: 15px 15px;
    
    background-image: lookup('bitmap-button-normal');
    background-image-slice-top: lookup('bitmap-button-slice-top');
    background-image-slice-left: lookup('bitmap-button-slice-left');
    background-image-slice-bottom: lookup('bitmap-button-slice-bottom');
    background-image-slice-right: lookup('bitmap-button-slice-right');
}

.bitmap-button .label, .bitmap-button .image {
    margin-top: -5px;
}

.bitmap-button:hover {
    background-image: lookup('bitmap-button-over');
}

.bitmap-button:down {
    background-position: 1px 1px;
}

.bitmap-button:down .label, .bitmap-button:down .image {
    margin-top: -4px;
    margin-left: 1px;
}

and then you can use the styles, as normal:

<hbox>
    <button text="Bitmap Button" styleName="bitmap-button" width="120" height="50" />
    <vbox>
        <button text="Bitmap Button" styleName="bitmap-button" width="240" height="50" />
        <button text="Bitmap Button" styleName="bitmap-button" width="240" height="50" />
    </vbox>    
    <button text="Bitmap Button" styleName="bitmap-button" width="200" height="105" />
</hbox>    

<hbox>
    <button text="Bitmap Button (Autosized)" styleName="bitmap-button" />
    <button text="Bitmap Button (Fixed Width)\n\nWith a hard break" width="140" styleName="bitmap-button" />
    
    <grid columns="2">
        <button text="Left" styleName="bitmap-button" icon="haxeui-core/styles/default/haxeui_small.png" />
        <button text="Right" styleName="bitmap-button" icon="haxeui-core/styles/default/haxeui_small.png" iconPosition="right" />
        <button text="Top" styleName="bitmap-button" icon="haxeui-core/styles/default/haxeui_small.png" iconPosition="top" width="100%" />
        <button text="Bottom" styleName="bitmap-button" icon="haxeui-core/styles/default/haxeui_small.png" iconPosition="bottom" width="100%" />
    </grid>
</hbox>    

and the result:
bitmap_buttons_css

As i mentioned, i know you arent a fan of css, but for other (like myself), this is a super useful addition, to be able to reference ImageDatas at run time from style sheets! :partying_face:

1 Like

That looks like a very powerful option!
I’m really not a fan of css indeed, but maybe that is the right way to create UI.
One more question : How calculate the top, left, bottom right px for the slice ?
I use graphic program for that , but it’s a slow and if I have a lot different buttons it can be very tedious.

I’m really not a fan of css indeed, but maybe that is the right way to create UI.

for haxeui, its certainly a very important option (for state styling at least), i also think its a very “clean” option, keeping your styles 100% separate from your layout / app logic. Even though its possible to separate things in a “code only” approach, often things seep in and the lines get “blurred” - with xml, css, haxe theres almost 0% chance of that happening since they are totally different languages / files.

I use graphic program for that , but it’s a slow and if I have a lot different buttons it can be very tedious.

i have no good option tbh, i just did it manually in mspaint… even that one button was tedious enough for me to think “hmmm, i think im going to write an app to do this”, but obviously i havent (yet!)

Is this method scaleBitmap available ? I could not see it. I’ve got the error Unknown identifier : scaleBitmap.
Is it also available outside customStyle in the code ? At example :

    var scaleImage = Toolkit.scaleBitmap(bitmapData2, .25);
    testButton2.backgroundImage = scaleImage ; 

its just a function i wrote to scale an openfl bitmap, its not part of haxeui.

    private function scaleBitmap(bitmap:BitmapData, scale:Float):BitmapData {
        var cx = Std.int(bitmap.width * scale);
        var cy = Std.int(bitmap.height * scale);
        
        var scaleX:Float = cx / bitmap.width;
        var scaleY:Float = cy / bitmap.height;
        var matrix:Matrix = new Matrix();
        matrix.scale(scaleX, scaleY);
        var resizedBitamp = new BitmapData(cx, cy);
        resizedBitamp.draw(bitmap, matrix, null, null, null, true);
        return resizedBitamp;
    }
1 Like

Would it be possible to share your project ? I try to recreate step by step the project, but result was different. Here is the screenshot:

chrome_2022-04-25_13-40-42

The problems are :

  1. Background of the button is not hidden,
  2. On click position of the background not change
  3. I can’t apply bitmap button data style ( Error: String should be haxe.ui.styles.Style )

Here is my full test project: https://drive.google.com/file/d/1u6dC71yTmWwLCR7Sp_209TNMvfKDk0m9/view?usp=sharing

I’m using:
Haxe : 4.2.3
OpenFL : 9.2.0-LqBuHo
Lime: 7.9.0
Haxeui-core : git
Haxeui-openfl: git

Test target : HTML5
Command: openfl test html5