Masked images not displaying in AS3 - actionscript-3

I am trying to mask an image on another so that I only view the specific portion of the unmasked image through the masked one. My problem is that I cannot see anything on the screen.. no Image, no effect at all
cardMask = new Image(Root.assets.getTexture("card_mask"));
cardMask.y = Constants.STAGE_HEIGHT*0.40;
cardMask.x = Constants.STAGE_WIDTH *0.48;
trace("it's add mask");
cardLight = new Image(Root.assets.getTexture("card_light_mask"));
cardLight.y = Constants.STAGE_HEIGHT*0.46;
cardLight.x = Constants.STAGE_WIDTH *0.48;
cardLight.mask=cardMask;
maskedDisplayObject = new PixelMaskDisplayObject(-1,false);
maskedDisplayObject.addChild(cardLight);
maskedDisplayObject.x=cardLight.x;
maskedDisplayObject.y=cardLight.y;
maskedDisplayObject.mask=cardMask;
maskedDisplayObject.blendMode = BlendMode.SCREEN;
addChild(maskedDisplayObject);

First, for masking an object the mask object should also be added to the display list. Your code does not add cardMask to display list anywhere. Second, if your maskedDisplayObject should be visible at all times, the mask should be assigned not to it, but to some other object which displayed part you desire to control. And third, it is also possible that this.stage is null, therefore the entire tree (this -> maskedDisplayObject -> cardLight) is plain not rendered. You need to check all three of these conditions to get something displayed.
Also, if you desire cardLight as an object to move independently of maskedDisplayObject, you should add it to this instead, and check that it's displayed on top of maskedDisplayObject (call addChild(cardLight) after addChild(maskedDisplayObject)).
This all totals to this code:
trace("Stage is null:", (this.stage==null)); // if this outputs true, you're out of display
cardMask = new Image(Root.assets.getTexture("card_mask"));
cardMask.y = Constants.STAGE_HEIGHT*0.40;
cardMask.x = Constants.STAGE_WIDTH *0.48; // mask creation unaltered
trace("it's add mask");
cardLight = new Image(Root.assets.getTexture("card_light_mask"));
cardLight.y = Constants.STAGE_HEIGHT*0.46;
cardLight.x = Constants.STAGE_WIDTH *0.48;
cardLight.mask=cardMask; // this is right
maskedDisplayObject = new PixelMaskDisplayObject(-1,false);
// maskedDisplayObject.addChild(cardLight); this is moved to main part of display list
maskedDisplayObject.x=cardLight.x;
maskedDisplayObject.y=cardLight.y;
// maskedDisplayObject.mask=cardMask; NO masking of this, you're only masking cardLight
cardLight.blendMode = BlendMode.SCREEN; // display mode is also changed
addChild(maskedDisplayObject);
addChild(cardLight);

Related

ActionScript 3 Adding images; different positions

