Paperjs group.pivot not setting to new coordinates - javascript

I'm trying to set the pivot point of a group that contains a raster image to the center of the screen to no avail.
Please see my current code here: condesandbox example
Any help will be much appreciated

Based on your code example, I guess that you just have to set the position of your raster to be the view center and its pivot point will automatically be the same by default.
Here is a sketch demonstrating a possible solution.
// Create the raster.
const raster = new Raster({
source: 'http://assets.paperjs.org/images/marilyn.jpg',
// When image is loaded...
onLoad: () => {
// ...place it at center.
raster.position = view.center;
}
});
// Include raster in a group.
const group = new Group(raster);
// Mark center with a circle.
new Path.Circle({
center: view.center,
radius: 10,
fillColor: 'blue'
});
// Scale the group (the pivot point is bounds center by default).
group.scale(0.5);

Related

PaperJS - How to move along path and rotate along the path

The examples shown in here show how to move an object along the path in Paperjs but how do I rotate them correctly along the path?
In the examples shown on the link above, people suggested by using a circle as an example. But once changed to a rectangle new Path.Rectangle(new Point(20,20), new Size(20,20)); you can see that it moves along the path but does not actually rotate in the direction of the path.
How do I calculate the rotation and set it to my object?
In order to calculate the rotation, you need to know the tangent vector to the path at the position of your rectangle.
This can be retrieved with path.getTangentAt(offset) method.
Then, an easy way to animate the rotation of an item is to set item.applyMatrix to false and then animate the item.rotation property on each frame.
Here is a sketch demonstrating the solution.
// Create the rectangle to animate along the path.
// Note that matrix is not applied, this will allow us to easily animate its
// rotation.
var rectangle = new Path.Rectangle({
point: view.center,
size: new Size(100, 200),
strokeColor: 'orange',
applyMatrix: false
});
// Create the path along which the rectangle will be animated.
var path = new Path.Circle({
center: view.center,
radius: 250,
strokeColor: 'blue'
});
// On each frame...
function onFrame(event) {
// ...calculate the time of the animation between 0 and 1...
var slowness = 400;
var time = event.count % slowness / slowness;
// ...and move the rectangle.
updateRectangle(time);
}
function updateRectangle(time) {
// Calculate the offset relatively to the path length.
var offset = time * path.length;
// Get point to position the rectangle.
var point = path.getPointAt(offset);
// Get tangent vector at this point.
var tangent = path.getTangentAt(offset);
// Move rectangle.
rectangle.position = point;
// Rotate rectangle.
rectangle.rotation = tangent.angle;
}

How do I get the center of a circle in paper.js?

I am trying out paper.js and I've made a few circles:
var circle = new Shape.Circle({
center: [100,100],
radius: 50,
strokeColor: 'black',
strokeWidth: 2
});
This draws a circle with center [100,100] (which could also be a point: Point({x:100, y:100});) and radius 50. This is great, this is a circle.
If I want to get the radius of a circle, I can do this:
circle.radius; // returns 50
But I don't know how to get the center back again. Part of the reason I guess is that Shape.Circle returns a Shape object, which does not have a center parameter (documentation here), but surely I can get this point back somehow. Does anyone know how?
Since circles are centred on the position they're created at, you can get the position (as a Point) and the x and y values from that:
var circle = new Shape.Circle({
center: [100,100],
radius: 50,
strokeColor: 'black',
strokeWidth: 2
});
console.log(circle.position.x, circle.position.y); //100 100
From http://paperjs.org/reference/shape/#position
While the circle object does not have a center property, if you read the docs properly you will find that it does have a bounds property.
In graphics, a "bound" is the rectangle that fully contains your object. So for a circle, the bounds will be a rectangle that touches the circle on the left, right, top and bottom. Therefore the center of the bound is the center of the circle (note: this is not always true for all objects depending on your definition of "center").
Paper.js will give you:
circle.bounds.x
circle.bounds.width
circle.bounds.y
circle.bounds.height
Therefore the center of the circle is:
var centerX = circle.bounds.x + circle.bounds.width/2;
var centerY = circle.bounds.y + circle.bounds.height/2;
Note: You will have to try this out yourself as I have zero experience with paper.js. I just read the docs
Use :
circle.center[0] and circle.center[1]
cause its an array
<script>
var circle = {
center: [100,100],
radius: 50,
strokeColor: 'black',
strokeWidth: 2
};
console.log(circle.center[0]);
</script>
Update:
Sorry, I haven't read your question properly.
You can use circle.position to get the position of center.

