I have code like this
private _addLayer(layerName: string, featureGeometry: any, featureName: string, style: any,
featureLabel: string = '') {
const labelStyle = new OM.style.Text({
fontSize: 16,
fill: '#FF0000'
})
let layer = new OM.layer.VectorLayer(layerName, {
renderingStyle: style,
def:
{
type: OM.layer.VectorLayer.TYPE_LOCAL,
features: [new OM.Feature(featureName, featureGeometry, {label: featureLabel})]
}
})
layer.setLabelsVisible(true);
layer.setLabelingStyle(labelStyle)
this._map.addLayer(layer);
}
Just adding line and label to map.
I want change default label position (for example basement to vertical align).
But I don't find in docs information about to set label position (OM.Style.Text).
So, How can I do this?
Related
I have integrated a Parcel Layer in the ArcGIS Esri map inside Angular application. But now I want to change the format of some values coming up in the popup template when user clicks on certain Parcel.
Now my popup values looks like this.
ASSMT_YEAR - 2,017.00
ATTDATE - 20190130
BATHROOMS - 0.00
Requirement
ASSMT_YEAR and YEAR_BUILT value format should not include commas or decimals.
ATTDATE and REC_DATE value format should be in date format.(01/30/2019)
How can I achieve above requirement?
.ts file
const createEsriPopupTemplate = function(layer) {
const config = {
fields: layer.fields.map(field => (
{
name: field.name,
type: field.type,
}
)),
title: formatName(layer.title),
};
return popupUtils.createPopupTemplate(config);
}
for (const layer of esriLayers) {
view.whenLayerView(layer).then(function (layerView) {
const popupTemplate = createEsriPopupTemplate(layer)
if (!popupTemplate) {
console.log("FeatureLayer has no fields.")
} else {
layer.popupTemplate = popupTemplate;
}
});
}
To format the fields for the popup, you can use format property of popup fieldInfos.
ArcGIS JS API - Field Info Format
In your case I think this config should work,
fieldInfos: [
{
fieldName: "ASSMT_YEAR",
label: "ASSMT Year",
format: {
dateFormat: "short-date"
}
},
{
fieldName: "ATTDATE",
label: "Attendance Date",
format: {
dateFormat: "short-date"
}
},
{
fieldName: "BATHROOMS",
label: "Bathrooms"
format: {
digitSeparator: true,
places: 0
}
}
]
Now, you are generating the popup using popupUtils.createPopupTemplate function. So to continue in that path, you will need to change a bit.
First you need to know what fields to change, and in that regard you will have to use something, for example the field type.
Second, the easy change I think it would be instead of popupUtils.createPopupTemplate, use popupUtils.createFieldInfos and follow the doc example.
I'm using Go.js to create a canvas a user can draw straight lines on. From the documentation, I've been able to create nodes. Node creation code looks like:
const node = this.goMake(go.Node, 'Horizontal',
{ position: new go.Point(point[0], point[1]) }, // set the Node.position
this.goMake(go.Shape, 'Circle', { width: 10, height: 10, fill: 'lightblue' })
);
As I understand the documentation, in order to create a line (non-directional link) between the two nodes, I need to use their key values like so:
this.myDiagram.model.addLinkData({ from: node1.key, to: node2.key });
When logging out my nodes, I see that key value is an empty string.
Question: When creating my nodes using the first snippet above, how do I inject the key value so the second code snippet properly links the two? Creating unique values for all points is not an issue, I just can't figure out how to attach the unique value to the node's key property.
keys are a property of Model data, where the model has an array of node data and link data. Keys are not properties of the Nodes themselves exactly. node.key is just a convenience for node.data.key.
So when you write:
myDiagram.model.addNodeData( { key: 'a' });
It is making a copy of the myDiagram.nodeTemplate, and assigning that Node the node.data of { key: 'a' }, so that node's key is 'a'
In other words, you can only relate these things by the model, not by the Node that you are creating.
If you are using models, you should be creating node templates on the Diagram, not stand-alone nodes, as it appears you are doing. So something like:
myDiagram.nodeTemplate = this.goMake(go.Node, 'Horizontal',
{ position: new go.Point(point[0], point[1]) }, // set the Node.position
this.goMake(go.Shape, 'Circle', { width: 10, height: 10, fill: 'lightblue' })
);
or if you have multiple templates:
myDiagram.nodeTemplateMap.add('newTemplate', this.goMake(go.Node, 'Horizontal',
{ position: new go.Point(point[0], point[1]) }, // set the Node.position
this.goMake(go.Shape, 'Circle', { width: 10, height: 10, fill: 'lightblue' })
));
I am using country_map in apache-superset for visualization purposes. When zooming in on a polygon, information from the columns appears inside of the polygon, like so:
There is only one available metric option to display:
Code for the metric update is found on this path:
superset/assets/src/visualizations/CountryMap/CountryMap.js
Code:
const updateMetrics = function (region) {
if (region.length > 0) {
resultText.text(format(region[0].metric));
}
};
The metrics are defined in controls.jsx:
/superset/static/assets/src/explore/controls.jsx
const metrics = {
type: 'MetricsControl',
multi: true,
label: t('Metrics'),
validators: [v.nonEmpty],
default: (c) => {
const metric = mainMetric(c.savedMetrics);
return metric ? [metric] : null;
},
mapStateToProps: (state) => {
const datasource = state.datasource;
return {
columns: datasource ? datasource.columns : [],
savedMetrics: datasource ? datasource.metrics : [],
datasourceType: datasource && datasource.type,
};
},
description: t('One or many metrics to display'),
};
const metric = {
...metrics,
multi: false,
label: t('Metric'),
default: props => mainMetric(props.savedMetrics),
};
Country map is using metric, which doesn't allow multiple metrics to be selected, Code found here:
superset/assets/src/explore/controlPanels/CountryMap.js
controlPanelSections: [
{
label: t('Query'),
expanded: true,
controlSetRows: [
['entity'],
['metric'],
['adhoc_filters'],
],
},
{
label: t('Options'),
expanded: true,
controlSetRows: [
['select_country', 'number_format'],
['linear_color_scheme'],
],
},
],
The python class of country_map is located at viz.py:
class CountryMapViz(BaseViz):
"""A country centric"""
viz_type = 'country_map'
verbose_name = _('Country Map')
is_timeseries = False
credits = 'From bl.ocks.org By john-guerra'
def query_obj(self):
qry = super(CountryMapViz, self).query_obj()
qry['metrics'] = [
self.form_data['metric']]
qry['groupby'] = [self.form_data['entity']]
return qry
Changing the code in CountryMap.js and viz.py from metric to metrics results in the following error:
Traceback (most recent call last):
File "/Documents/superset/superset/superset/viz.py", line 410, in get_df_payload
df = self.get_df(query_obj)
File "/Documents/superset/superset/superset/viz.py", line 213, in get_df
self.results = self.datasource.query(query_obj)
File "/Documents/superset/superset/superset/connectors/sqla/models.py", line 797, in query
sql = self.get_query_str(query_obj)
File "/Documents/superset/superset/superset/connectors/sqla/models.py", line 471, in get_query_str
qry = self.get_sqla_query(**query_obj)
File "/Documents/superset/superset/superset/connectors/sqla/models.py", line 585, in get_sqla_query
elif m in metrics_dict:
TypeError: unhashable type: 'list'
How can I add more metrics to display inside the polygon?
The direct cause of the error TypeError: unhashable type: 'list' is your modification to file "viz.py":
self.form_data['metric']] to self.form_data['metrics']], in the query_obj(self) method.
As you can see in the source code here, form data metrics is a list object that contains metric, where metric is probably a string or other hashable object. In python language, a list object is not hashable. Because you replace a hashable object (metric) with an unhashable one (metrics), an unhashable type error is then raised.
The correct way to modify CoutryMapViz.query_obj() to accept metrics query can be found in the other Viz classes. The code section here is a very nice example:
class CalHeatmapViz(BaseViz):
"""Calendar heatmap."""
...
def query_obj(self):
d = super(CalHeatmapViz, self).query_obj()
fd = self.form_data
d['metrics'] = fd.get('metrics')
return d
Finally, the CoutryMapViz.query_obj() method should look like this:
class CountryMapViz(BaseViz):
...
def query_obj(self):
qry = super(CountryMapViz, self).query_obj()
qry['metrics'] = fd.get('metrics')
qry['groupby'] = [self.form_data['entity']]
return qry
I am building a map using the Google Maps API and have hit a snag. In the table I have a column that labels the iconName for each marker ('mStyle', it's col3). In the following code I am trying to set the icon style based on the column values, and I've tried many, many different iterations that haven't worked. Including this one.
What has perplexed me, is that replacing iconStyler:{} with iconName: 'grn_blank' (or whatever) does work. The documentation for markerOptions is here: https://developers.google.com/fusiontables/docs/v1/reference/style
var layer = new google.maps.FusionTablesLayer();
layer.setOptions
(
{
query:
{
select: "col0",
from: "1UtgWf_kgwI3iUtrWvH3vIbxJfBdutl9oR8Wjqhiv",
where: ""
},
styles:
[{
markerOptions:
{
iconStyler:
{
kind: 'fromColumn',
columnName: 'mStyle',
}
}
}]
}
);
The code can be accessed here: https://drive.google.com/file/d/0BxeBEc_dsbUqWVJwbV9JTXRvb2s/edit?usp=sharing
The way the map should look is about 800 flags in the DC area, in various colors (red, purple, blue, green, light blue, and white). They represent schools. I can make it work in the browser-based editor, but I am adding dynamics once I get this piece to work, so I need it to work in Javascript.
Thanks
Click on the map tab in the fusion tables UI, select "Publish", "Get HTML and Javascript".
In that code grab the layer definition:
layer = new google.maps.FusionTablesLayer({
map: map,
heatmap: { enabled: false },
query: {
select: "col0",
from: "1UtgWf_kgwI3iUtrWvH3vIbxJfBdutl9oR8Wjqhiv",
where: ""
},
options: {
styleId: 2,
templateId: 2
}
});
you want the styleId and templateId defined there (looks like 2 and 2 to me).
I am using the MarkerCluster.js to create clustering in my google maps api. The clusters work how I want them however I want to style differently than yellow, blue and red circles. I was trying to use the MarkerStyleOptions and it says you have an array of styles with the smallest cluster icon first and the biggest last. I tried to create this below but I am getting really confused about what syntax to use and can't find any good examples.
var clusterStyles = [
[opt_textColor: 'white'],
[opt_textColor: 'white'],
[opt_textColor: 'white']
];
var mcOptions = {
gridSize: 50,
styles: clusterStyles,
maxZoom: 15
};
var markerclusterer = new MarkerClusterer(map, cluster, mcOptions);
What you need to do is use the url to specify which images to use instead of the blue/yellow/red images currently being used. And probably a good idea to include the height and width options too.
var clusterStyles = [
{
textColor: 'white',
url: 'path/to/smallclusterimage.png',
height: 50,
width: 50
},
{
textColor: 'white',
url: 'path/to/mediumclusterimage.png',
height: 50,
width: 50
},
{
textColor: 'white',
url: 'path/to/largeclusterimage.png',
height: 50,
width: 50
}
];
It's never too late to post a rather helpful answer, so additionally you can look through the whole MarkerClusterer Documentation for IconStyle
UPDATE
There's also google maps v3 utility on github as stated by ehcanadian
According to latest docs, renderer does the trick. It allows you to use a Marker w/all its styling options - see Marker documentation:
new MarkerClusterer({
renderer: {
render: ({ markers, _position: position }) => {
//here is where you return a Marker
//and style it w/custom label/icon props
return new google.maps.Marker({
position: {
lat: position.lat(),
lng: position.lng(),
},
label: String(markers.length),
});
},
},
...etc
});
You can now pass your own renderer to your MarkerClusterer Object which returns a google.maps.Marker like this:
const renderer = {
render({ count, position }) {
return new google.maps.Marker({
label: { text: String(count), color: "white", fontSize: "10px" },
position,
// adjust zIndex to be above other markers
zIndex: Number(google.maps.Marker.MAX_ZINDEX) + count,
});
}
}
// use this if you use NPM version
const markerCluster = new MarkerClusterer({ map, markers, renderer });
// Use this if you use the CDN version
// const markerCluster = new markerClusterer.MarkerClusterer({ markers, map , renderer});
Inside the render method, you can customize the cluster maker the same way you would customize normal marker. See https://developers.google.com/maps/documentation/javascript/custom-markers for more details. For example, if you just want to add a specific icon.png you could do it like this:
const icon = {
url: '/path/to/your/icon.png',
scaledSize: new google.maps.Size(50, 50),
};
const renderer = {
render({ count, position }) {
return new google.maps.Marker({
label: { text: String(count), color: "white", fontSize: "10px" },
position,
icon,
// adjust zIndex to be above other markers
zIndex: Number(google.maps.Marker.MAX_ZINDEX) + count,
});
}
}
You can also find some clustor marker render example at https://googlemaps.github.io/js-markerclusterer/public/renderers/
See https://developers.google.com/maps/documentation/javascript/marker-clustering for a full example how to setup MarkerCluster.
History Details:
The MarkerCluster library has been rewritten in 2021. One goal was to change the render process. The cluster icon itself is now a google.maps.Marker and can thus be styled just as normal marker. The mcOptions in the constructor is gone.
The proposed design is to encapsulate the logic for clustering and rendering into interfaces that the developer can extend specifically algorithm and renderer. The algorithm computes the clusters and the renderer generates a google.maps.Marker to represent clusters instead of using a google.maps.OverlayView.
https://github.com/googlemaps/js-markerclustererplus/issues/300
https://github.com/googlemaps/js-markerclustererplus/issues/293
https://docs.google.com/document/d/1X8hQaHdVvpB-12bOQ_qbgfGFet8gPRTtHyO_EihcpsA/edit