In short, I have clickable objects with varying colours. I want these colours upon being clicked to appear in my placeholders (there will be 6). I currently have managed to code so that upon clicking any colour it is placed in the first placeholder.
In what way am I able to code to recognise that the first placeholder has been filled and that once filled, the second placeholder should become the target?
Preferably until the 6th has been filled and then stopped, so that the user can see all 6.
I am thinking something like a for loop would be fitting, but I am not sure how to go about it.
So far it's looking something like this:
//Placeholder
var placeHolder1:MovieClip = new MovieClip();
placeHolder1.x = 20;
placeHolder1.y = 245;
stage.addChild(placeHolder1);
//Placeholder2 (UNUSED CURRENTLY)
var placeHolder2:MovieClip = new MovieClip();
placeHolder2.x = 60;
placeHolder2.y = 245;
stage.addChild(placeHolder2);
//Click and select colours
var newBlue:cBlue = new cBlue();
numBlue.addEventListener(MouseEvent.CLICK, fBlue)
function fBlue(e:MouseEvent){
placeHolder1.addChild(newBlue);
}
var newRed:cRed = new cRed();
numRed.addEventListener(MouseEvent.CLICK, fRed)
function fRed(e:MouseEvent){
placeHolder1.addChild(newRed);
}
First, you probably want to learn about Arrays (or Vectors). Arrays/Vectors are lists, so you would put all your placeholders into an array:
var placeHolders:Array = [placeHolder1, placeHolder2];
Though, since there is a formula to your place holder creation, you probably would want to do this in a loop to make it DRYer (Don't Repeat Yourself)
This loop would create 10 place holders and add them to the array:
var placeholders:Array = new Array();
for(var i:int=0; i < 10; i++){
var placeHolder = new Sprite(); //if your not using timelines, just use Sprite instead of MovieClip as it's less overhead
placeHolder.x = 20 * (i + 1); //i starts at 0, and goes to 9
placeHolder1.y = 245;
stage.addChild(placeHolder); //add it to the display list
placeholders.push(placeHolder); //add it to the array
}
Now (continuing to be DRY), attached the same event listener to all your color buttons:
numBlue.addEventListener(MouseEvent.CLICK, selectColor);
numRed.addEventListener(MouseEvent.CLICK, selectColor);
In that event handler I've called 'selectColor' (see code comments)
function selectColor(e:Event):void {
//get the first element in the array
var placeHolder:Sprite = placeholders.shift(); //shift removes the first item from the array, and returns it
placeHolder.addChild(e.currentTarget); //e.currentTarget refers to item that you attached the event listener to, in this case either numBlue or numRed
}
So to summarize, this gets the first placeholder in the array, remove that item from the array, then adds color button that was clicked as a child of that placeholder.

Oxyplot showing HeatMapSeries behind ScatterSeries

I am trying to combine LineSeries, ScatterSeries and HeatmapSeries on a single OxyPlot instance. I am able to show the first two just fine on the same plot and it looks like the following:
The axes for this are generated by the following code:
var xAxis = new DateTimeAxis();
xAxis.Key = "X";
xAxis.Position = AxisPosition.Bottom;
xAxis.AbsoluteMinimum = DateTimeAxis.ToDouble(CurrentPass.AOS);
xAxis.AbsoluteMaximum = DateTimeAxis.ToDouble(CurrentPass.LOS);
xAxis.AxislineColor = xAxis.TextColor = xAxis.TicklineColor = xAxis.MajorGridlineColor = OxyColors.DarkGray;
var yAxis = new LinearAxis();
yAxis.Key = "Y";
yAxis.Position = AxisPosition.Left;
yAxis.AbsoluteMinimum = 0.0;
yAxis.AbsoluteMaximum = MaximumFrequency;
yAxis.Maximum = MaximumFrequency;
yAxis.AxislineColor = yAxis.TextColor = yAxis.TicklineColor = yAxis.MajorGridlineColor = OxyColors.DarkGray;
If I add in a third axes for the Heatmap (not even a HeatMapSeries yet), I get the following:
The extra code here for the axis for the HeatMap is:
var heatmapAxis = new LinearColorAxis();
heatmapAxis.AbsoluteMinimum = 0.0;
heatmapAxis.AbsoluteMaximum = MaximumFrequency;
heatmapAxis.Palette = OxyPalettes.Gray(1024);
heatmapAxis.Key = "HeatMap";
I am not sure what's going on here. The line series still shows. And all the ScatterPoints from the scatterseries I have are definitely there - the tracker shows up and I can interact with the points (hover, click etc.). But the points don't show. If I add a HeatMapSeries, the HeatMapSeries data does show up as expected, the LineSeries data still shows up but no ScatterSeries data.
Again, the HeatMap data and the Scatter Series data show up individually, but never together.
Has anyone encountered this before? Are there workarounds?
Thanks,
Aditya
Sorry this is a bit late but just stumbled upon this. I had something similar with a line not showing up on a Heatmap and after some experimenting i realized the order in which the series' are added to the plot model make a big difference. Make sure you add your ScatterSeries after you've added your Heatmap to the plot model.

How to draw timelines in a tree table

I am writing an analyzer to visually see where my application is spending time. The interface that I am trying to achieve (see below) is something similar to a tree table with
lines or boxes to denote response time.
be a collapsible tree like graph
the ability to display metrics in the table columns (e.g., start time, cost, etc)
the ability to display the labels or description and metrics on the left and lines on the right
I create the following diagram (see below) in R -- unfortunately, although the graph production is automated, the approach is not interactive. I was wondering if you could suggest a better way -- maybe a tree table. I looked at many Swing, JavaFx tree table examples. I have not seen an example that has lines (time lines) in a tree table.
Any suggestions would be greatly appreciated. Thanks in advance.
You can show any node in a TreeTableCell using the grahic property in javaFX. This includes Rectangles.
This is a simple example of showing bars in a column using Rectangles:
// Arrays in TreeItems contain {startValue, endValue} (both positive)
TreeItem<int[]> root = new TreeItem<>(new int[]{0, 10});
root.getChildren().addAll(new TreeItem<>(new int[]{0, 5}), new TreeItem<>(new int[]{5, 10}));
TreeTableView<int[]> ttv = new TreeTableView<>(root);
// Column displaying bars based on data of TreeItem. Do not use this as
// the first column, otherwise the alignment be off depending on the
// distance to the root.
TreeTableColumn<int[], int[]> column = new TreeTableColumn<>();
column.setCellValueFactory(c -> c.getValue().valueProperty());
final double BAR_SIZE = 20;
column.setCellFactory((t) -> new TreeTableCell<int[], int[]>() {
// the bar
private final Rectangle rectangle = new Rectangle(0, 10);
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// bar invisible by default
rectangle.setVisible(false);
setGraphic(rectangle);
}
#Override
protected void updateItem(int[] item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
// resize and display bar, it item is present
rectangle.setWidth((item[1] - item[0]) * BAR_SIZE);
rectangle.setTranslateX(item[0] * BAR_SIZE);
rectangle.setVisible(true);
} else {
// no item -> hide bar
rectangle.setVisible(false);
}
}
});
// add a columns new column
// add a additional empty column at the start to prevent bars being
// aligned based on distance to the root
ttv.getColumns().addAll(new TreeTableColumn<>(), column);
Things you need to do
use a data type different to int[]; the cell value factory and TreeTableCell needs to be adjusted accordingly; an example of a more complex model can be found e.g. in the oracle tutorial: https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/tree-table-view.htm
Choose better colors; These colors could e.g. be stored in a Map and created if a new one is needed.
add additional colums

