Is it possible to control which layers are in front on deck.gl? - deck.gl

On Leaflet, when I create a layer from a GeoJSON, I have a way of controlling which layer is shown in front of the map by looping the layer features and then using a function like feature.bringToFront(). The result is like the following:
On deck.gl however, after creating my layers from a GeoJSON, it's hard to tell which layer is in front of the map... The following image is the same example made with deck.gl instead of Leaflet.
So, is there any way of controlling the feature that I want to show in front with deck.gl? I know I could change the elevation when the view of the map is from above, but in this case, it's not a good solution when I'm navigating through the 3D map. Is it possible to do on deck.gl? Can I force some specific feature to appear in front of others? Is there any parameter or function that controls that?

Have been working on this for a few hours and from a leafletJs background.
The closest I've gotten to a feature.bringToFront equivalent is that you can order the layers and pass that to the DeckGl component, a description from the deck.gl documentation is here:
https://deck.gl/docs/developer-guide/using-layers#rendering-layers
The below works for me, however, it seems to work only for layers of the same type. In the example below, if I add a LineLayer type at index 0 of the layers array below, it will render in front of the two SolidPolygonLayer's below.
const layers = [
new SolidPolygonLayer({
id: 'at array index 0 and appears in the background',
data: helper.getPolygonData(),
getPolygon: d => d.coordinates,
getFillColor: d => [255, 0, 0],
filled: true,
}),
new SolidPolygonLayer({
id: 'at array index 1 and appears in the foreground',
data: helper.getPolygonData(),
getPolygon: d => d.coordinates,
getFillColor: d => d.color,
filled: true,
}),
];
return (
<DeckGL
layers={layers}
viewState={getViewState()}
onViewStateChange={e => setViewState(e.viewState)}
initialViewState={INITIAL_VIEW_STATE}
controller={true}
getTooltip={getTooltip}
>
...
</DeckGL>
);

Related

How to create a Crossword board in React Native

I'm trying to create a crossword game in react native. I'm having trouble starting off with the gameboard. I think I'm going to have the crosswords stored in an object like
{
across: {
1: {
question: "test",
answer: "test",
position:(0,0),
length: 4,
}
}
down:{}
}
Would it make sense to create a matrix of 0 for black squares 1 for white squares and 2 for word starting squares. Then use a flat list to build out the matrix visually?
Any help or advise on another way to do it would be appreciated.
Cheers,
I've. tried. using flat lists but the indexing becomes very complicated and I'm hoping there is a better way.
I made one of those React Pathfinding visualizers and basically just had an array I kept track of thru state for if it was filled or not. Map/ForEach that grid and plop down what you would have as another component shall we say Node passing whatever information is needed as props.
This example may not be the best, due to it being React and not React Native (small difference really)... and there is a lot to this that doesn't apply to your scenario but I think it shows what I mentioned in the beginning.
<div className="grid">
{grid.map((row, rowId) => {
return (
<div key={rowId}>
{row.map((node, nodeId) => {
const { row, col, isFinish, isStart, isWall } = node;
return (
<Node
key={nodeId}
row={row}
col={col}
isStart={isStart}
isFinish={isFinish}
isWall={isWall}
mouseIsPressed={this.state.mouseIsPressed}
onMouseDown={(row, col) => this.handleMouseDown(row, col)}
onMouseEnter={(row, col) =>
this.handleMouseEnter(row, col)
}
onMouseUp={() => this.handleMouseUp()}
></Node>
);
})}
</div>
);
})}
</div>
I'd map the crossword data to an array of fields. There are three types of fields in crosswords: question block, fillable block and dead block.
Algorithmically, there are countless options. One would be to first convert every question to its blocks and then convert all of these to a flat array of blocks, combined.
Extra tip: consider using an array of questions instead of an object indexed by numbers. These indexes don't matter anyway.

How to do series/parallel animation in react-native-reanimated 2?

