Leaflet: How to control opacity of Layer Groups? - maps

Does some expert know how to change the opacity of each tilemap of a Layer Group by using a HTML-slider input?
For example: I've got several tilemaps, which could be switched by using Lealet's Layercontrol button, like here: Leaflet Layer Groups.
When using the opacity-slider I want to dim each tilemap, not just one being actually active. For example: I'm dimming map1 to 0.5
Then switching to map2, its opacity should already also be 0.5. And when changing the opacity of map2 to 0.8 with the slider and switching back to map1, map1 should already have opacity 0.8 again (not the former adjusted value of 0.5)
I know how to implement the slider control and how to change the opacity of a single tilemap by using the command
nameOfMaplayer.setOpacity(opacityValue);
But I don't have an idea how to reference using Leaflet's methods to the Pane/Grid Layer/array of all tilemaps to change the map's pane opacity instead of the opacity of each indivdual tilemaps simultaniously.

I think in the end I found a satisfying answer myself:
If we want to change the opacity of the tilePane (= basemap-layers AND overlaymap-layers):
map.getPane('tilePane').style.opacity = 0.5;
But this has the disadvantage that also the Overlay-tilemaps get dimmed which I wanted to avoid.
My prefered method is to change just the opacity of the active basemap-layer. Since Leaflet doesn't support getting the active basemap Layer, you'll have to use the "Activelayers"-Plugin and use its methods:
ctrLayer = L.control.activeLayers(baseMaps, overlayMaps, {position: 'topright'}).addTo(map);
.....
tilemapLayer = ctrLayer.getActiveBaseLayer().layer;
tilemapLayer.setOpacity(actualOpacityValue);
Each time you change the basemap, you have to run the later 2 commands to change the new basemap's oppacity to the actual used opacity value.

Related

How to detect background color in React