OpenLayers adding circle feature with same vectorSource increases opacity of all

Background
Specs
OpenLayers 4.4.1
OSM
I'm fairly new to OpenLayers and have never used vectors before (primarily because I found out that I was using OpenLayers version 1, and had to relearn everything).
My application adds circles to a map relating to a position with a specific radius indicating position accuracy.
In its operation, multiple circles are added to the map at different times.
This is my code for loading the map:
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'mapdiv',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: new ol.View({
//center: [0, 0],
zoom: 16
})
});
//this is where all map 'features' (circles) are stored
var vectorSource = new ol.source.Vector({
projection: 'EPSG:4326'
});
As you can see, I load the 'vector source' right after the map as I understood that it holds all 'vectors' which are displayed on the map so long as you specify it as the 'source'.
This is the code I use to generate the circle (source) (I tweaked it at getPointResolution because the OP made a mistake):
//code from https://stackoverflow.com/a/28299599
function addCircle(map, vectorSource, radius) {
var view = map.getView();
var projection = view.getProjection();
var resolutionAtEquator = view.getResolution();
var center = view.getCenter();
var pointResolution = ol.proj.getPointResolution(projection, resolutionAtEquator, center);
var resolutionFactor = resolutionAtEquator/pointResolution;
var radius = (radius / ol.proj.METERS_PER_UNIT.m) * resolutionFactor;
var circle = new ol.geom.Circle(center, radius);
var circleFeature = new ol.Feature(circle);
// vector layer
vectorSource.addFeature(circleFeature);
var vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addLayer(vectorLayer);
}
Problem
Loading one circle goes normally, adds a blue stroked, opaque circle at the specified location with specified radius.
Loading a second circle appears more opaque than the last. Moving the map to the previous circle, it is also more opaque.
With each added circle, the apparent opacity increases for all displayed circles.
Running vectorLayer.getOpacity() in every circle generation results in 1, when clearly the circle is translucent, becoming increasingly opaque with every new circle.
Summary
Looking around, it appears that often it is the case that the developer is reloading the same circle over and over until many are stacked on top of one another. It almost seems like this is the case for me too, except I've triple-checked that I'm only running addCircle() once and the circle is in a different position than the last.
Is it possible that OpenLayers is redrawing all previous circles with every new circle?
Maybe this isn't related to getOpacity but has to do with the color as an rgba() combination...
Question
I want every circle to remain the same after drawing new circles. The default opacity and color is fine.
Am I doing something wrong?
Here's a fiddle as an example - https://jsfiddle.net/f5zrLt20/5/
Define the layer when defining the vectorSource:
var layer = null;
//this is where all map 'features' (circles) are stored
var vectorSource = new ol.source.Vector({
projection: 'EPSG:4326'
});
And check if it exists on creating a new circle:
// If layer is not yet set, create new layer and add it to map
if (!layer) {
vectorSource.addFeature(circleFeature);
layer = new ol.layer.Vector({
source: vectorSource
});
map.addLayer(layer);
}
//Otherwise, just add feature to the source
else {
layer.getSource().addFeature(circleFeature);
}

Adding an animated arrow on an offset Leaflet polyline

