Closed ghost closed 4 years ago
That is perhaps a misconception. Such an Ellipse either scales with the Map's ViewScale, or it has a fixed size in view coordinates, i.e. pixels.
thanks for the quick response. If you run the example WPF app with my changes, you should notice an inconsistency when zoomed out the ellipses created in the map:MapItemsControl
do not scale correctly (notice Red ellipses are much bigger than blue even though they were defined with much smaller Radius
properties):
The MapPath in your ControlTemplate doesn't have a Location property set. The Location is set on the templated parent element, i.e. the MapItem.
It doesn't work that way - without a Location, a MapPath can't scale the Geometry in its Data property.
You should be able to do something like
<Canvas>
<Canvas.Resources>
<EllipseGeometry RadiusX="100" RadiusY="100" x:Shared="False" x:Key="Data"/>
</Canvas.Resources>
<map:MapPath Fill="Red" Opacity="0.7" Data="{StaticResource Data}" Location="{Binding Location}"/>
</Canvas>
That works, and drawing a theoretical ellipse is much more efficient than my work around of drawing a MapPolygon
of hundreds of NTS points, so thank you for clarifying this.
For anyone else stuck on how to implement drawing enumerable ellipses that scale with zoom level, here's my fully working Style
to use in the WPF Sample app:
<Style x:Key="EllipseItemStyle" TargetType="map:MapItem">
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="map:MapItem">
<Canvas>
<Canvas.Resources>
<EllipseGeometry
RadiusX="100"
RadiusY="100"
x:Shared="False"
x:Key="Data" />
</Canvas.Resources>
<map:MapPath
Fill="Red"
Opacity="0.7"
Data="{StaticResource Data}"
Location="{Binding Location}" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(Notice location must be bound twice, as without the Setter Property="map:MapPanel.Location"
nothing would display)
Hello, @ClemensFischer! Thank you for your great work!
I have the similar issue but difference is items disappear from map after zoom changed. I need to draw point on some location and add filled circle around it (I call it heat map). There are ~2000 points and I need to draw heat map circles to find clusters fast. The problems are:
System.InvalidOperationException: 'Cannot set a property on object 'System.Windows.Media.EllipseGeometry' because it is in a read-only state.'
on line 80 MapPath.cs when I use
<map:MapItemsControl ItemsSource="{Binding HeatMap}" ItemContainerStyle="{StaticResource HeatMapStyle}" />
<Style x:Key="HeatMapStyle" TargetType="map:MapItem">
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
<Setter Property="ToolTip" Value="{Binding Location}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="map:MapItem">
<Canvas>
<map:MapPath Location="{Binding Location}" Fill="Green" Opacity="0.2">
<map:MapPath.Data>
<EllipseGeometry RadiusX="100" RadiusY="100"/>
</map:MapPath.Data>
</map:MapPath>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What I need:
Thanks in advance!
You have not used an EllipseGeometry as shared resource. Take another look.
@ClemensFischer, If I use x:Shared="False"
my circles disappear after zoom changed. And I catch the error if I don't.
@YiehraiS You may perhaps do something like shown below. It uses the read-only ViewScale property of the MapBase class, which I have just added - check out the latest sources.
Be aware that this is a scaling factor from projected map coordinates - typically meters in a projected cartesian coordinate system - to view coordinates, i.e. device-independent pixels.
<map:MapItemsControl ItemsSource="{Binding HeatMap}">
<map:MapItemsControl.ItemContainerStyle>
<Style TargetType="map:MapItem">
<Setter Property="Location" Value="{Binding Location}"/>
</Style>
</map:MapItemsControl.ItemContainerStyle>
<map:MapItemsControl.ItemTemplate>
<DataTemplate>
<Path Fill="Green" Opacity="0.2">
<Path.Data>
<EllipseGeometry RadiusX="100" RadiusY="100"/>
</Path.Data>
<Path.RenderTransform>
<ScaleTransform
ScaleX="{Binding ViewScale, ElementName=map}"
ScaleY="{Binding ViewScale, ElementName=map}"/>
</Path.RenderTransform>
</Path>
</DataTemplate>
</map:MapItemsControl.ItemTemplate>
</map:MapItemsControl>
@YiehraiS For the original approach, I would suggest to change the Location Binding of the MapPath to this:
<map:MapPath Fill="Green" Opacity="0.2"
Data="{StaticResource Data}"
Location="{TemplateBinding Location}"/>
You can also use a Setter for a regular dependency property (instead of an attached property) in the ItemContainerStyle:
<Setter Property="Location" Value="{Binding Location}"/>
You may also drop the Canvas and move the EllipseGeometry to Style.Resources:
<Style TargetType="map:MapItem">
<Style.Resources>
<EllipseGeometry RadiusX="100" RadiusY="100" x:Shared="False" x:Key="Data" />
</Style.Resources>
<Setter Property="Location" Value="{Binding Location}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="map:MapItem">
<map:MapPath
Fill="Green" Opacity="0.2"
Data="{StaticResource Data}"
Location="{TemplateBinding Location}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
@YiehraiS With another recent source update, you can now also directly set the MapPath.Data property
<Style TargetType="map:MapItem">
<Setter Property="Location" Value="{Binding Location}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="map:MapItem">
<map:MapPath
Fill="Green" Opacity="0.2"
Location="{TemplateBinding Location}">
<map:MapPath.Data>
<EllipseGeometry RadiusX="100" RadiusY="100"/>
</map:MapPath.Data>
</map:MapPath>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
https://github.com/ClemensFischer/XAML-Map-Control/issues/66#issuecomment-1301085272
@ClemensFischer
In this case circles are not disappeared after zoom changed, but size of each is const despite zoom changing. And by the way it takes a lot of time to load when I use ScaleTransform
but it doesn't when I don't (just removed it).
Thank you!
https://github.com/ClemensFischer/XAML-Map-Control/issues/66#issuecomment-1301175669
This is not working. Circles get disappeared with zoom changes.
This option throws the exception
I will be based on this option when searching for the solution of scaling: https://github.com/ClemensFischer/XAML-Map-Control/issues/66#issuecomment-1301085272
Thanks for your help, @ClemensFischer! One more thing I need is to show scale bar (how much meters per 1 visible centimeter) for user. How could it be implemented?
@YiehraiS Forgot a commit or push last night. Will do later. For the scale bar, see the MapScale class.
@YiehraiS I've just pushed the recent code changes.
There is now a read-only MapTransform property in the MapItem class, which scales and rotates from map to view coordinates.
It may be used like this:
<ControlTemplate TargetType="map:MapItem">
<Path Fill="Green" Opacity="0.2"
RenderTransform="{Binding MapTransform, RelativeSource={RelativeSource TemplatedParent}}">
<Path.Data>
<EllipseGeometry RadiusX="100" RadiusY="100"/>
</Path.Data>
</Path>
</ControlTemplate>
Hi and thank you for this repo,
When zooming, ellipses defined in a
MapItemsControl
do not appear to scale with the zoom level. As you zoom out they get bigger instead of smaller. This is the opposite behavior of a statically defined ellipse, which correctly scales (gets smaller) as you zoom out:For instance, this works as described above (from your WPF sample app):
But this doesn't work; Extending your WPF Sample, I display an ellipse for each point location you've defined. They display perfectly fine, but as you zoom out they get bigger (whereas static ellipse stays a fixed size)
And then beside the other mapcontrols: