Styling Turf buffer based on marker attribute - leaflet

As title suggests, i'm trying to style the Turf buffers around my marker layer based on attributes from that marker layer.
I know how to style a layer based on attributes of that SAME layer but am having trouble connecting the style to the buffers instead.
I have played with two methods, both of which are able to style my buffers but still don't connect to my marker's attribute information (for obvious reasons as you will see). Please ignore any strange formatting as the post rearranged things and I tried to fix them.
Attempt 1:
lyrHouses = {
type: "FeatureCollection",
features: [],
};
// parse local CSV file
Papa.parse("src/data1/Houses.csv", {
header: true,
download: true,
dynamicTyping: true,
skipEmptyLines: true,
complete: function (results) {
results.data.forEach((house) => {
feature = {
type: "Feature",
geometry: {
type: "Point",
coordinates: [house.Longitude, house.Latitude],
},
properties: {
Location: house.Location,
Type: house.Type,
},
};
mrkHouses = L.geoJSON(feature).addTo(mymap);
lyrHouses.features.push(feature);
houseBuffer = turf.buffer(mrkHouses.toGeoJSON(), 3, {
units: "kilometers",
});
lyrTest = L.geoJSON(houseBuffer, {
style: function (feature) {
switch (feature.properties.Type) {
case "Duplex":
return { color: "blue" };
case "Quadplex":
return { color: "yellow" };
}
return { color: "red" };
},
}).addTo(mymap);
});
},
});
Attempt 2:
function setBuffColor(d) {
return d = 'Duplex' ? "green" :
d = 'Quadplex' ? "red" :
d = 'Semidetached' ? "blue" :
'#FFED80';
}
function BuffStyle(feature) {
return {
color: setBuffColor(feature.properties.Type),
};
}

Why just not like this?
lyrTest = L.geoJSON(houseBuffer, { style: house.Type === 'Duplex' ? { color: "blue" } : (house.Type === 'Quadplex' ? { color: "yellow" } : { color: "red" }) });

Related

Is there any way to downplay toolbox custom feature button on another feature button

Two custom feature added in toolbox. I need functionality where in we can reset one feature on click of another.
like existing feature 'zoom' button and 'horizontally select' brush button. If we click the zoom button first and then click on brush button then zoom button automatically gets reset to default.
below is the reference code -
`function func(x) {
x /= 10;
return Math.random() * 22;
}
function generateData() {
let data = [];
for (let i = 0; i <= 10; i += 0.1) {
data.push([i, func(i)]);
}
return data;
}
var isPointSelect = false;
var rangeSelector = false;
option = {
animation: false,
toolbox: {
feature: {
dataZoom: {
yAxisIndex: false
},
myRangeSelector: {
show: true,
title: 'Range Selector',
icon: 'path://M432.45,595.444c0,2.177-4.661,6.82-11.305,6.82c-6.475,0-11.306-4.567-11.306-6.82s4.852-6.812,11.306-6.812C427.841,588.632,432.452,593.191,432.45,595.444L432.45,595.444z M421.155,589.876c-3.009,0-5.448,2.495-5.448,5.572s2.439,5.572,5.448,5.572c3.01,0,5.449-2.495,5.449-5.572C426.604,592.371,424.165,589.876,421.155,589.876L421.155,589.876z M421.146,591.891c-1.916,0-3.47,1.589-3.47,3.549c0,1.959,1.554,3.548,3.47,3.548s3.469-1.589,3.469-3.548C424.614,593.479,423.062,591.891,421.146,591.891L421.146,591.891zM421.146,591.891',
onclick: function (model, api, type) {
// debugger;
rangeSelector = !rangeSelector;
this.model.setIconStatus(type, rangeSelector ? 'emphasis' : 'normal');
}
},
myPointSelect: {
show: true,
title: 'Point Select',
icon: 'path://M432.45,595.444c0,2.177-4.689,6.82-11.305,6.82r-6.475,0-11.306-4.567-11.306-6.82s4.852-6.812,11.306-6.812C427.841,588.632,432.452,593.191,432.45,595.444L432.45,595.444z M421.155,589.876c-3.009,0-5.448,2.495-5.448,5.572s2.439,5.572,5.448,5.572c3.01,0,5.449-2.495,5.449-5.572C426.604,592.371,424.165,589.876,421.155,589.876L421.155,589.876z M621.146,591.294c-1.916,0-3.47,1.589-3.47,3.549c0,1.959,1.554,3.548,3.47,3.548s3.469-1.589,3.469-3.548C424.614,593.479,423.062,591.891,421.146,591.891L421.146,591.891zM421.146,591.891',
onclick: function (model, api, type) {
isPointSelect = !isPointSelect;
this.model.setIconStatus(type, isPointSelect ? 'emphasis' : 'normal');
}
},
brush: {
type: ['lineX', 'clear', 'keep']
}
}
},
brush: {
xAxisIndex: 'all',
brushLink: 'all',
brushStyle: {
color: 'white'
},
outOfBrush: {
colorAlpha: 0.1
}
},
graphic: {
elements: []
},
grid: {
top: 100,
left: 50,
right: 40,
bottom: 50
},
xAxis: {
minorTick: {
show: true
},
minorSplitLine: {
show: true
}
},
yAxis: {
minorTick: {
show: true
},
minorSplitLine: {
show: true
}
},
series: [
{
type: 'line',
showSymbol: false,
clip: true,
data: generateData(),
markArea: {
data: []
}
}
]
};`
Echart has similar functionality for zoom and brush feature.

