Svg Component
Allows the creation of SVG elements from the server side
Overview
The Vaadin Component Factory SVG component is a wrapper around svg.js that allows creation of simple and complex SVGs from the Vaadin server-side code.
Usage
Add the dependency to your project (see sidebar in directory). Create a new Svg component and add an SvgElement element into it (see code examples)
Client-side implementation
This is the server-side (Java) API for the Vaadin Platform for the vcf-svg component. Looking for the client-side version? It can be found here: https://vaadin.com/directory/component/vaadin-component-factoryvcf-svg
License & Author
This Add-on is distributed under Apache 2.0
Component Factory Svg is written by Vaadin Ltd.
Sponsored development
Major pieces of development of this add-on has been sponsored by multiple customers of Vaadin. Read more about Expert on Demand at: Support and Pricing
Sample code
Svg draw = new Svg(); Rect rect = new Rect("rect", 100, 100); Circle circle = new Circle("circle", 50); rect.move(75, 0); rect.size(150, 150); circle.center(150, 75); circle.setRadius(75); circle.setFillColor("#396"); draw.add(rect); draw.add(circle);
VerticalLayout demoContainer = new VerticalLayout(); HorizontalLayout controlButtons = new HorizontalLayout(); demoContainer.add(controlButtons); Span dragDetail = new Span(); demoContainer.add(dragDetail); Svg svg = new Svg(); svg.viewbox(0, 0, 380, 380); svg.setWidth("100%"); svg.setHeight("500px"); double size = 100; double space = size + 20; double x = 20; double y = 20; String fillColor = "#ff0066"; //Rect Rect rect = new Rect("rect1", size, size); rect.setFillColor(fillColor); rect.move(x, y); svg.add(rect); //Circle double circleRadial = size / 2; Circle circle = new Circle("circle1", circleRadial); circle.setFillColor(fillColor); circle.move(x += space, y); svg.add(circle); //Ellipse Ellipse ellipse = new Ellipse("ellipse1", circleRadial, circleRadial * 0.5); ellipse.setFillColor(fillColor); ellipse.move(x += space, y); svg.add(ellipse); //Line Line line = new Line("line", new AbstractPolyElement.PolyCoordinatePair(x = 20, y += space), new AbstractPolyElement.PolyCoordinatePair(x + size, y + size)); line.setStroke(fillColor, 10, Path.LINE_CAP.ROUND, null); svg.add(line); //Polyline List<AbstractPolyElement.PolyCoordinatePair> points = new ArrayList<>(); points.add(new Polyline.PolyCoordinatePair(50, 0)); points.add(new Polyline.PolyCoordinatePair(60, 40)); points.add(new Polyline.PolyCoordinatePair(100, 50)); points.add(new Polyline.PolyCoordinatePair(60, 60)); points.add(new Polyline.PolyCoordinatePair(50, 100)); points.add(new Polyline.PolyCoordinatePair(40, 60)); points.add(new Polyline.PolyCoordinatePair(0, 50)); points.add(new Polyline.PolyCoordinatePair(40, 40)); Polyline polyline = new Polyline("polyline", points); polyline.setFillColor("none"); polyline.setStroke(fillColor, 4, Path.LINE_CAP.ROUND, Path.LINE_JOIN.ROUND); polyline.move(x += space, y); svg.add(polyline); //Polygon Polygon polygon = new Polygon("polygon", points); polygon.setFillColor(fillColor); polygon.move(x += space, y); svg.add(polygon); //Path Path path = new Path("path", "M0 0 H50 A20 20 0 1 0 100 50 v25 C50 125 0 85 0 85 z"); path.setFillColor("none"); path.setStroke(fillColor, 4, Path.LINE_CAP.ROUND, Path.LINE_JOIN.ROUND); path.move(x = 20, y += space); svg.add(path); //Text Text text = new Text("text", "Sample text."); text.setFontFamily("'Roboto', 'Noto', sans-serif"); text.setFillColor(fillColor); text.move(x += space, y); svg.add(text); //Image Image image = new Image("image", "https://vaadin.com/images/hero-reindeer.svg"); image.size(size, size); image.move(x += space, y); image.setDraggable(false); svg.add(image); demoContainer.add(svg); //Add control buttons controlButtons.add(new Button("Toggle Zoom", e -> { svg.setZoomEnabled(!svg.isZoomEnabled()); })); controlButtons.add(new Button("Toggle draggable", e -> { svg.getSvgElements().forEach(el -> el.setDraggable(!el.isDraggable())); svg.getSvgElements().forEach(el -> { // Due to the nature of how the polygons are written (M0 0), // if we do an update to them they will move back to 0,0. // Hence, we have to move them back to their desired // location when we do an update. if (el == polyline) { el.move(20 + space, 20 + space); } if (el == polygon) { el.move(20 + space * 2, 20 + space); } svg.update(el); }); })); controlButtons.add(new Button("Stroke black", e -> { svg.getSvgElements().forEach(el -> el.setStroke("#000000", 4, Path.LINE_CAP.ROUND, Path.LINE_JOIN.ROUND)); svg.getSvgElements().forEach(el -> { // Due to the nature of how the polygons are written (M0 0), // if we do an update to them they will move back to 0,0. // Hence, we have to move them back to their desired // location when we do an update. if (el == polyline) { el.move(20 + space, 20 + space); } if (el == polygon) { el.move(20 + space * 2, 20 + space); } svg.update(el); }); })); controlButtons.add(new Button("Display drag events", e -> { svg.addDragStartListener(event -> { Notification.show("Drag start: " + event.getElement().getId(),2500, Notification.Position.MIDDLE); dragDetail.setText("Drag Start for: " + event.getElement().getId() + " X: " + event.getElementX() + " Y: " + event.getElementY()); }); svg.addDragEndListener(event -> { Notification.show("Drag End: " + event.getElement().getId(), 2500, Notification.Position.MIDDLE); dragDetail.setText("Drag End for: " + event.getElement().getId() + " X: " + event.getElementX() + " Y: " + event.getElementY()); }); svg.addDragMoveListener(event -> { dragDetail.setText("Drag Move for: " + event.getElement().getId() + " X: " + event.getElementX() + " Y: " + event.getElementY()); // }); e.getSource().setEnabled(false); })); controlButtons.add(new Button("Remove Line", e -> { svg.remove(line); e.getSource().setEnabled(false); }));
//Extend the rectangle to add a missing or new attribute public class MyCustomSvg extends Rect { public MyCustomSvg(String id, double width, double height) { super(id, width, height); } // Ensure that the client-side actually knows how to handle // the attribute or if you made your own extension that // the attribute names match. // For existing client-side attributes look to // https://svgjs.com/docs/3.0/manipulating/#attributes public void setMyCustomAttribute(){ setAttribute("theAttributeToSet", "theValueToSet"); } public String getMyCustomAttribute(){ return getStringAttribute("theAttributeISet"); } }
@Route("ex") public class ExView extends VerticalLayout { public ExView() { MyCustomSvgComponentWithExtendedEventListenerParams svg = new MyCustomSvgComponentWithExtendedEventListenerParams(); add(svg); Circle circle = new Circle("c1", 50); circle.setDraggable(true); svg.add(circle); svg.addDragEndListener(event -> { System.out.println("The width on drag end was: " + event.getRawEventData() .getNumber( "event.detail.handler.el.node.instance.width()")); }); } public static class MyCustomSvgComponentWithExtendedEventListenerParams extends Svg { private static final Logger log =Logger.getLogger( MyCustomSvgComponentWithExtendedEventListenerParams.class.getName()); private DomListenerRegistration dragendDomRegistration; @Override protected void ensureDomDragEndEventListenerRegistered() { //super.ensureDomDragEndEventListenerRegistered(); /* * Copied default implementation from super. */ if (dragendDomRegistration == null) { dragendDomRegistration = getElement().addEventListener("dragend", e -> { onDragEndEvent(e.getEventData() .getString("event.detail.handler.el.node.id"), e.getEventData()); }).addEventData("event.detail.handler.el.node.id") .addEventData("event.detail.handler.el.node.instance.x()") .addEventData("event.detail.handler.el.node.instance.y()"); /* * End of copied default implementation from super */ //Say we want to include the width of the element when the drag ends dragendDomRegistration .addEventData("event.detail.handler.el.node.instance.width()"); } } } }
Links
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
Fix an error when the component was used in a dialog
- Released
- 2021-09-01
- Maturity
- STABLE
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 14+
- Browser
- Firefox
- Safari
- Google Chrome
- Microsoft Edge