fabric.js: Asynchronously add to group fails - javascript

I am trying to create an abstraction for a loadable group. In this instance, I am using the load svg function to create a arrow to add to the group, but this similarly fails when adding anything to the canvas dynamically.
export class CustomGroup extends fabric.Group {
ready = new BehaviorSubject(false);
constructor(title: string = '') {
super(
[
// Adding something here causes everything to magically work
// new fabric.IText(title)
],
{
left: 500,
top: 250,
originX: 'center',
originY: 'center',
angle: 90,
hasRotatingPoint: false,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
}
);
setTimeout(() => {
// Load an svg or some other stuff dynamically...
// This doesn't show up if I don't add a thing during construction time (above)
this.add(new fabric.Circle({ fill: '#ff0000', radius: 5 }));
this.ready.next(true);
}, 500);
// This fails the same way
// fabric.loadSVGFromString(ARROW_SVG, (svg: fabric.Object[]) => {
// this.add(...svg);
// this.ready.next(true);
// });
}
}
const group = new CustomGroup('test');
group.ready.subscribe((ready) => {
if (ready) {
canvas.add(group);
}
});
When I run this code, my circle shows up fine, but I have to add something to the group beforehand in order to make it work, which is something I don't want to do.
Why won't the add work when I'm using it this way?

Related

How do I reload script using barba transition

javascript is almost new for me and I wanted to use a transition with barba.js.
Unfortunately, I encountered a problem that seems common, once my transition is done, I have to reload the page for the additional scripts to work.
I've been looking for a long time and tried a lot of solutions, but with my level of javascript, I'm not even sure I've typed the code correctly.
I leave my Github project here, if someone is willing to explain to a noob how to write code correctly, I will be eternally grateful.
https://github.com/Jeremmie/punchyparasite_2
const wipe = document.querySelector('.wipe-transition');
const allBandes = document.querySelectorAll('.bande');
const TLAnim = new TimelineMax();
function delay(n) {
return new Promise((done) => {
setTimeout(() => {
done();
}, n)
})
}
barba.init({
sync: true,
transitions: [
{
async leave() {
const done = this.async();
TLAnim
.to(allBandes, { height: '100%', stagger: 0.05 })
// TLAnim.to(wipe, {left: '0%', ease: "power2.out", duration: 0.5});
await delay(1500);
done();
},
enter() {
// TLAnim
// .to(wipe, {left: '100%', ease:"power2.in", duration: 0.5})
// .set(wipe, {left: '-100%'})
TLAnim
.to(allBandes, { height: '0%', stagger: 0.05 })
}
}
]
})

How to properly re-layout a graph and center on a node

I'm using cytoscape to dynamically create a network visualisation and I'm having trouble to setup the layout correctly.
Occasionally, a collection of nodes is created and attached to a parent node.
Then I call the following function to layout the new nodes and center the graph on that parent:
static DoLayout(node) {
setTimeout(() => {
cy.layout({
name: 'cose',
fit: false,
nodeRepulsion: function (node) { return 99999; },
componentSpacing: 100,
padding: 100,
randomize: false,
animate: 'end',
animationEasing: 'ease-in-out',
animationDuration: 350,
stop: () => {
setTimeout(() => {
cy.zoom(.8)
cy.center(node);
}, 100);
}
})
.run();
}, 50);
}
And here's the issue:
Is there a possibility to have these three actions layout, center and zoom happen at the same time? Or smoothly?
Edit: (fit: true,)
Setting fit to true, as suggested by canbax, solves the 'flickering' issue shown in the gif. However it still doesn't produce a smooth transition (animation?) when zooming and centering. Plus, I don't want the graph to be completely zoomed-out then zoomed-in and centered.

Hide / Remove Specific GoogleMapsOverlay From Google Map

I have used geojson files into google map by multi selection . but when i try to remove overlay , it is not working .this is my code to used for add and remove.
i need to know how to remove selected geojson file from map
var deckOverlay ;
deckOverlay = new deck.GoogleMapsOverlay({
layers: [
new deck.GeoJsonLayer({
id: 'layerId',
data: 'path of geojson file',
filled: true,
pointRadiusMinPixels: 2,
opacity: 0.5,
pointRadiusScale: 2000,
getFillColor: f => (f.properties.COLOR),
wireframe: true,
pickable: true,
}), +
new deck.ArcLayer({
id: 'arcs',
data: Layer_Id,
dataTransform: d => d.features.filter(f => f.properties.scalerank < 4),
getSourcePosition: f => [-0.4531566, 51.4709959], // London
getTargetPosition: f => f.geometry.coordinates,
getSourceColor: [0, 128, 200],
getTargetColor: [200, 0, 80],
getWidth: 1
})
]
});
if (checked) {
deckOverlay.setMap(map); // Set multiple overlays working
}
else {
deckOverlay.setMap(null); // Remove Option Not Working
deckOverlay = null;
}
By using Data Layer .
To load map
map.data.loadGeoJson(Layer_Id);
To Remove Specific Layer
map.data.forEach(function (feature) {
if (feature.getProperty('myprop') == myprop) {
map.data.remove(feature);
}
});
To Remove All Layers
map.data.forEach(function (feature) {
map.data.remove(feature);
});
FYI , use color codes as HEX in json file not RGB or RGBA

