JavaFX: Navigating through a Canvas within a ScrollPane of equal dimensions - user-interface

I created a 10 000 x 10 000 pixel canvas, placed it inside a scroll pane with dimensions 300 x 300. This was implemented fine. The whole grid was drawn and I could scroll through it.
I'm tasked to instead create the same functionality, except with a 300 x 300 canvas instead. As speed is important in this program, I'm told this would work much faster.
My problem is that when I do this, I lose access to the scroll bars on the bottom and right of the scroll pane. How do I regain access to those scroll bars, to physically scroll?
The canvas is updating at 60 steps per second. What's being drawn is a square grid from the information in a 2D array.

Since the the viewport handling will be done by the drawing logic, it's rather easy to create a "ScrollPane" yourself using a GridPane:
public static ScrollBar createScrollBar(Orientation orientation, double fullSize, double canvasSize) {
ScrollBar sb = new ScrollBar();
sb.setOrientation(orientation);
sb.setMax(fullSize - canvasSize);
sb.setVisibleAmount(canvasSize);
return sb;
}
Canvas canvas = new Canvas();
canvas.setHeight(300);
canvas.setWidth(300);
ScrollBar vScroll = createScrollBar(Orientation.VERTICAL, 10000, 300);
ScrollBar hScroll = createScrollBar(Orientation.HORIZONTAL, 10000, 300);
GridPane scrollPane = new GridPane();
scrollPane.addColumn(0, canvas, hScroll);
scrollPane.add(vScroll, 1, 0);

Related

iText 7 - How to fill a canvas rectangle with a transparent color

In iText 7.1.9 I am taking a pdf created programmatically (not via iText) and need to apply a transparent rectangle along the left side and bottom to ensure the no content exists within a predefined clear zone (for print).
The below code places the yellow rectangles correctly but the desired result is the for the yellow fill to be semi-transparent or not 100% opaque so that visual inspection will show the content that that intersects with the rectangle instead of the rectangle clipping the content.
var page = pdf.GetPage(1);
PdfCanvas canvas = new PdfCanvas(page);
canvas.SaveState();
canvas.SetFillColor(iText.Kernel.Colors.ColorConstants.YELLOW);
var pageHeight = page.GetPageSize().GetHeight();
var pageWidth = page.GetPageSize().GetWidth();
// left side
canvas.Rectangle(0, 0, 15, pageHeight);
// bottom
canvas.Rectangle(0, 0, pageWidth, 15);
canvas.Fill();
canvas.RestoreState();
I attempted to use a TransparentColor but canvas.SetFillColor won't accept a TransparentColor, are there any other options?
When we speak about low-level content stream instructions, color itself and transparency levels are specified separately in PDF syntax. The TransparentColor class that you speak about was designed to simplify lives of users who are less familiar with nuances of PDF syntax, but it it a higher-level class that you can use e.g. in layout module, and in your case you operate with the document on quite low level.
Long story short, to set color transparency you only need one additional line next to setting the color itself:
canvas.SetExtGState(new PdfExtGState().SetFillOpacity(0.5f));
So the code becomes:
var page = pdf.GetPage(1);
PdfCanvas canvas = new PdfCanvas(page);
canvas.SaveState();
canvas.SetFillColor(iText.Kernel.Colors.ColorConstants.YELLOW);
canvas.SetExtGState(new PdfExtGState().SetFillOpacity(0.5f));
var pageHeight = page.GetPageSize().GetHeight();
var pageWidth = page.GetPageSize().GetWidth();
// left side
canvas.Rectangle(0, 0, 15, pageHeight);
// bottom
canvas.Rectangle(0, 0, pageWidth, 15);
canvas.Fill();
canvas.RestoreState();

Unity-3d-5 Scale images for 16:9 to other resolutions

So I created a snake game with a border created with 2d sprites. I have my game window set to 16:9, when in this resolution the images look fine. However, scaling to anything else begins to make the game look weird. I want the game window to be re-sizable. How can I make my sprites stretch and shrink based on the current resolution?
I have already tried creating a sprite that is 120 in Width and 1 in Height, then using the x,y,z scales to change the scale to 16. This produced a huge sprite.
I am experimenting with using a canvas scaler, but with no success.
My end goal isn't to have my game fit pre-defined resolutions like 16:9, but to scale according to the current window size. So that if they make the window extremely thin, the game will only make the top and bottom borders extremely thin, while still confing the game play into the borders.
Below I post the screenshots of how my sprites are setup. And how they are placed into the hierarchy.
Border sprite - this sprite's width is now 70 pixels, because this is how it was given to me.
Border in hierarchy, position, scale, and rotation are defaults. Then for example the BorderTop is moved 25 on the y axis to move it to the top of the screen.
Camera setup
Example resolutions and current output
16:9
5:4
Add a simple script to every border:
public class Border : MonoBehaviour {
enum BorderTypes
{
bottom, top, left, right
}
[SerializeField] float borderOffset = 0.1f;
[SerializeField] BorderTypes type = BorderTypes.top;
// Use this for initialization
void Start () {
switch (type)
{
case BorderTypes.bottom:
transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, borderOffset, 10));
break;
case BorderTypes.top:
transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1 - borderOffset, 10));
break;
case BorderTypes.left:
transform.position = Camera.main.ViewportToWorldPoint(new Vector3(borderOffset, 0.5f, 10));
break;
case BorderTypes.right:
transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1 - borderOffset, 0.5f, 10));
break;
default:
break;
}
}
}
You can use a simple way:
First, create a Canvas
in Canvas component in Inspector, set Render Mode to Screen Space - Camera and drag your main camera to Render Camera field.
Then, in Canvas Scaler component in Inspector window, set UI Scale Mode to Scale Width Screen Size and other settings like this image
Now drag your game objects to Canvas.
First, you should not change your sprites. You problem is a game viewport. You simply cannot have 16:9 fixed aspect ratio on every device in "full-screen". You have 2 options here:
Don't care about aspect ratio and adapt your gameplay, make your canvas scalermode to "scale with screen size" and reference resolution something like 1920x1080 or 1600:900 or 800:450. Your game logic must take into account that you may have different size of screens. You can experiment in editor by switching different aspect ratios in game view.
Maintain 16:9 and therefore calculate for where to add "bars" (sides or top and down), when the game is initialized.

