Get Click event on elements inside canvas - c#

I am working on unity project which has a 3D sphere (Rotatable and zoomable). Inside that sphere there are 121 Quads (Tiles). Sphere is visible like google earth and inside a Canvas. I want to get Click events on Quads so that I can know on which Quad user has clicked and app can perform action according to that.
Is there any way to do this? I have heard that Canvas is just like a Bitmap Image.

If you able to get particular Quard details, if (x,y) co-ordinate given then, you can archive it by attaching click event to canvas.
var elem = document.getElementById("myCanvas");
// Add event listener for click events.
elem.addEventListener('click', function (event) {
var x = event.pageX - elemLeft;
var y = event.pageY - elemTop;
// Collision detection between clicked offset and element.
quardElements.forEach(function (element) {
if (y > element.top && y < element.top + element.height
&& x > element.left && x < element.left + element.width) {
//do your stuff here
}
});
}, false);

Related

SkiaSharp Touch Bitmap Image

In the app I'm trying to develop a key part is getting the position of where the user has touched. First I thought of using a tap gesture recognizer but after a quick google search I learned that was useless (See here for an example).
Then I believe I discovered SkiaSharp and after learning how to use it, at least somewhat, I'm still not sure how I get the proper coordinates of a touch. Here are sections of the code in my project that are relevant to the problem.
Canvas Touch Function
private void canvasView_Touch(object sender, SKTouchEventArgs e)
{
// Only carry on with this function if the image is already on screen.
if(m_isImageDisplayed)
{
// Use switch to get what type of action occurred.
switch (e.ActionType)
{
case SKTouchAction.Pressed:
TouchImage(e.Location);
// Update simply tries to draw a small square using double for loops.
m_editedBm = Update(sender);
// Refresh screen.
(sender as SKCanvasView).InvalidateSurface();
break;
default:
break;
}
}
}
Touch Image
private void TouchImage(SKPoint point)
{
// Is the point in range of the canvas?
if(point.X >= m_x && point.X <= (m_editedCanvasSize.Width + m_x) &&
point.Y >= m_y && point.Y <= (m_editedCanvasSize.Height + m_y))
{
// Save the point for later and set the boolean to true so the algorithm can begin.
m_clickPoint = point;
m_updateAlgorithm = true;
}
}
Here I'm just seeing or TRYING to see if the point clicked was in range of the image and I made a different SkSize variable to help. Ignore the boolean, not that important.
Update function (function that attempts to draw ON the point pressed so it's the most important)
public SKBitmap Update(object sender)
{
// Create the default test color to replace current pixel colors in the bitmap.
SKColor color = new SKColor(255, 255, 255);
// Create a new surface with the current bitmap.
using (var surface = new SKCanvas(m_editedBm))
{
/* According to this: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/paths/finger-paint ,
the points I have to start are in Xamarin forms coordinates, but I need to translate them to SkiaSharp coordinates which are in
pixels. */
Point pt = new Point((double)m_touchPoint.X, (double)m_touchPoint.Y);
SKPoint newPoint = ConvertToPixel(pt);
// Loop over the touch point start, then go to a certain value (like x + 100) just to get a "block" that's been altered for pixels.
for (int x = (int)newPoint.X; x < (int)newPoint.X + 200.0f; ++x)
{
for (int y = (int)newPoint.Y; y < (int)newPoint.Y + 200.0f; ++y)
{
// According to the x and y, change the color.
m_editedBm.SetPixel(x, y, color);
}
}
return m_editedBm;
}
}
Here I'm THINKING that it'll start, you know, at the coordinate I pressed (and these coordinates have been confirmed to be within the range of the image thanks to the function "TouchImage". And when it does get the correct coordinates (or at least it SHOULD of done that) the square will be drawn one "line" at a time. I have a game programming background so this kind of sounds simple but I can't believe I didn't get this right the first time.
Also I have another function, it MIGHT prove worthwhile because the original image is rotated and then put on screen. Why? Well by default the image, after taking the picture, and then displayed, is rotated to the left. I had no idea why but I corrected it with the following function:
// Just rotate the image because for some reason it's titled 90 degrees to the left.
public static SKBitmap Rotate()
{
using (var bitmap = m_bm)
{
// The new ones width IS the old ones height.
var rotated = new SKBitmap(bitmap.Height, bitmap.Width);
using (var surface = new SKCanvas(rotated))
{
surface.Translate(rotated.Width, 0.0f);
surface.RotateDegrees(90);
surface.DrawBitmap(bitmap, 0, 0);
}
return rotated;
}
}
I'll keep reading and looking up stuff on what I'm doing wrong, but if any help is given I'm grateful.

How to solve what y axis segment was clicked in LightningChart

I've started using LightningChart in my real time monitoring application. In my app there are many y axis which use segmented layout (one y axis per segment):
mainChart.ViewXY.AxisLayout.YAxesLayout = YAxesLayout.Segmented;
My goal is that when you mouse click a segment, it gets larger compared to other segments (kinda like zoom effect) and the other segments gets smaller. When you click it again it goes back to normal.
I know I can change the size of the segments with:
mainChart.ViewXY.AxisLayout.Segments[segmentNumber].Height = someValue;
That takes care of the zooming effect.
Now the problem is that how can I solve which segment was actually clicked? I figured out that you get mouse position via MouseClick -event (e.MousePos) but that seem to give only the screen coordinates so i'm not sure that it helps.
I'm using the LightningChart version 8.4.2
You are correct that getting mouse position via MouseClick event is the key here. The screen coordinates you get via e.GetPosition (not e.MousePos) can be converted to chart axis values with CoordToValue() -method. Then you just compare the y-coordinate to each y-axis minimum/maximum value to find out what segment was clicked. Here is an example:
_chart.MouseClick += _chart_MouseClick;
private void _chart_MouseClick(object sender, MouseButtonEventArgs e)
{
var mousePos = e.GetPosition(_chart).Y;
double axisPos = 0;
bool isWithinYRange = false;
foreach (AxisY ay in _chart.ViewXY.YAxes)
{
ay.CoordToValue((float)mousePos, out axisPos, true);
if (axisPos >= ay.Minimum && axisPos <= ay.Maximum)
{
// Segment clicked, get the index via ay.SegmentIndex;
isWithinYRange = true;
}
}
if (!isWithinYRange)
{
// Not in any segment
}
}
After finding out the segment index, you can modify its height as you described:
_chart.ViewXY.AxisLayout.Segments[0].Height = 1.5;
Note Height means segment height compared to other segments.
Hope this is helpful.

Animation move left and right

I am making a windows form animation where a animation of a character is walking left and then walk right once he reached the end of the windows form.
and i have to put a play/pause button for the animation to stop and continue where he left off
I have 16 frames each of the character walking right and left
I would like to ask how to put a boundary on the picturebox and how to get the picturebox to change to the walking right animation once it reach the left edge of the windows form and change the walking left animation once it reach the right edge of the windows form
public partial class Form1 : Form
{
//Declare a new integer for frame and set it to 1
int frame = 1;
public Form1()
{
InitializeComponent();
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
//Increase the frame per tick
frame++;
//Loop : If the frame exceeds 16, set the frame back to 1
if (frame > 16)
{
frame = 1;
}
//REtrieve the image fromfile base on the value of the ineger "frame"
pictureBox1.Image = Image.FromFile(Application.StartupPath +
"\\left" + frame + ".png");
int x = pictureBox1.Location.X;
int y = pictureBox1.Location.Y;
x -= 5;
//else if (e.KeyCode == Keys.Left) x -= 1;
pictureBox1.Location = new Point(x, y);
}
PictureBox has a border property. Check if it works for you.
You can check if PictureBox Left matches Forms Left that would mean it needs to move right and change the image on this condition.
You will need 2 different images 1 directed to left and 1 directed to right...
create an extra variable stating direction
then you can turn the image direction if the folowing criteria is met
if direction = right and picture.location >= (how far you want it to go probably border)
thendirection = leftchange to the left directed image change your movement variable to negative
if direction = left and picture.location <= 0
then direction = rightchange to the rightdirected image change your movement variable to positive
To detect when the control has reached the boundaries, you may check if the Location.X property + Width is equal to or greater than the PictureBox container (in this case, Form)'s width.
if(pictureBox1.Location.X + pictureBox1.Width >= pictureBox1.parent.Width)
{
direction = "left";//reached the end so go left
Of course you can easily test if we're at the starting position by checking if pictureBox1.Location.X == 0

game works perfectly in standard screensize but not in fullscreen

So a friend and I are making a horizontal scroller game. There are mice hidden throughout the screen and because it's a horizontal scroller game you can also scroll to the left and right and see more mice.
We originally made this game in de default xna screensize (800 x 480). We're now at a point where we want our game to be fullscreen. Our point of the game is to click on the mice and get a higher score, etc...
Now before we made our game fullscreen we could click on the mice and our score would add up. After we've made it fullscreen we can't click on the mice anymore. Well, we can still click on them, but instead of adding points to our score nothing happens.
We're using bounding boxes on the mice, and whenever the X & Y position of our computermouse is withing one of those boundingboxes and you will click with your computermouse at the moment that your computermouse is inside a mouse boundingbox then you're supposed to get points adding up to your score. This is the code for the boundingbox on every mouse.
public Rectangle getBoundingBox()
{
return new Rectangle(
(int)_position.X,
(int)_position.Y,
_texture.Width,
_texture.Height
);
}
We gave all our mice a position by the next code:
_position = _scrollerBackground.GetPosition() + _offsetFromBackground;
The next piece of code is how we get the position of our mouse and what it should do when the position of the mouse is within one of our mice(_number0). When the mouseposition is within the boundingbox from the mouse and when the computermouse clicks at that moment then input = 0;
public void UpdateMouse()
{
mouse = Mouse.GetState();
mousePosition.X = mouse.X;
mousePosition.Y = mouse.Y;
}
public void OnMouseOver()
{
if (_number0.getBoundingBox().Contains(mousePosition))
{
if (mouse.LeftButton == ButtonState.Pressed && oldMouseState.LeftButton == ButtonState.Released)
{
input += "0";
}
}
This is how it worked before we made our game fullscreen, but now that doesn't work anymore. This is the code we used to make our game fullscreen:
graphics.IsFullScreen = true;
Does anyone have any similar experiences or maybe knows how to fix this?

Moving a Control horizontally

I have a list of buttons wrapped inside a stackpanel which stacks them horizontly. I want to know the code behind in C# to apply an animation such that if my mouse is near the left end of the MainWindow, the buttons slowly moves right. Whereas if my mouse is near the right side of the MainWindow, the buttons slowly moves left.
The buttons are added and styled at runtime.
If it is possible for you to use a canvas instead of the stackpanel you can use this code to achieve the animation I wrote for you right away:
Declare a field in you class like the following: private bool _running = true;
After this you can use this to animate your buttons.
new Thread(() =>
{
while (_running)
{
Thread.Sleep(20);
canvas.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
var position = Mouse.GetPosition(canvas).X;
var canvasWidth = canvas.ActualWidth;
if (position >=0 && position < 10.0d)
btn.SetValue(Canvas.LeftProperty, (double)btn.GetValue(Canvas.LeftProperty) + 1);
if (position <= canvasWidth && position > canvasWidth - 10.0d)
btn.SetValue(Canvas.LeftProperty, (double)btn.GetValue(Canvas.LeftProperty) - 1);
}));
}
}).Start();
Dont forget to add following usages to your class:
using System.Threading;
using System.Windows.Threading;
If you want the code to work with more than just one buttons just use a list for example and rewrite the code a little bit. Also adjust Thread.Sleep(20) to your needs.
Good luck.

Categories