I'm looking for the equivalent of Animated.sequence and Animated.parallel from react-native. So far from the docs for v2, I could only see the withSequence function that changes the value of only on value and therefore the style of only one component in series.
What I was looking for was to trigger animations in two different components, either in series or in parallel.
For parallel, it seems changing values in statements one after another worked. Correct me if I'm wrong.
// these will run in parallel
val1Shared.value = withTiming(50);
val2Shared.value = withTiming(100);
But for series, I need to have each animation inside a useTiming callback. Which leads to kind of callback hell.
val1Shared.value = withTiming(50, undefined, () => {
val2Shared.value = withTiming(100);
});
Please help with the best practices in achieving this with reanimated 2.
Thanks.
I think there is no way of doing it like in Animated.
This library requires you to think a different way. If you want you run two animations (each one for a separate view) using interpolation, you can use a single shared value and a sufficient interpolation config.
Let's assume (according to your example) that you have two views you want to animate. The first animation is from 0 to 50, the second one is from 0 to 100.
Let's also assume you're transforming an X axis (I don't know what's your case, but it's going to be very similar) and we count the animation progress from 0 to 1, and both views will animate for the same period of time.
Initialize the shared value:
const animation = useSharedValue(0);
And do sth like this (of your choice):
animated.value = withTiming(1, { duration, easing });
For the first view, your transformation will look like this:
const animatedStyles1 = useAnimatedStyle(
() => ({
transform: [
{
translateX: interpolate(animation.value, [0, 0.5, 1], [0, 50, 50]),
},
],
}),
[mode, rectSize]);
and for the second one, like this:
const animatedStyles2 = useAnimatedStyle(
() => ({
transform: [
{
translateX: interpolate(animation.value, [0, 0.5, 1], [0, 0, 100]),
},
],
}),
[mode, rectSize]);
Now the explanation.
For the first view, we only work for the half of progress from the whole animation, so we from 0 to 0.5 we'll animate from 0 to 50. then, for the reset of the progress we'll stay in the same place (this is called a dead zone), to from 0.5 to 1 value of the progress does not change (50 to 50).
Now, for the second view, we wait for the progress to be in half, so from 0 to 0.5 we don't do anything (0 to 0). Then, when the progress is in half, we animate the view from 0 to 150.
In general, that way you can orchestrate the whole thing using just a single shared value.
Here you can find more info about the interpolation. The docs is from the react-native's Animated, but the idea is the same.
Good luck!

Problem painting a map with Openlayers using Vue

I'm writing an application in Vue that will have a map in it. I want to add some points in that map. The code relevant to the map is,
<div>
<vl-map :load-tiles-while-animating="true" :load-tiles-while-interacting="true" data-projection="EPSG:4326" style="height: 400px">
<vl-view :zoom.sync="zoom" :center.sync="center" :rotation.sync="rotation"></vl-view>
<vl-layer-tile>
<vl-source-osm></vl-source-osm>
</vl-layer-tile>
<vl-layer-vector>
<vl-source-vector :features="points"></vl-source-vector>
</vl-layer-vector>
</vl-map>
</div>
Here points is part of data points: []
If I write the points directly in data everything works.
Like,
points: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [0.0, 0.0]
},
properties: {}
]
shows a point in [0, 0].
However, I need to use a method that will call several APIs to find out the points that I need to show. It's when I write the code to prepare the points to have the correct value when everything stops working. I'm writing this code in the mounted section.
async calculatePoints () {
this.points = // points as I want them to be
}
But this is not working (although some few times works). Any idea what is going on here or which is the best way to handle this?

Problem using Filters and Sprites in a StageGL context

First of all, sory my English.
I am working with some sprites using WebGL on CreateJS library. I need apply a custom color filter over the jpg used to create the spritsheet.
Here is my code:
let bmp = new createjs.Bitmap(rscTexture);
bmp.filters = [new createjs.AlphaFilter()];
bmp.cache(0, 0, rscTexture.width, rscTexture.height, {1, useGL:"stage"});
let frames = this.generateFrames();
this.sprite = new createjs.Sprite( new createjs.SpriteSheet({
framerate: 24,
"images": [bmp.cacheCanvas],
"frames": frames,
"animations": {
"run": [0, frames.length - 1],
}
}));
The problem is that this trow next error:
ERROR Cannot use 'stage' for cache because the object's parent stage
is not set, please addChild to the correct stage.
How can I add the element to the stage first, if I still do not create it?
If you have a StageGL instance that already exists, you can pass it in directly instead. The "stage" shortcut attempts to figure it out; however, sometimes you need to be specific and directly passing the reference is the only solution.
bmp.cache(0, 0, rscTexture.width, rscTexture.height, 1, { useGL: myStage });
The specific and full documentation can be found here:
https://createjs.com/docs/easeljs/classes/BitmapCache.html#method_define

AngularJS: Take a single item from an array and add to scope

I have a ctrl that pulls a json array from an API. In my code I have an ng-repeat that loops through results.
This is for a PhoneGap mobile app and I'd like to take a single element from the array so that I can use it for the page title.
So... I'm wanting to use 'tool_type' outside of my ng-repeat.
Thanks in advance - I'm just not sure where to start on this one.
Example json data
[{ "entry_id":"241",
"title":"70041",
"url_title":"event-70041",
"status":"open",
"images_url":"http://DOMAIN.com/uploads/event_images/241/70041__small.jpg",
"application_details":"Cobalt tool bits are designed for machining work hardening alloys and other tough materials. They have increased water resistance and tool life. This improves performance and retention of the cutting edge.",
"product_sku":"70041",
"tool_type": "Toolbits",
"sort_group": "HSCo Toolbits",
"material":"HSCo8",
"pack_details":"Need Checking",
"discount_category":"102",
"finish":"P0 Bright Finish",
"series_description":"HSS CO FLAT TOOLBIT DIN4964"},
..... MORE .....
Ctrl to call API
// Factory to get products by category
app.factory("api_get_channel_entries_products", function ($resource) {
var catID = $.url().attr('relative').replace(/\D/g,'');
return $resource(
"http://DOMAIN.com/feeds/app_productlist/:cat_id",
{
cat_id: catID
}
);
});
// Get the list from the factory and put data into $scope.categories so it can be repeated
function productList ($scope, api_get_channel_entries_products, $compile) {
$scope.products_list = [];
// Get the current URL and then regex out everything except numbers - ie the entry id
$.url().attr('anchor').replace(/\D/g,'');
$scope.products_list = api_get_channel_entries_products.query();
}
Angular works as following:
Forgiving: expression evaluation is forgiving to undefined and null, unlike in JavaScript, >where trying to evaluate undefined properties can generate ReferenceError or TypeError.
http://code.angularjs.org/1.2.9/docs/guide/expression
so you only need to write:
<title>{{products_list[0].tool_type}}</title>
if there is a zero element the title will be the tool_type, if not, there is no title.
Assuming you want to select a random object from the list to use something like this should work:
$scope.product-tool_type = products_list[Math.floor(Math.random()*products_list.length)].tool_type
Then to display the result just use
<h1>{{product-tool_type}}</h1>
Or alternatively:
<h1>{{products_list[Math.floor(Math.random()*products_list.length)].tool_type}}</h1>