Need to draw arrows and circles on canvas without clearing the whole canvas

I'm trying to draw arrows and circles on a canvas, currently the whole canvas is cleared on mousemove and mousedown or whenever the draw function is called, I am not able to draw multiple arrows and circles. Is there any other to accomplish this task?
heres a fiddle: http://jsfiddle.net/V7MRL/
Stack two canvases on top of each over, and draw the temporary arrows/circle on the one on top, and do the final draw on the canvas below.
This way you can clear the top canvas with no issue, and your draws 'accumulate' in the lower canvas.
http://jsfiddle.net/V7MRL/5/ (updated)
I changed your draw function so it takes a 'final' flag that states wether the draw is final.
For a final draw, lower canvas is used, for an temporary draw, upper canvas is cleared then used.
function draw(final) {
var ctx = final ? context : tempContext ;
if (final == false) ctx.clearRect(0, 0, canvas.width, canvas.height);
Edit : for the issue #markE mentionned, i just handled mouseout event to cancel the draw if one is ongoing :
function mouseOut(eve) {
if ( mouseIsDown ) {
mouseIsDown = 0;
cancelTempDraw();
}
}
with :
function cancelTempDraw() {
tempContext.clearRect(0, 0, canvas.width, canvas.height);
}
Rq that your undo logic is not working as of now. I changed it a bit so that in draw, if the draw is final, i save the final canvas prior to drawing the latest figure to quickly have a 1-step undo. i just created a third temp canvas to/from which you copy.
Rq also that you cannot store one canvas for each stroke, or the memory will soon explode. Store the figures + their coordinates in an array if you want a full undo... or just allow 1-step undo for now.
i updated the jsfiddle link.

Performance considerations using html elements on top of canvas

It is known that if you have html elements (for example a modal window with lists) on top of a flash element you have huge performance issues cause flash cause the browser to repaint the any html on top of it while the flash is animating. I wonder if the same happens if you have html elements on top of an animating canvas element.
I am asking this cause I am building a canvas game and I wonder if it is a good idea to make the GUI (menus, navigation buttons etc) using DOM and not drawing it on canvas.
I just tested using Chromium Version 28.0.1500.45 Mageia.Org 3 (205727) and the elements are NOT repainted while my canvas animates.
I tried this simple box animation with a DIV over it. After that, I profiled my application to see what was happening. I noticed only the canvas was being repainted.
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var GX = 0;
function animate() {
var canvas = document.getElementById('jaja');
var context = canvas.getContext('2d');
// update
GX += 10;
if (GX > 500) GX = 0;
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// draw stuff
context.beginPath();
context.rect(GX, 10, 100, 100);
context.fillStyle = '#8ED6FF';
context.fill();
context.lineWidth = 1;
context.strokeStyle = 'black';
context.stroke();
requestAnimFrame(function() {
animate();
});
} // request new frame
Following, I tried to make the DIV repaint by selecting the text. This time yes, the DIV repainted.
Here's a screenshot of the profile.
1: We can se the Paint (600x586) being called everytime I do my animation.
2: It called Paint for the DIV element ONLY when I selected the text.
I personally do not believe any other browser would have a different behavior than that.
Yes, putting other DOM elements on top of a canvas element will reduce its performance.
This is because the browser have to do extra clipping when updating canvas / painting.
The canvas need to update 60 times per second to output to screen. If something is on top it needs to be clipped just as many times. If the DOM element is repainted as well will be browser dependent but the performance of the canvas element itself is reduced.
Usually the DOM paints happens in a single thread (but is about to change for most major browsers) so if there is extra load on that thread it will affect everything else being drawn too.
And there is the single-threading of JavaScript which is necessary to use to update canvas. If canvas has reduced performance than the script executing its changes (as well as changes to the DOM) will get hit too.

Clearing the drawn SpriteFont in XNA 4.0

This code is used to basically display number of times the user touches the screen. But the problem is every time the Update method(XNA 4.0), the previous texture is Drawn upon , therefore the count cannot be read. How do i clear the SpriteFont texture each time when it is redrawn?.
//Code used to draw the Sprite Font.!
batch.DrawString(fontSegoe, "Touches "+count, new Vector2(100, 100), Color.Black, 0, Vector2.Zero, 1, SpriteEffects.None, 0f);
Make sure to clear the screen at the beginning of Draw()
GraphicsDevice.Clear(Color.Black); //Use any color of your choice

Resources