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
New Features:
- Add tooltip support to Svg Elements (#23)
- Released
- 2024-07-29
- Maturity
- TESTED
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 24
- Vaadin 23+ in 1.2.0
- Vaadin 14+ in 1.0.1
- Browser
- N/A
Svg Component - Vaadin Add-on Directory
Allows the creation of SVG elements from the server sideView on GitHub
Issue tracker
Svg Component version 1.0.1
v 1.0.1:
- Fixes issue with drag where the drag in some cases would never end
- Fixes issue where calling setDraggable(true) before calling svg.add() and then calling svg.update() caused the component to not actually be draggable.
v 1.0.0: Initial release:
- Initial component API and Element APIs
- Supports 9 SVG elements (see demo)
- Drag and Drop listener support
- Extendable server-side API
Svg Component version 1.0.2
Changes since __v1.0.1__:
- Updated the web component to [__v1.0.4__](https://vaadin.com/directory/component/vaadin-component-factoryvcf-svg), fixes `viewbox` method.
- Added `panTo` method.
Svg Component version 1.0.3
Update the license to Apache 2.0
Svg Component version 1.0.4
The license checker was still active in v1.0.3.
Remove the license checker
Svg Component version 1.1.0
Add a click listener to the component
Svg Component version 1.1.1
Fix an error when the component was used in a dialog
Svg Component version 1.2.0
Update to Version 23
Svg Component version 1.2.1
Update to support Version 24
Svg Component version 1.1.2
* Update web component dependency to 1.0.9 to fix svgjs dependency issue.
Svg Component version 2.0.0
#### New Features:
* Add tooltip support to Svg Elements ([#23](https://github.com/vaadin-component-factory/svg/issues/23))