Gravit Designer discussion

How to manually fire an update event to the canvas?

Is there a way to manually update the canvas through code? For example, when adding rectangles to the canvas within a for loop; it only gets added once the for loop has finished running. I’m trying to add them while the for loop is running.

Any help is appreciated! :slight_smile:

Hi @SachinthaGunaratne, in order to accomplish that you need to control it yourself. Gravit Designer is a web-based application, which means that both Javascript and DOM share the same thread, so you need to “stop” the Javascript execution for a while in order to allow the DOM to update the view. Basically, the elements are rendered as soon as you add them, but they will only show on your screen when the Javascript execution ends. You can use animation frames to allow the DOM to update itself. Here’s a small example:

var i = 0; //number of rectangles to be added
var numElements = 10;
var frame = null; //animation frame
function step() {
    //instantiate a new rectangle using the GRectangle class of the framework
    var rectangle = new GRectangle();

    //it will be added in the position x: 0, y:0, with width: 50, height: 50
    rectangle.setBounds(i * 50, i * 50, 50, 50);

    //elements by default are created without fill, so lets add one FillPaintLayer from GStylable
    rectangle.getPaintLayers().appendChild(new GStylable.FillPaintLayer(new GRGBColor([235,235,235]), 1.0));

    //finally, lets add the new element to the active page
    gDesigner.getActiveDocument().getEditor().getScene().getActivePage().appendChild(rectangle);

    i++;

    //if added the desired number of elements, stop the animation frame
    if (i === numElements) {
        window.cancelAnimationFrame(frame);
        return;
    }

    //keep calling animation frame until it is stopped
    frame = window.requestAnimationFrame(step);
}
  
frame = window.requestAnimationFrame(step);

On this example, I’ve used animation frames to add 10 rectangles to the screen. This way, each rectangle will be rendered on the DOM before the next rectangle is added. Hope it helps!

1 Like

Although I had a little coding experience; never knew about this. Thanks for your detailed reply. Worked perfectly! BTW, is there an easy way to get the selected element rather than traversing all page elements and looking for _flags to check whether it is selected?

Glad to hear it worked. Yes, you can call gDesigner.getActiveDocument().getEditor().getSelection()
This will return an array with all elements you have selected in the current active document.

I tried it, but how can I get and set shape properties such as size, color, position from the selection. So far I have been able to manipulate paths but not shapes. BTW, is it OK to continue this here or should I create separate topics?

Hi. Each element has a set of properties that you can retrieve by calling element.getProperty(property) or change by using the method element.setProperty(property, value). For example, if you want to change the visibility of a element, you can call element.setProperty("vis", true/false). For other properties, like fill and borders you can check the paintLayers (element.getPaintLayers()), that can be FillPaintLayers or BorderPaintLayers, and for size and position you can call element.getGeometryBBox() and use GravitDesigner.framework.core.GTransform and the function element.transform to update the element matrix and apply transformations to it. Hope it clarifies a bit, and you can continue sending your questions here, no problem at all :slight_smile:

1 Like

I’m not quite sure how to set values for paint layers and element transforms. I was able to get the current colour values using element.getPaintLayers().getFillLayers()[0].getProperty('_pt').getValues() (_pt for pattern? I might be accessing the wrong variable and doing it completely wrong.) but no setProperty function is available for it. I’m confused on element transformation part. For which and how should I pass a transformation matrix?

About the paint layers, to set the color of a fill layer to black, you can do this (similar with what you already did):
fillLayer.setProperty("_pt", new GravitDesigner.framework.core.GRGBColor([0,0,0])).

About transformations, you need to take the current transformation matrix and multiply it with a new one to be able to apply new transformations for it. A few examples below:

Moving elements a specific amount:
element.transform(new GravitDesigner.framework.core.GTransform().translated(x,y));, where x and y represent the amount you want to move the element horizontally and vertically.

Moving elements to a specific position:
var bbox = element.getGeometryBBox();
element.transform(new GravitDesigner.framework.core.GTransform().translated(x - bbox.getX(), y - bbox.getY()));, where x and y are the new position of the element. You also need the bounding box of the element, which can be retrieved by using getGeometryBBox function.

Scaling elements
element.transform(new GravitDesigner.framework.core.GTransform().translated(-bbox.getX(),-bbox.getY()).scaled(sx, sy).translated(bbox.getX(), bbox.getY())), where sx and sy are the scale you want to apply to the element. For example, if sx = 2, then the new width of the element will be the double of the current

Setting specific size of elements
element.transform(new GravitDesigner.framework.core.GTransform().translated(-bbox.getX(),-bbox.getY()).scaled(sx/bbox.getWidth(),sy/bbox.getHeight()).translated(bbox.getX(), bbox.getY())), where sx and sy are the new dimensions you want for the element.

Hope that clarifies a bit those features.

1 Like

Thanks a lot for the detailed answer. I will get back when I have more questions.

Hi @denner.erthal! Back with some more questions. :sweat_smile:

  1. Is there a way to get the exact coordinates of a active page from the canvas?
  2. How to properly add the gPatternChooser to a gPropertyRow?
  3. Is it possible to avoid a layer being added to the layer panel when an object is created or is there a way to name a group via the GGroupAction?

Hi @SachinthaGunaratne,
Sorry for the late response.

  1. You can get this information by the Geometry bounding box.
let pageCoordinate = gDesigner.getActiveDocument().getScene()
        .getActivePage().getGeometryBBox();
  1. Here is an example of how you can do it.

    // Import some classes from Gravit Framework (Keep it in the header).
    const {GColor, GLinearGradient, GRadialGradient} = GravitDesigner.framework.core;

    $('<div></div>')
        .gPropertyRow({ //start propertyrow object.
            label: 'Color', // Optional label, you can remove it, if you want.
            columns: [ // start array of column object.
                { // start column object.
                    width: '100%', // the column's width.
                    content: $('<div></div>') // the content itself that will be inside of the column layout.
                        .gPatternChooser({
                            types: [GColor, GLinearGradient, GRadialGradient], // the list patterns that will be available to choose.
                        })
                        .on('patternchange', (evt, pattern, opacity, temporary) => { // The event that will be called for any pattern changed.
                            console.log(pattern);   // the selected {GPattern} pattern
                            console.log(opacity);   // the {Number} opacity of the selected pattern.
                            console.log(temporary); // Whether this new pattern is a temporary value or not.
                                                    // Normally temporary patterns will be triggered during the edition.
                                                    // Non temporay patterns will be the final value. 
                        })
                } // end column object.
            ] // end array of column object.
        }) // end propertyrow object.
        .appendTo(myDiv); //append this propertyrow somewhere.
  1. you can update the name of any shape like this:
layer.setProperty('name', 'myName');

Let me know if you have any questions about it.

Best regards!

Hi @MatheusNetto.

Thanks for your reply. But there seems to be some confusion.

  1. By exact coordinates I meant it should account for offsets from the window. By getGeometryBBox(), I can only get coordinates based on ruler. So is there a way included in the API to get this information?
  2. I already figured out how to implement it before posting the question. But when clicking on it for the first time only the header part of the panel is displayed. After clicking the color icon it works afterwards. So I thought I must have messed with the implementation. Maybe because it isn’t associated with any element?
    BTW, is bubbling and capturing of patternchange event blocked? So far, it’s the only thing that I can’t attach a custom event.
  3. I wanted to name a group in the layers panel through the GGroupAction. Or, is there some other way to group without the action?

Hope I have clearly explained. :smiley: