dynamic icon/symbol coloring with mapbox - mapbox-gl-js

I am working with mapbox gl js for the first time. I need to be able to define a 'template' icon/symbol (lets say a triangle that is approx 16X16) and then use that icon/symbol on a layer but be able to use the icon-color property in the 'paint' section to be able to set the color for the icon/symbol in the style.
I have created a triangle svg file. I then used a cli utility to convert that svg to an sdf (I named it triangle16_sdf.png) and uploaded it to my aws public bucket. The sdf is monochromatic. I am trying to use that in a style as defined int the below style snippet:
{"type":"symbol","icons":{"triangle-16":"https://my_aws_url/icons/triangle16_sdf.png"},"paint":{"icon-color":"#00ff00"},"layout":{"symbol-placement":"point","icon-image":"triangle-16","icon-ignore-placement":true,"icon-allow-overlap":true}}
This shows the icon but only the template. It does not color the icon with the appropriate color.
Is there something I am doing incorrectly here or is there another approach where I can have a single icon/symbol that I can color differently with a style?

I'm not sure you can use the style to tell mapbox-gl that an icon should be considered an "sdf" icon. But with the addImage method you are able to do this:
const image = new Image();
image.onload = () => {
map.addImage('icon-name', image, {sdf: true});
};
image.src = 'your-image-url';

Related

Material-UI Sizing Confusion

In the sizing documentation, it says "Easily make an element as wide or as tall (relative to its parent) with the width and height utilities.".
What I realize is that almost all the examples in system section of documentation, examples mostly related to Box component. I tried some of the tricks from there on Button element. And expectedly nothing changed.
Well for those who is new on material (actually UI) this is a bit tricky. first, they use Box because as per box documentation they said box generated using material styled (not the styled-components) "The Box component packages all the style functions that are exposed in #material-ui/system. It's created using the styled() function of #material-ui/core/styles."
So, I went to the github and material core repository to understand how to do that.
export const styleFunction = css(
compose(
borders,
display,
flexbox,
grid,
positions,
palette,
shadows,
sizing,
spacing,
typography,
),
);
css and compose are also exported from #material-ui/system
then at the end of the file;
const Box = styled(BoxRoot, { shouldForwardProp }, { muiName: 'MuiBox' })(styleFunction);
export default Box;
The styled used here is from an experimentalStyled package (an internal package) but that does not matter. Cuz, Material guys exporting a styled function/hook for our use.
import { styled } from "#material-ui/core/styles";
I tried this styled function for Button component.
const CustomButton = styled(Button)(sizing);
adn yes it worked. I am now able to apply magical styling skills defined in the system section of material UI.
For those who wants to use this instead of other methods. I pushed an npm package too.
material-ui-styled-hook

Mapbox GL JS Set Paint property on specific Feature in Layer

I am using Mapbox Studio as basis for mapping and styling and then using HTML for additional map features.
One of the features is to change Icon opacity when hovering or mouse enter. I've checked other examples and all other refer to feature when you create it directly in HTML. I managed to change opacity but only for whole layer.
Can I use somehow e.features[0] command line to apply changes only to one feature rather than to whole layer?
I used this code which changer opacity for whole Layer 'Icon' (Layer contains 5 icons with text):
// Change the cursor to a default and change opacity when the it enters a feature in the 'Icons' layer.
map.on('mouseenter', 'Icons', function() {
map.getCanvas().style.cursor = 'default';
var feature = e.features[0];
map.setPaintProperty('Icons', 'icon-opacity', 0.5);
});
// Change it back to a pointer and reset opacity when it leaves.
map.on('mouseleave', 'Icons', function() {
map.getCanvas().style.cursor = '',
map.setPaintProperty('Icons', 'icon-opacity', 1);
});
Thank you!!!
There are a few ways which you could achieve this. One approach is to add each feature as separate layer, so that when you want to change the opacity of an icon added in a layer 'specific-icon-layer', you can pass 'specific-icon-layer' to the Map#on method. This is likely the most straightforward option if you have a relatively minimal number of markers.
Another approach is to add unique IDs to each icon feature, so that you can use a filter expression in conjunction with Map#setPaintProperty and Map#queryRenderedFeatures (or Map#querySourceFeatures). For example, suppose you add an 'id' property to each GeoJSON feature representing an icon in the source for the 'Icons' layer. Then, you could set up an event listener similar to this example, retrieve the 'id' of the returned feature, and use the 'id' (suppose here it is 'example-id') to update the paint property for the 'Icons' layer:
map.setPaintProperty(
'Icons',
'icon-opacity',
['match', ['get', 'id'], 'example-id', 0.5 , 1]
);
Here, we use match and get expressions to say "if the 'id' of a feature is 'example-id', paint its icon with opacity 0.5, otherwise use opacity 1."
Check the example at https://docs.mapbox.com/mapbox-gl-js/example/hover-styles/
This approach makes use of setFeatureState and feature-state expressions
The problem with using map.setPaintProperty(layer, property, filter, matchValue, styleValue, fallbackStyleValue) every time is that it restyles every feature on the layer instead of only the feature being interacted with. This can cause poor performance when the layer has a high number of features.

Writing to absolute position while using direct content

I am creating a pdf-document. First I add a table and some Texts to the PdfWriter. Now I want to add a costum template (including images and texts): I have to get the direct Content, which ist a layer over the PdfWriter-layer:
over= PdfWriter.getDirectContent();
I want to set the template exactly after the content on PdfWriter-layer.
I can use
writer.getVerticalPosition(true)
for my calculation of y-Position on PdfWriter-layer.
This way I can add the costum template to the upper layer at that position. Now back to PdfWriter-layer how can I set the position of PdfWriter-layer after the tempalte on over-layer?!
Can somebody help?
Thanks in advance.
Mixing content added with document.add() and direct content us always a delicate operation. You need to know the height of the custom template and then add some white space that matches that height. However: what are you going to do if the content of the custom template doesn't match the page?
I would advise against your plans, and I would recommend another approach.
I am assuming that your custom template is a PdfTemplate object. In that case, you can wrap this object inside an Image object, and use document.add() to add the template.
See for instance: Changing Font on PDF Rotated Text
In this example, we create a PdfTemplate with a bar code and some text:
PdfTemplate template = canvas.createTemplate(rect.getWidth(), rect.getHeight() + 10);
ColumnText.showTextAligned(template, Element.ALIGN_LEFT,
new Phrase("DARK GRAY", regular), 0, rect.getHeight() + 2, 0);
barcode.placeBarcode(template, BaseColor.BLACK, BaseColor.BLACK);
We want to add this template to a document with document.add(), so we wrap the template inside an Image object:
Image image = Image.getInstance(template);
We can now add this image to the document:
document.add(image);
Afterwards, we can add extra content:
Paragraph p3 = new Paragraph("SMALL", regular);
p3.setAlignment(Element.ALIGN_CENTER);
document.add(p3);
That content is added under the template at the right position. You don't need to worry anymore about getting the Y position with getVerticalPosition() and you don't need to worry about setting the Y position after adding the template. If the template doesn't fit on the current page, it will automatically be moved to the next page.
Important: Maybe you are worried about the resolution of your template. You shouldn't be. If the template consists of vector data, wrapping that data inside an Image object won't change it into raster data. The vector data will be preserved. This is important in the bar code example, because you don't want the quality of your bar code to deteriorate by making it a raster image.

Change color of a node in Zest

I'm using Zest to draw a graph. However, I want to change the default color of the graphnode to another color based on its label. For example: Label: red => color of the node is red.
If you are using the GraphViewer API of Zest (similar to JFace viewers), let your LabelProvider extend IEntityStyleProvider that provides the necessary getBackgroundColor() callback method (among others).
However, if you are using the base Graph API, then you have to set the color of all the nodes manually using the GraphNodes set*Color methods.

programmatically change the background color in eclipse

I have a question related to eclipse plugin development. Is there any means
by which I can programmatically change the background color in eclipse.
I am able to change the text foreground color by calling
setTextColor(color, offset, length, controlRedraw) in ITextViewer
but I don't find any function by which I can change the background
color of the text.
If anyone has been through this kindly share your thoughts.
Thanks
arav
I am not sure this can be done easily, short of extending your own version of a Text Editor, here you provide a Configuration Class which inturn accepts a PresentationReconciler Class which is like a Rule Class that tells you if you need to put a Foreground or a Background Color
See this document
PresentationReconciler
IPresentationDamager: define dirty region given a text change
IPresentationRepairer: recreate presentation for dirty region
DefaultDamagerRepairer does both, based on a token scanner
ITokenScanner: parse text into a token stream
RuleBasedScanner uses simple rules
Extract from the presentation
From Text Editor Recipes, Season’s recipes for your text editor
Tom Eicher, IBM Eclipse Team
Here, the null background color means, takes the default system background for that widget. (so here: white).
But you could specify whatever color you want, based on the partitioning of your document and on the rules that would apply.
I know this was asked a while ago, but in case anyone is looking for another solution, I thought I would post the following:
Since you are able to use the setTextColor method, then you should be able to use the changeTextPresentation method as well.
In the case of my plug-in, I have a TextListener that calls the TextChanged method I overwrote. I did the following to add background color using the changeTextPresentation method. In doing so, I was able to get a Green background with Black foreground. Not that I would want this, of course, but just for testing purposes.
public void TextChanged(TextEvent event){
...
TextPresentation presentation = new TextPresentation();
TextAttribute attr = new TextAttribute(new ColorManager().getColor(MyConstants.BLACK),
new ColorManager().getColor(MyConstants.GREEN), style);
presentation.addStyleRange(new StyleRange(startOffset, tokLength, attr.getForeground(),
attr.getBackground());
sourceViewer.changeTextPresentation(presentation, true); //sourceViewer is a global variable passed to my TextListener class constructor.
}