I have a project which consist in visualizing the exchange of data between points on a map.
I'm using Leaflet to draw polylines from coordinates in a GeoJson file and Leaflet.polylineDecorator (https://github.com/bbecquet/Leaflet.PolylineDecorator) to put an animated arrow on the polyline.
The thing is that I need to visualize the stream in both directions. I started by adding to my Geojson file polylines in the other direction but the issue is when I zoom out, the two polylines are stacked.
So I found Leaflet.polylineOffset (https://github.com/bbecquet/Leaflet.PolylineOffset) which allows to create an another polyline just by setting the offset option.
I thought, i just had to do the same to put the animated arrow on it but when i'm doing it, the animation is affected to the original polyline. In fact, the offset polyline keeps the coordinates from the original one.
I wanted to know if there is a way to apply this animation to the offset polyline.
Here is my code:
d3.json("data/trajetsFibreDCSigma.json",function (data){ // getting polylines' data from a json file to add them on the map
L.geoJson(data, {
style: function(feature){return {color : feature.properties.stroke,opacity: 1};}, // setting the style of the polylines
onEachFeature: function(feature){
// getting the coordinates of the polyline from the json file
var latlng = feature.geometry.coordinates;
var size = feature.geometry.coordinates.length;
var buffer;
// reversing the order of latitude and longitude in the array because a L.latLng object needs the latitude first and I have the opposite in my json file
for (i=0;i<size;i++)
{
buffer = latlng[i][0];
latlng[i][0] = latlng[i][1];
latlng[i][1] = buffer;
}
var polylineOffset = L.polyline(latlng,{offset: 5,color: 'blue',opacity: 1}).addTo(map); // putting an offset to the polyline
addArrow(latlng,feature);
addArrow(polylineOffset,feature);
}
}).addTo(map);
});
function addArrow(polyline,feature){ // function to add an arrow on the map
var arrowHead = L.polylineDecorator(polyline).addTo(map); // creating an arrow which will be put on the polyline
var arrowOffset = 0;
window.setInterval(function() { // creating an animation for the arrow to cross the polyline
arrowHead.setPatterns([
{offset: arrowOffset+'%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false,
pathOptions: {stroke: true,color: feature.properties.stroke,opacity: 1}})}
]);
if(++arrowOffset > 100)
arrowOffset = 0;
}, 100);
}
(If I'm just calling addArrow with the offset polyline, it will pop on the original one).
I found a solution to get the offset polyline's coordinates.
The PolylineOffset plugin has a function which returns the offset coordinates.
You can use it like this:
var pts = L.PolylineOffset.offsetLatLngs(latlng,10,map); // getting the coordinates from the offset polyline
where latlng is the array of the original coordinates
; 10 is the offset
; map is your leaflet map

GoogleMaps V3 Only Displays 1 Polygon

have a web page which displays weather charts from many sources. You pick your source and outlines of the charts appear on a Google Map. (See http://www.geoffschultz.org/weather_map.php Weather Charts/GMDSS/Forecasts - should draw 3 polygons) Up until now all of the charts have been rectangular, but I just came across the need for non-rectangular charts. I had coded the js with this in mind, but I have been baffled because only the last polygon drawn is displayed. Is there something that I'm missing with regards to multiple polygons?
The code is very simple. It gets an array of bounding box coordinates. For simple rectangles the array element looks like "-31,-32|2,25" and for polygons it just has more coordinates separated by "|". If there are 2 coordinates, I draw a rectangle, otherwise I draw a polygon, closing it with the 1st point.
What am I doing wrong as it works great for rectangles?
-- Geoff
for (i in bb[selValue])
{
bb_lat_long = bb[selValue][i]["bb_lat_long"].split("|");
if (bb_lat_long.length == 2) //Rectangle
{
lat_long = bb_lat_long[0].split(",");
sw = new google.maps.LatLng(lat_long[0], lat_long[1]);
lat_long = bb_lat_long[1].split(",");
ne = new google.maps.LatLng(lat_long[0], lat_long[1]);
bounds = new google.maps.LatLngBounds(sw, ne);
bounding_box = new google.maps.Rectangle({map: map, bounds: bounds, fillOpacity: 0.05, strokeWeight: 1});
}
else // polygon
{
poly_lat_long.length = 0;
for (j = 0; j < bb_lat_long.length; j++)
{
lat_long = bb_lat_long[j].split(",");
poly_lat_long.push(new google.maps.LatLng(lat_long[0], lat_long[1]));
}
lat_long = bb_lat_long[0].split(",");
poly_lat_long.push(new google.maps.LatLng(lat_long[0], lat_long[1])); // close polygon with 1st point
bounding_box = new google.maps.Polygon({map: map, paths: poly_lat_long, fillOpacity: 0.05, strokeWeight: 1});
}
}
My suspicion is that it has to do with re-using the path in the new polygons (you are ending up with multiple polygons, the just all are the same, perhaps if you declare poly_lat_long locally (with var), or make a createPolygon function that would get function closure on the path.
I have seen this behavior before when clearing the path array using poly_lat_long.length = 0;
rather than creating a new array (poly_lat_long = []).
Thread from the Google Maps API v3 group discussing similar problem

Categories