Getting all polygon coordinates of specific area of image? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have an image were I put links and text with html image map. That works fine. I would like to have some hover effect on specific areas of the image. For example take a world map and when you hover over a country that one get highlighted. With the html image map and some css it is not a problem, that is, if you have a list of all polygon coordinates of all countries.
So how do I get those? You cant possibly do that manually.
I am not a photoshop expert but I imagine you would do a "magic wand" selection on an area and then somehow list the coordinates that is used to create the selection. Is there such functionality?
I personally use Paint.Net for simple image editing and it does not have that feature that I know of.
Do you know the way to do this?
I'll tell you how to do it with JavaScript, since this is a programming Q/A site.
To get the rectangular coordinates of the selection bounds is easiest:
#target photoshop
// Save the current unit preferences (optional)
var startRulerUnits = app.preferences.rulerUnits
var startTypeUnits = app.preferences.typeUnits
// Set units to PIXELS
app.preferences.rulerUnits = Units.PIXELS
app.preferences.typeUnits = TypeUnits.PIXELS
// Use the top-most document
var doc = app.activeDocument;
var coords = doc.selection.bounds;
// Write coords to textfile on the desktop. Thanks krasatos
var f = File( '~/Desktop/coords.txt' );
f.open( 'w' );
f.write( coords );
f.close();
// Reset to previous unit prefs (optional)
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
This will give the rectangular bounds (think of the bounding box you see when transforming) of the selection in the current active document. It outputs in the order minX, minY, maxX, maxY. This should be enough info to translate to CSS coordinates.
To get the coordinates of individual polygon points you can make the selection into a path and output each pathPoint.anchor on the path using this script:
#target photoshop
// Save the current unit preferences (optional)
var startRulerUnits = app.preferences.rulerUnits
var startTypeUnits = app.preferences.typeUnits
// Set units to PIXELS
app.preferences.rulerUnits = Units.PIXELS
app.preferences.typeUnits = TypeUnits.PIXELS
// Use the top-most document
var doc = app.activeDocument;
// Turn the selection into a work path and give it reference
doc.selection.makeWorkPath();
var wPath = doc.pathItems['Work Path'];
// This will be a string with the final output coordinates
var coords = '';
// Loop through all path points and add their anchor coordinates to the output text
for (var i=0; i<wPath.subPathItems[0].pathPoints.length; i++) {
coords += wPath.subPathItems[0].pathPoints[i].anchor + "\n";
}
// Write coords to textfile on the desktop. Thanks krasatos
var f = File( '~/Desktop/coords.txt' );
f.open( 'w' );
f.write( coords );
f.close();
// Remove the work path
wPath.remove();
// Reset to previous unit prefs (optional)
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
Instructions:
-open your map image
-make a selection of the region using your favorite selection tool
-run the script with the extendscript toolkit or by choosing File>Scripts>Browse... and select the .jsx file where the script is saved.
there isn't any option in ps you have to make coordinates in Dreamweaver.

erasing a layer where mouse is over it

I got the following question.
i added the following elements to the stage:
homeBg = new HomeBg();
homeMask = new HomeDrawBg();
addChild(homeBg);
addChild(homeMask);
I allready instantiated them in the beginning of the document. But my problem is the following. the homeBg layer is a image, the homeMask layer is the same image but it has a pencil scetch look. What i want is that wherever i move my mouse, the homemask layer should be erased so the bottom layer becomes visible(only where the mask is erased). So how can i tell the mask layer to erase itself if the mouse is over it?
Answer attempt 2
You can use the blendMode property of a display object to achieve this. Here's the code (tested):
// set the eraser width (diameter)
var eraserWidth:int = 20;
//get the HomeMask library item
var homeMask:HomeMask = new HomeDrawBg();
homeMask.blendMode = BlendMode.LAYER;
addChild(homeMask);
// create the eraser shape
var eraser:Shape = new Shape();
eraser.graphics.beginFill(0x000000);
eraser.graphics.drawCircle(0,0,eraserWidth/2);
eraser.blendMode = BlendMode.ERASE;
homeMask.addChild(eraser);
homeMask.addEventListener(MouseEvent.MOUSE_MOVE,mouseOverMask);
function mouseOverMask(evt:MouseEvent):void
{
eraser.x = homeMask.mouseX;
eraser.y = homeMask.mouseY;
}
There are a couple of important bits here.
Firstly, you must set the blendMode of the thing you want to erase to BlendMode.LAYER.
Secondly (and this is what has tricked me before) your eraser, with BlendMode.ERASE, must be a child of the object you're wanting to erase.
Have a look on the following:http://www.piterwilson.com/personal/2008/05/07/bitmapdata-erasing-in-as3-with-custom-brush-shape/