简体   繁体   中英

GXT3: How to implement svg buttons

Using SVG icons has a lot of advantages over png/gif icons. As a result, I would like to implement a svg button class to act as a gwt widget. Is there already something existing in GXT 3? Or what would be the best option to implement such a widget? Thanks.


More Details:

I need a pure clickable svg icon act like a button widget. It needs to have mouse click handler and the ability to apply different css in three states: normal, hover, disabled. I do not want a button with a svg icon inside.

In browsers that support them, SVG can be used as if it was an image file (png/jpg/etc). GXT/GWT shouldn't make a difference, you just have to apply the image.

Rather than building your own widget (which is, of course, an option), you can use built-in widgets that can be told to use any image or css class (depending on the widget).

For example, GXT's TextButton has a setIcon method which takes an ImageResource . Typically these are created in a ClientBundle , but the code generation for GWT's ClientBundle doesn't know what SVG is.

The ImageResource interface has an implementation built in to GWT, ImageResourcePrototype , allowing you to specify all of the parameters required. The second parameter is a url, the path to an image, which will be rendered as long as the browser supports it. So, we need to get the SVG file you want to use into the ImageResourcePrototype.

    ImageResource icon = new ImageResourcePrototype("icon", UriUtils.fromSafeConstant("/path/to/my.svg"), 0, 0, 20, 20, false, false);
    TextButton button = new TextButton("square", icon);
    RootPanel.get().add(button);

Now, you can do this by just passing in a normal URL, but then we're no better than a normal image, since we still need a round trip to the server - most icon buttons are only a few kb, but the overhead of an HTTP call can be that bad, so your SVG will be just as bad. Thankfully all built-in ImageResource s in GWT are already bundled into the app, so no HTTP calls are needed. It turns out we can also bundle our svg file, though we need to get it just right for the browser to handle it.

Put the SVG file in your source with your Java, and we'll make a bundle out of it. I put this very boring icon into a file called icon.svg :

<svg width="50" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">

  <rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
</svg>

Next, use it in our app. I made an entrypoint that just grabs this icon and puts it into a button. We use DataResource here to refer to the file as a data url from inside our app, but we need to specify the mime-type correctly for the browser to understand that it is an image:

public class SampleIconEntryPoint implements EntryPoint {
    interface Bundle extends ClientBundle {
        @Source("icon.svg")
        @MimeType("image/svg+xml")
        DataResource icon();
    }

    @Override
    public void onModuleLoad() {
        Bundle bundle = GWT.create(Bundle.class);
        ImageResource icon = new ImageResourcePrototype("icon", bundle.icon().getSafeUri(), 0, 0, 50, 50, false, false);
        TextButton button = new TextButton("square", icon);
        RootPanel.get().add(button);
    }
}

带有SVG图标的渲染按钮


This could be made easier by adding support for .svg files to the ImageResourceGenerator in GWT, but this turns out to not be a very common use case.


Okay, so what does SVG have over raster images? For large images, a lot! They can be much smaller for the same level of detail since they stretch nicely, but for small icons, it can be hit or miss. It is easier to change some details about them on the fly, but that's really outside the scope of a question addressing how to use SVG in gwt (see GXT's chart/draw library for lots of easy SVG render tools), and doesn't often matter for a single image on a button. Icon images are small, and saving a few bytes here and there is probably not an efficient use of time - plus, SVG takes more time to render in the browser than much-simpler images (though again, the difference will be minimal for very small browsers).


Edit, trying to address the question edit instead of the original point.

SVG elements are nearly normal dom elements, though check what browsers you need to support to ensure that they will work correctly. https://developer.mozilla.org/en-US/docs/SVG_In_HTML_Introduction gives a quick introduction on how the elements need to be built to correct namespace them so that the browser will work with them correctly. Beyond that, they behave roughly as normal dom elements in GWT. I would generally suggest that you treat them like normal dom elements in GWT, and so your widget should not attach handlers to child elements but just use addDomHandler as normal on each widget. Given the ability of svg elements to overlap each other (based on order in the dom), you might consider other ways of seeing which element is on top of others if you need to know exactly what the mouse is over (though for a button, this shouldn't matter).

As mentioned above, GXT's draw tools provide a DrawComponent class which can use SVG and let you get events that happen to each drawn sprite, plus normalize for different browser issues (support canvas if possible, or VML if necessary).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM