I have InkCanvas inside a zoomable ScrollViewer:
<ScrollViewer x:Name="ScrollViewer" ZoomMode="Enabled">
<Border Height="5000" Width="5000" BorderBrush="Black" BorderThickness="1">
<InkCanvas x:Name="inkCanvas" />
</Border>
</ScrollViewer>
I want to position ruler to the top left corner.
Ruler is positioned on the InkCanvas and state of ScrollViewer is defined by by HorizontalOffset, VerticalOffset and ZoomFactor
I've found this code (sample)
void OnBringIntoView(e)
{
// Set Ruler Origin to Scrollviewer Viewport origin.
// The purpose of this behavior is to allow the user to "grab" the
// ruler and bring it into view no matter where the scrollviewer viewport
// happens to be. Note that this is accomplished by a simple translation
// that adjusts to the zoom factor. The additional ZoomFactor term is to
// make ensure the scale of the InkPresenterRuler is invariant to Zoom.
Matrix3x2 viewportTransform =
Matrix3x2.CreateScale(ScrollViewer.ZoomFactor) *
Matrix3x2.CreateTranslation(
ScrollViewer.HorizontalOffset,
ScrollViewer.VerticalOffset) *
Matrix3x2.CreateScale(1.0f / ScrollViewer.ZoomFactor);
ruler.Transform = viewportTransform;
}
in short:
viewport = Scale(zoom) * Translate(offset) * Scale(1/zoom)
This works, but I'm a bit lost.
What does the first scale do and what does the second? Why can't I use juct TranslateTransform?
Why can't I use juct TranslateTransform?
Because the InkPresenterRuler.Transform property is designed to be Matrix3x2.
What does the first scale do and what does the second?
Scale(zoom)*Scale(1/zoom) aiming at letting the ruler be invariant to Zoom. No matter what your current zoom level is, the ruler will return to it's original size.
Translate(offset) changes the translation values(offsetX and offsetY) of the transform Matrix.
For details of the transformation theory you can refer to:
Remarks of Matrix Transform
Affine transformations section of Transformation matrix Wiki.
Related
The sample I am talkin' about is here
https://recharts.org/en-US/examples/HighlightAndZoomLineChart
and here
https://codesandbox.io/s/highlight-zomm-line-chart-v77bt
Please press left button of the mouse and drag it to the right - this is how zoom is currently done. Please take a look at the activeLabel variable.
Currently recharts could make a zoom into the graph by passing the x coordinate (which is stored in activeLabel variable) and zooom looks like a pillar all over the y coordinate.
I want to select an area - square or rectangle to make more customized zoom. The trouble is that I can't get the y value of the graph (not pixel in window). Recharts gives only x coordinate of the graph, but not y.
I've searched all over the issues on gitHub, mailed the creator with no luck.
I've read the
Recharts value at pointer to show in tooltip?
but I could not get how could I count the initial values of chartX and chartY in my responsive container, so it is very depends on the window user has.
Please help me to find a solution to match chartY in pixels to my real values in my chart depending on Responsive Container I am using.
Zoom can be done by using the mouse events of the chart.
You can store the values in a state then call the zoom function on onMouseUp.
And in zoom function, you can set the domains of the axes.
Don't forget to set the axes to allowDataOverflow.
And you can also draw the rectangle by using ReferenceArea
function zoom () {
setXAxisBoundaries([rectangle[0], rectangle[1]])
setYAxisBoundaries([rectangle[2], rectangle[3]])
}
<ScatterChart
onMouseDown={(event) => setRectangle([event.xValue, event.yValue])}
onMouseMove={(event) => setRectangle(rectangle => [...rectangle, event.xValue, event.yValue]))}
onMouseUp={zoom}>
<XAxis
dataKey="x"
allowDataOverflow
domain={xAxisBoundaries}
type="number" />
<YAxis
dataKey="y"
allowDataOverflow
domain={yAxisBoundaries}
type="number" />
I'm adding a drop shadow to a Xamarin.UWP project (but the question is not really Xamarin-specific but UWP in general):
bool IsShadowSupported => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3); // SDK >= 14393
if (IsShadowSupported) {
var compositor = ElementCompositionPreview.GetElementVisual(Control).Compositor;
dropShadow = compositor.CreateDropShadow();
if (Control is Windows.UI.Xaml.Controls.TextBlock textBlock)
dropShadow.Mask = textBlock.GetAlphaMask();
shadowVisual = compositor.CreateSpriteVisual();
shadowVisual.Shadow = dropShadow;
ElementCompositionPreview.SetElementChildVisual(Control, shadowVisual);
...
dropShadow.Offset = new Vector3((float)Shadow.GetDistanceX(Element), (float)Shadow.GetDistanceY(Element), -5f);
}
It runs and the shadow appears—but above the text, not beneath it. At first I thought this would be determined by the Z coordinate of the offset, but no negative, positive or zero value there changes anything. The shadow looks like this:
Which is not a bad effect on its own but it's not what was requested: white text and a dark grey shadow beneath it.
The problem is that the SetElementChildVisual sets the visual as the last child of the given element, which will make the shadow appear above the TextBlock. Unfortunately not even the parent of the TextBlock is enough, you should instead have a adjacent element that will host the shadow:
<Grid x:Name="ShadowHost" />
<TextBlock x:Name="Hello" Text="Hello" />
Now use ShadowHost instead of Control in your code except for the GetAlphaMask call where you should use the TextBlock instead.
Of course this is quite some work to make shadows work, which is why you can try to use the Windows Community Toolkit's DropShadowPanel instead - see documentation for more info.
I need to get width/height of displayed image in imegView and compare it to orginal image size which is in imageView.getImage().getWidth()/getHeight() and listen changes if user resize it form application GUI.
I get this size from imageView.fitWidthProperty() and similar for height, but I get size of imageView not image within it:
I get size of blue which is imageView but I need size of displayed image (green). How can I get it as property to listen when user resize window app (green also change size but it seems to have max and min size so it stop resize with imageView when it is max or min).
I use this property to compute % of size of orginal image in bottom right below blue rectangle.
Is it possible?
E: Below is fxml of this tab:
<BorderPane fx:id="root" fx:controller="..."
xmlns:fx="..." xmlns="..." stylesheets="#...css">
<center>
<StackPane>
<ImageView fx:id="..."/>
<fx:include source="...fxml" fx:id="..."/>
</StackPane>
</center>
<bottom>
<VBox fx:id="..." minHeight="110" styleClass="small-padding" spacing="5">
<HBox alignment="CENTER_RIGHT" spacing="5">
<fx:include source="...fxml" resources="..."
fx:id="..."/>
</HBox>
<TextArea fx:id="..." promptText="%..." styleClass="-fx-description-text-area"/>
</VBox>
</bottom>
When the ImageView is set to preserve the aspect ratio, one has to calculate the real dimensions by hand. At least I've not found another way.
double aspectRatio = image.getWidth() / image.getHeight();
double realWidth = Math.min(imageView.getFitWidth(), imageView.getFitHeight() * aspectRatio);
double realHeight = Math.min(imageView.getFitHeight(), imageView.getFitWidth() / aspectRatio);
To explain this a bit: getFitHeight/Width is your blue rectangle. When preserving the aspect ratio of the source image, at least one side of the blue rectangle must have the same length as the corresponding side of the green rectangle. Also, the green rectangle will always be inside of the blue one, hence the call to Math.min().
~>1)
The fact that the Image is not resizing to cover all the ImageView has to do with preserveRatio method.If you want to be covered setPreserveRatio(false);
with a combination of setSmooth( true );
~>2)
The green border is the size of the original image.
~>3)
Before adding the Image to the ImageView you can do:
Image image = new Image("FILE:...");
image.getWidth( );
image.getHeight( );
And that is the original size of the image.
As for the size of the image when it is displayed inside the ImageView:
imageView.getFitWidth();
imageView.getFitHeight();
For the size of ImageView inside the Scene (the blue border in your question):
imageView.getWidth();
imageView.getHeight();
ImageView class has properties for the above.
I am not aware of any property that you could use directly to get at the numbers you want but you might propose this as an improvement for a future version of JavaFX.
What you can do now is write some code which tracks all proerties of the ImageView which have an influence on the size of the displayed image and then compute the displayed size yourself. This does not sound too complicated to me.
From this post i came to know that there exist some platform improvements for
implementing pinch and zoom functionality. By using this new method(ManipulationDeltaEventArgs.PinchManipulation) how i can implement pinch to zoom functionality in windows phone.
Apart from this i need to implement scrolling feature too to the image control. In my current implementation, i am using Toolkit(gesture listener) for pinch and zoom functionality along with scroll viewer, now it seem both scrolling and and pinching events are overlapping and hence it produces a bad user experience.
Can anyone help me to solve this issue in my application. I am looking some code samples that help me to achieve the functionality.
I am not expected to get Multi touch behavior(codeplex) as answer. The assemblies using in the project are quite old and i heard that many of them are facing issues with marketplace submission only because of this.
As I said in my previous answer if you're building a WP8 exclusive app you can use the new ManipulationDeltaEventArgs.PinchManipulation for pinch & zoom effects. Here's a basic example of how to use ManipulationDeltaEventArgs.PinchManipulation data to scale, move and rotate an image.
First, we'll create a basic image hovering in the middle of a grid:
<Grid x:Name="ContentPanel">
<Image Source="Assets\Headset.png"
Width="200" Height="150"
ManipulationDelta="Image_ManipulationDelta"
x:Name="img"
>
<Image.RenderTransform>
<CompositeTransform CenterX="100" CenterY="75" />
</Image.RenderTransform>
</Image>
</Grid>
Next, we'll handle the ManipulationDelta event, check if it's a Pinch Manipulation and apply the correct Silverlight transformations on our UIElement.
private void Image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
if (e.PinchManipulation != null)
{
var transform = (CompositeTransform)img.RenderTransform;
// Scale Manipulation
transform.ScaleX = e.PinchManipulation.CumulativeScale;
transform.ScaleY = e.PinchManipulation.CumulativeScale;
// Translate manipulation
var originalCenter = e.PinchManipulation.Original.Center;
var newCenter = e.PinchManipulation.Current.Center;
transform.TranslateX = newCenter.X - originalCenter.X;
transform.TranslateY = newCenter.Y - originalCenter.Y;
// Rotation manipulation
transform.Rotation = angleBetween2Lines(
e.PinchManipulation.Current,
e.PinchManipulation.Original);
// end
e.Handled = true;
}
}
// copied from http://www.developer.nokia.com/Community/Wiki/Real-time_rotation_of_the_Windows_Phone_8_Map_Control
public static double angleBetween2Lines(PinchContactPoints line1, PinchContactPoints line2)
{
if (line1 != null && line2 != null)
{
double angle1 = Math.Atan2(line1.PrimaryContact.Y - line1.SecondaryContact.Y,
line1.PrimaryContact.X - line1.SecondaryContact.X);
double angle2 = Math.Atan2(line2.PrimaryContact.Y - line2.SecondaryContact.Y,
line2.PrimaryContact.X - line2.SecondaryContact.X);
return (angle1 - angle2) * 180 / Math.PI;
}
else { return 0.0; }
}
Here's what we did:
Scaling: PinchManipulation actually tracks scaling for us, so all we had to do is apply PinchManipulation.CumulativeScale to the scaling factor.
Transform: PinchManipulation tracks the original center and the new center (calculated between the two touch points). By subtracting the new center from the old center we can tell how much the UIElement needs to move and apply that to a translate transform. Note that a better solution here would also account for multiple Manipulation sessions by tracking cumulative original centers which this code doesn't.
Rotation: We figured out the angle between the two touch points and applied it as the rotation transform. More on that in this Nokia wiki article # Real-time rotation of the Windows Phone 8 Map Control
Here's a few print screens showing this code runs just fine:
I found the perfect soultion for smooth pinch to zoom and pan. It is actually a Microsoft Code sample at the following link
http://code.msdn.microsoft.com/wpapps/Image-Recipes-0c0b8fee
I just used it as boiler plate code and it worked wonders.
Cheers
If you're looking to roll your own, you might want to check out this article about pinch zooming in Silverlight: Implementing pinch zoom correctly in Silverlight
Telerik also has an out of the box pan and zoom image control, but it does cost money: Telerik Pan and Zoom Control
There are a few rectangles inside a canvas. How can I get the coordinates of the rectangles wrt canvas using the Name of rectangles in C# ?
You can do this using TransformToVisual. There's a good example here: Visual.TransformToVisual MSDN
From the page for Posterity:
<StackPanel Name="myStackPanel" Margin="8">
<TextBlock Name="myTextBlock" Margin="4" Text="Hello, world" />
</StackPanel>
// Return the general transform for the specified visual object.
GeneralTransform generalTransform1 = myStackPanel.TransformToVisual(myTextBlock);
// Retrieve the point value relative to the child.
Point currentPoint = generalTransform1.Transform(new Point(0, 0));