Cropper.js at angular 2: cropper displays the previos image

I build ionic2 application - based on angular 2.
In my app I use Cropper.js library for let user edit the images he loaded.
Now I have a problem.
When user load new picture, I show it at the main container and open the crop-box for this image.
But the crop-box show the previous image which was at the container.
The only solution that worked for me is to open the crop by setTimeout, but it is not good solution, as we know.
Any idea else?
Here is my code:
HTML - the container element:
<div class="selected-image">
<img *ngIf="currentImage.src != null" #selectedPhoto [src]="currentImage.src"/>
</div>
Now, after user click a button to add picture from the camera (by cordova plugin), and I get the image url, I push the picture to pictures array and then set currentImage variable to hold the new image.
Here is my typeScript code, it also have viewChild to hold the container.
Notice to the setTimeout block, now its is work but if I unwrap the code from setTimeout wrapper - it open the crop-box with the previous picture.
I also tried to change it to NgZone.run wrapper, but it didn't help.
export class myClass {
#ViewChild('selectedPhoto') input: ElementRef;
pictures: PictureData[] = new Array();
mainImage: PictureData = new PictureData();
private cropper: Cropper;
constructor(public _zone: NgZone) {}
function addPicture(){
var self = this;
Camera.getPicture({
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
quality: 95,
targetHeight: 400,
targetWidth:400
}).then((imageURI) => {
var picture = {src:imageURI};
self._zone.run(() => {
self.pictures.push(picture);
self.currentImage = picture;
setTimeout(() => {
if (this.cropper && this.cropper['canvas']) {
this.cropper.destroy();
}
if (!this.cropper || !this.cropper['canvas']) {
this.cropper = new Cropper(this.input.nativeElement, {
aspectRatio: 1 / 1,
dragMode: 'crop',
modal: true,
guides: false,
center: true,
highlight: false,
background: false,
autoCrop: true,
autoCropArea: 0.9,
responsive: true,
checkCrossOrigin: false,
crop: (e: Cropper.CropperCustomEvent) => {
}
});
}
}, 2000);
});
});
}
}
P.S. If you are user with more then 1500 reputation, please, think about create new tag for 'cropper.js'.

How to add href inside node in Gojs?

I created a diagram with GoJS.
I need that every node will contain a href.
var template = GO(go.Node, "Auto", {
desiredSize: new go.Size(width, height)
},
GO(go.Shape, shapeMap.getValue(shape), new go.Binding("fill", "fill")),
GO(go.TextBlock, {
textAlign: 'center',
margin: 4
}, new go.Binding("stroke", "color"), new go.Binding("text", "text")));
var node = {
key: src,
color: textColor,
fill: backgroundColor,
category: shape,
text: "www.google.com"
};
diagram.model.addNodeData(node);
I tried to insert a Html content.
var node = {
key: src,
color: textColor,
fill: backgroundColor,
category: shape,
text: <a href='www.google.com'>href</a>
};
But it's not working. How can I do that?
A TextBlock does not render HTML, but just a string as a block of text.
If you put the URL in your node data, you can declare a GraphObject.click event handler that opens a window.
GO(go.Node, . . .
{
click: function(e, obj) {
window.open("http://" + encodeURIComponent(obj.part.data.url));
}
},
. . .
GO(go.TextBlock,
{ textAlign: "center", margin: 4 },
new go.Binding("stroke", "color"),
new go.Binding("text", "url"))
),
. . .
)
This is for node data such as:
{ url: "www.example.com" }
You can use a conversion function on the TextBlock.text binding to show a different string than the data.url property value.
It is also demonstrated by the sample at http://gojs.net/latest/samples/euler.html
Add click event to the TextBlock, and in the click function - open new web page.
GO(go.Node,...
GO(go.TextBlock,{textAlign: 'center', click: function(e, obj) {window.open(obj.part.data.url)}}),...);

Categories