How to save/update object in collection and embed object in object?

I have two collections Colors and Cars.
In the car possibly to choose the color.
How to save/update object in collection so that embed Color object in Car object?
Cars = new Mongo.Collection('cars');
Cars.attachSchema(new SimpleSchema({
colorId: {
label: 'Color',
type: String,
autoform: {
options: function () {
return Colors.find().map(function (p) {
return {label: p.colorName, value: p._id};
});
},
label: false
}
},
color: {
type: Object,
},
'color._id': {
type: String,
autoform: {
omit: true,
},
},
'color.colorName': {
type: String,
autoform: {
omit: true,
},
},
'color.colorCode': {
type: String,
autoform: {
omit: true,
},
},
}));
Colors = new Mongo.Collection('colors');
Colors.attachSchema(new SimpleSchema({
colorName: {
type: String,
label: "Color Name",
max: 20,
},
colorCode: {
type: String,
optional: true,
label: "Color Code",
autoform: {
afFieldInput: {
type: "color"
}
}
},
}));
I try use
AutoForm.hooks({ insertCarForm: {before: {
but it did not work
There are several ways that you can achieve this and the solution largly depends on any relevant packages that you might be using. It's hard to give a working example without seeing your existing code that creates new 'cards'. Nevertheless, here is an example using the core Meteor API.
Assuming you have some form Template defined (which I have called 'manageCar'), you would do something like this.
Define a Meteor Method to handle inserting/updating the Car.
Meteor.methods({
updateCar: function(carDoc) {
check(carDoc, { /* carDoc schema */ });
const color = Colors.findOne(carDoc.colorId);
carDoc.color = color;
if (carDoc._id) {
Cars.update(carDoc._id, {
$set: {
colorId: carDoc.colorId,
color: carDoc.color,
}
})
} else {
Cars.insert(carDoc);
}
},
});
Add an event handler for the form submission that calls the defined Method.
Template.manageCar.events({
'click .js-save-car'(event, instance) {
const data = {
_id: event.target._id.value,
colorId: event.target.colorId.value
};
Meteor.call('updateCar', data, function(error, result) {
if (!error) {
alert('Car updated successfully');
}
});
}
});
Long story short, you just need to make sure you have access to the Color id that you are saving for the Car and then make sure you perform a find on the Color collection to retrieve the necessary Color document, then use that for your Car insert or update.
Let me know if you have any questions or need further explanation.

How to position the dataLabel for highcharts on the same side of the x-axis?

I have a column chart with positive and negative values. Using the default dataLabels, keeps the label at the end of the column, which isn't ideal for negative values, as it goes below the x axis.
$(function () {
$('#container').highcharts({
chart: {
type: 'column',
height: 200,
borderColor: '#ddd'
},
title: {
text: ''
},
legend: {
padding: 0,
margin: 5
},
credits: {
enabled: true
},
tooltip: {
enabled: false
},
plotOptions: {
column: {
dataLabels: {
enabled: true,
crop: false,
overflow: 'none'
}
}
},
colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'],
loading: {
labelStyle: {
top: '35%',
fontSize: "2em"
}
},
xAxis: {
categories: ["7/12", "7/13", "7/14", "7/15", "7/16"]
},
series: [{
"name": "Odometer",
"data": [{
"y": 94.98
}, {
"y": 182.96
}, {
"y": -160.97
}, {
"y": -18.00
}, {
"y": 117.97
}]
}]
});});
Example: http://jsfiddle.net/absessive/NKXRk/54/
Add plotOptions.column.stacking as normal like this and it will work.
You can change a little bit Highcharts.seriesTypes.column.prototype.alignDataLabel function, so it will not have functionality of aligning the dataLabel below your column if its value is smaller than 0.
Here you can find code that may help you:
H.seriesTypes.column.prototype.alignDataLabel = function(point, dataLabel, options, alignTo, isNew) {
var inverted = this.chart.inverted,
pick = H.pick,
Series = H.Series,
series = point.series,
merge = H.merge,
dlBox = point.dlBox || point.shapeArgs, // data label box for alignment
below = false,
inside = pick(options.inside, !!this.options.stacking), // draw it inside the box?
overshoot;
// Align to the column itself, or the top of it
if (dlBox) { // Area range uses this method but not alignTo
alignTo = merge(dlBox);
if (alignTo.y < 0) {
alignTo.height += alignTo.y;
alignTo.y = 0;
}
overshoot = alignTo.y + alignTo.height - series.yAxis.len;
if (overshoot > 0) {
alignTo.height -= overshoot;
}
if (inverted) {
alignTo = {
x: series.yAxis.len - alignTo.y - alignTo.height,
y: series.xAxis.len - alignTo.x - alignTo.width,
width: alignTo.height,
height: alignTo.width
};
}
// Compute the alignment box
if (!inside) {
if (inverted) {
alignTo.x += below ? 0 : alignTo.width;
alignTo.width = 0;
} else {
alignTo.y += below ? alignTo.height : 0;
alignTo.height = 0;
}
}
}
// When alignment is undefined (typically columns and bars), display the individual
// point below or above the point depending on the threshold
options.align = pick(
options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'
);
options.verticalAlign = pick(
options.verticalAlign,
inverted || inside ? 'middle' : below ? 'top' : 'bottom'
);
// Call the parent method
Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
};
The only change I have made is that I have changed below parameter to false.
Here you can find an example how it can work:
http://jsfiddle.net/NKXRk/59/
Best regards,

Highcharts :Donut chart overlaps data labels

I'm working on a donut chart type, with the Highcharts library.
As you can see in the image below, some of the inner data labels are overlapped.
I've been playing with the parameter "distance" but doesn't fix this.
Find attached the code below,
// Create the chart
$(container).highcharts({
chart: {
type: 'pie'
},
credits: {
enabled: false
},
exporting: {
buttons: {
contextButton: {
symbol: 'url(/icon-turn-down.png)'
}
}
},
title: {
text: _title,
margin: 50
},
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%']
}
},
tooltip: {
formatter: function() {
var s = this.point.name.split('.');
if (s.length == 1) {
return this.y > 1? '<b>'+this.point.name+':</b> '+Highcharts.numberFormat(this.point.y) : null;
}
return this.y > 1? s[0]+'<br /><b>'+$.trim(s[1])+':</b> '+Highcharts.numberFormat(this.point.y) : null;
}
},
series: [{
name: '',
data: innerData,
size: '80%',
dataLabels: {
formatter: function() {
return this.y > 0 ? this.point.name : null;
},
color: 'white',
distance: -50
}
}, {
name: '',
data: outerData,
size: '100%',
innerSize: '80%',
dataLabels: {
formatter: function() {
var s = this.point.name.split('.');
if (s.length == 1) {
return this.y > 1 ? '<b>'+ this.point.name+':</b> '+ Highcharts.numberFormat(this.point.y) : null ;
}
s = this.point.name.substring(this.point.name.indexOf(".")+2);
return this.y > 1 ? '<b>'+ s+':</b> '+ Highcharts.numberFormat(this.point.y): null;
},
style: {
fontSize: "10px",
fontColor: "#000000"
}
}
}]
});
Finally, I found a solution, which is playing with the "startangle" attribute.
series: [{
name: '',
data: innerData,
startAngle:110,
size: '80%',
dataLabels: {
formatter: function() {
return this.y > 0 ? this.point.name : null;
},
color: 'white',
distance: -45
}, {
...
Distance parameter cannot be applied for each point, only general, so only what comes to my mind is iteared on each datalabel and use translate() function, or use formatter, apply CSS class and dhten use top/left parameter for each element. But will be helpful if you recreate your example as fiddle.

Extjs chart shadow

I have the following code to contruct a pie chart.
The problem is i don't get a shadow.
Note : If the chart config, theme='Base', then the pie has a shadow
Ext.define('ChartPanel', {
extend: 'Ext.panel.Panel',
//------------------CONSTRUCTOR
, constructor: function(externalConfigs) {
externalConfigs = externalConfigs || {};
var configs = {
title: 'My panel',
items: [
{
xtype: 'chart',
store: myStore,
width: '30%',
series: [{
type: 'pie'
, field: 'persentage'
, shadow: 'sides'
, showInLegend: false
, donut: false
, renderer: function(sprite, record, attributes, index, store) {
if (record.data.description == 'option1') {
sprite.setAttributes({
fill: 'url(#redGradient)',
stroke: '#ffffff'
}, false);
} else if (record.data.description == 'option2') {
sprite.setAttributes({
fill: 'url(#greenGradient)',
stroke: '#ffffff'
}, false);
}
}
}]
, gradients: [{
id: 'redGradient',
angle: 45,
stops: {
0: { color: '#820000' },
100: { color: '#BD1E00' }
}
}, {
id: 'greenGradient',
angle: 0,
stops: {
0: { color: '#89AC10' },
100: { color: '#A1C22D' }
}
}]
}
]
}
Ext.apply(configs, externalConfigs);
this.callParent([configs]); //Call the parent constructor
}
});
Any ideas how to get a shadow?
Thanks
Use shadow: true (see the docs in the previous link to see other possible options) within your chart definition. (Not within the pie definition). There is no shadow config property for Ext.chart.series.Pie. You would need to use shadowAttributes within Ext.chart.series.Pie.
I found that
return attributes;
inside the renderer is essential.