Is there a way to detect the background color at one certain point of the page dynamically? I have a website with a fixed header, and the default logo on it is white (default background is black). However, as I scroll down there are sections that have white background, so the logo would have to change colour to black.
Setting it based on scrolling position is not possible, because all sections have different heights and the height is often dependent on the content.
I have found mix-blend-color, but unfortunately its support is pretty bad across browsers. Also tried numerous npm packages, but none of them seem to pick up the background colour.
Is there another way to dynamically change the logo color without getting the background color?
Answer 1
I never tried this, but I think this might lead to the answer.
You can use document.elementFromPoint.
This will retrieve the top element at some (x, y) point.
So you can set the x and y to 1px down the border of your modal ( or some place where you know that will only have element with the background color you want) and get the element.
And check, on a scroll event listener, what is the element at that position and get it's background color.
Is this a good thing to do? Maybe not, but it works and it have good support across browsers.
Answer 2
Setting it based on scrolling position is not possible
Of course it's possible!
If your modal is with position absolute, what you can do is get the modal's ref and use element.getBoundingClientRect() to get it's position.
Then on each section, you also get the ref (you will have an array of section's ref) in the parent component, which knows the modal's refs and section's ref.
Then, on a scroll event, you use getBoundingClientRect on each section element and check if it's inside the modal logo.
To check if it's inside, you can simply use the top and bottom ( if the scroll is vertical).
This is harder to implement, but I think it's the way to go.

Retrieve the Default Selection Opacity

Text selection in WPF (text boxes etc.) looks different from that of other UI toolkits, as WPF uses a semi-transparent overlay over the text for its selection rectangle.
The SystemColors class provides the color used for that rectangle in the HighlightColor property (and the other properties related to it). However, that color is fully opaque. Hence, the color has to be used as a reduced opacity.
Documentation pages on TextBoxBase.SelectionOpacity, PasswordBox.SelectionOpacity and on FlowDocumentPageViewer.SelectionOpacity suggest:
The default is 0.4.
On the other hand, this blogpost says:
SelectionOpacity (...) defaults to a value of .6.
Whatever that default value is, is there any way to retrieve the selection opacity to be used with SystemColors.HighlightColor from the environment, rather than hardcoding an arbitrary value (which may not even be the best choice for non-standard highlight colors)?
No, and yes.. There is no SystemColors.HighlightOpacity - but there should be.
The SelectionOpacity default property value is hardcoded to 0.4 in WPF: http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/Primitives/TextBoxBase.cs,9716201433499854
I don't exactly know how this can differ(0.6 as you said), it seems to be hardcoded as 0.4 in every .NET that supports it(4.0, 4.5).
If you want to actually query the default value of SelectionOpacityProperty, you can do so:
var prop = TextBoxBase.SelectionOpacityProperty;
var defValue = (double) prop.DefaultMetadata.DefaultValue; // 0.4

WP7 Game - rotate only some controls when orientation changed

I'm making a simple WP7 game and I have a little problem with orientation changing. My gameboard looks like this:
And I need to rotate only the numbers when orientation changed. Is there any easy way to do it? The numbers are TextBlocks and lines are rectangles. Gameboard is Canvas (but I can use Grid as well).
Or i could exclude the canvas from automatic rotating and only redraw the numbers. But I don't know how to do it either.
Using PlaneProjection should be fine:
<TextBlock.Projection>
<PlaneProjection RotationZ="90"/>
</TextBlock.Projection>
Obviously this would apply the projection immediately, so you would need to create it in code (or try using 0 for the Z value and then changing that in code (possibility of this is a long shot)) based on the data provided (and within) the OrienationChanged event handler, such as:
myTextBlock.Projection = new PlaneProjection { RotationZ = 90 };

Morphing from an image to a shape in Silverlight 3

I have a requirement to morph from an image (png) to a shape (polygon) in Silverlight 3 as an effect, but of course there is no built in transition or method to do this.
At the moment the best I have is fade one out and the other in, but can anyone suggest a decent alternative that may work or look better?
Regards
Moo
In Blend:
Create a rectangle. Set stroke to No Brush and Fill to Tile Brush.
For the ImageBrush of the Tile Brush, select your image.
In the object browser, select the rectangle, right click > Path > Convert to Path.
Use the pen tool to add some points to the path.
Add a storyboard.
Add a keyframe at 1 second. Blend will go into record mode
Use the direct selection tool to move the points into the polygon shape you want. Test out your animation.
At this point, the image morphs into a shape, but the image is still there. If you need to remove the image as well as morph it:
In your storyboard, at the keyframe at 1 second, change the opacity to 0.
Create a copy of the rectangle, but make sure fill is set to No Brush and Stroke is set to a color and width. Set the opacity to 0.
Add points, and mimic the animation you just set up for the image's rectangle.
Add a keyframe at 1 second for this element. In record mode, change the opacity to 100%.
The end result will be both paths morphing, the one with the image fading out while the one with no fill fading in.
I'm not a silverlight programmer, and don't know the details of what you want to do, so this is just a shot in the dark, but... if the shape you want the image to morph to is always going to have the same initial visual appearance (or some limited set of appearances) you might try morphing from the original image to an image of that shape, and then swapping the image that's the morph target for the geometry once you're done the morph. Course whether that would work or not is very dependent on the details of what you're doing. Sorry if you've already considered that and ruled it out.
You could possibly morph the image brush to the path of the shape by using an appropriate projection matrix. Or render a shape using the image brush and then morph that shape to the target shape, i.e. go from a rectangle to the target shape but using the image brush as the shape background. You may need to still warp the image brush somehow though.
An example of rendering a warped image is here in Charles Petzold's blog.

Use another control as an opacity mask in WPF?

I'm trying to use the OpacityMask property combined with a VisualBrush so that when you drag an image over another control (such as another image, rectangle, or any other control), the part of the image that is over the second control has a different opacity. That is, the image has some non-zero base opacity, and any part of the image that is over another control has a different (again, non-zero) opacity.
Is this possible simply using VisualBrush and OpacityMask? Or is a more complex approach required?
Thanks!
Edit: I'm trying to make the image have some lower opacity (such as 0.5), and the part being dragged over the control have a higher opacity (such as 1.0). I originally left out this detail, which is important to the approach taken.
In addition to ima's answer, I have figured this out using an opacity mask. I use the following code hooked into the LayoutUpdated event for the image.
// Make a visual brush out of the masking control.
VisualBrush brush = new VisualBrush(maskingControl);
// Set desired opacity.
brush.Opacity = 1.0;
// Get the offset between the two controls.
Point offset = controlBeingMasked.TranslatePoint(new Point(0, 0), maskingControl);
// Determine the difference in scaling.
Point scale = new Point(maskingControl.ActualWidth / controlBeingMasked.ActualWidth,
maskingControl.ActualHeight / controlBeingMasked.ActualHeight);
TransformGroup group = new TransformGroup();
// Set the scale of the mask.
group.Children.Add(new ScaleTransform(scale.X, scale.Y, 0, 0));
// Translate the mask so that it always stays in place.
group.Children.Add(new TranslateTransform(-offset.X, -offset.Y));
// Rotate it by the reverse of the control, to keep it oriented correctly.
// (I am using a ScatterViewItem, which exposes an ActualOrientation property)
group.Children.Add(new RotateTransform(-controlBeingMasked.ActualOrientation, 0, 0));
brush.Transform = group;
controlBeingMasked.OpacityMask = brush;
If you want a desired base opacity, use two images; one that's always at the base opacity, and another that uses the opacity mask that sits on top of it. If you want the base opacity to be higher than the masked opacity, then it might be easier to use ima's approach.
One advantage of this solution as opposed to the maskless approach is that if the masking control moves, changes size, etc., this will automatically pick up the change without having to keep another control in sync with it.
Here's how it looks:
(source: yfrog.com)
No masks
Define visual brush for the control
Paint shape right on top of the control with that brush
Drag image between the shape and the control
Set opacity of the brush to achieve desired effect

Resources