I am using react-leaflet lib.
And after rendering marker, I get an error that there is no file.
I had tried to put manually file in root folder of component which creates Marker but then I get fatal error
TypeError: options.icon.createIcon is not a function
Below is whole component code.
import React, { Component } from 'react';
import { Marker, Tooltip, Polygon } from 'react-leaflet';
import L from 'leaflet';
import './style.css';
import icon from './marker.svg';
/**
* #class ./widgets/SeatMap/components/LeafletMap/components/CategoryControl/components/ShapeLayer
*/
class ShapeLayer extends Component
{
/**
* #type {object}
*/
shapes = {};
/**
* Constructor.
*
* #param {object} props
*/
constructor (props)
{
super(props);
this.shapes = props.shapes;
}
/**
* #returns {XML}
*/
render() {
return (
<div className={'ShapeLayer'}>
{
this.shapes['texts'].map(text => {
return (
<Marker key={text['id']} position={text['coordinates']} draggable={false} opacity={0.01} icon={icon}>
<Tooltip direction={"center"} permanent className={'shape-tooltip'}>
<span>{text['text']}</span>
</Tooltip>
</Marker>
);
})
}
{
this.shapes['polygons'].map(polygon => {
return (
<Polygon key={polygon['id']} positions={polygon['coordinates']} fillColor={"white"} color={'gray'} />
);
})
}
</div>
)
}
}
export default ShapeLayer;
How can I solve this issue?
Hi you can't directly using icon like that.
React Leaflet is an "abstraction" of Leaflet so it uses the same functions.
To create custom icons you have to create a divIcon.
For a live example go there:
https://react-leaflet.js.org
Related
I convert HTML to PDF using iText7 and need to add Text Markup Annotations for specific text in the HTML. I am using CustomTagWorkers as explained in this link and then I am using the annotation examples given here.
I am able to successfully add Link Annotation by replacing the qr tag with a link annotation. However my requirement is to add a Text Markup Annotation. The Text Markup annotation can only be drawn by giving the specific coordinates of the page (rectangle object) which I do not know in the code. I tried to give Rectangle(0, 0) hoping that iText will render this in place of tag. However I am unable to add the Text Markup Annotation to paragraph object which is the return object of public IPropertyContainer getElementResult() {.
Here is my entire code:
/**
* Converts an HTML file to a PDF document, introducing a custom tag to create a
* QR Code involving a custom TagWorker and a custom CssApplier.
*/
public class C05E04_QRCode2 {
/**
* The path to the resulting PDF file.
*/
public static final String DEST = "C:\\Samples\\itext-annotation\\qrcode.pdf";
/**
* The path to the source HTML file.
*/
public static final String SRC = "C:\\Samples\\itext-annotation\\qrcode.html";
/**
* The main method of this example.
*
* #param args no arguments are needed to run this example.
* #throws IOException signals that an I/O exception has occurred.
*/
public static void main(String[] args) throws IOException {
File file = new File(DEST);
file.getParentFile().mkdirs();
C05E04_QRCode2 app = new C05E04_QRCode2();
System.out.println("pdf");
app.createPdf(SRC, DEST);
}
/**
* Creates the PDF file.
*
* #param src the path to the source HTML file
* #param dest the path to the resulting PDF
* #throws IOException signals that an I/O exception has occurred.
*/
public void createPdf(String src, String dest) throws IOException {
ConverterProperties properties = new ConverterProperties();
properties.setCssApplierFactory(new QRCodeTagCssApplierFactory())
.setTagWorkerFactory(new QRCodeTagWorkerFactory());
HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}
/**
* A factory for creating QRCodeTagCssApplier objects.
*/
class QRCodeTagCssApplierFactory extends DefaultCssApplierFactory {
/**
* Gets the custom css applier.
*
* #param tag the tag
* #return the custom css applier
*/
/*
* (non-Javadoc)
*
* #see com.itextpdf.html2pdf.css.apply.impl.DefaultCssApplierFactory#
* getCustomCssApplier(com.itextpdf.html2pdf.html.node.IElementNode)
*/
#Override
public ICssApplier getCustomCssApplier(IElementNode tag) {
if (tag.name().equals("qr")) {
return new BlockCssApplier();
}
return null;
}
}
/**
* A factory for creating QRCodeTagWorker objects.
*/
class QRCodeTagWorkerFactory extends DefaultTagWorkerFactory {
/**
* Gets the custom tag worker.
*
* #param tag the tag
* #param context the context
* #return the custom tag worker
*/
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (tag.name().equals("qr")) {
return new QRCodeTagWorker(tag, context);
}
return null;
}
}
/**
* The custom ITagWorker implementation for the qr-tag.
*/
static class QRCodeTagWorker implements ITagWorker {
/** The p. */
private Paragraph p;
/** The annotation. */
private PdfLinkAnnotation linkAnnotation;
/**
* Instantiates a new QR code tag worker.
*
* #param element the element
* #param context the context
*/
public QRCodeTagWorker(IElementNode element, ProcessorContext context) {
}
/**
* Process content.
*
* #param content the content
* #param context the context
* #return true, if successful
*/
#Override
public boolean processContent(String content, ProcessorContext context) {
return true;
}
/**
* Process tag child.
*
* #param childTagWorker the child tag worker
* #param context the context
* #return true, if successful
*/
#Override
public boolean processTagChild(ITagWorker childTagWorker, ProcessorContext context) {
return false;
}
/**
* Process end.
*
* #param element the element
* #param context the context
*/
#Override
public void processEnd(IElementNode element, ProcessorContext context) {
//Link Annotation
linkAnnotation = new PdfLinkAnnotation(new Rectangle(0, 0)).setAction(PdfAction.createURI(
"https://kb.itextpdf.com/"));
Link link = new Link("here", linkAnnotation);
p = new Paragraph("The example of link annotation. Click ").add(link.setUnderline())
.add(" to learn more...");
//Line Annotation
float[] floatArray = new float[] { 169, 790, 105, 790, 169, 800, 105, 800 };
PdfAnnotation lineAnnotation = PdfTextMarkupAnnotation.createHighLight(new Rectangle(0, 0), floatArray);
lineAnnotation.setTitle(new PdfString("You are here:"));
lineAnnotation.setContents("Cambridge Innovation Center");
lineAnnotation.setColor(ColorConstants.YELLOW);
//Text Markup Annotation
PdfAnnotation ann = PdfTextMarkupAnnotation.createHighLight(
new Rectangle(105, 790, 64, 10),
new float[]{169, 790, 105, 790, 169, 800, 105, 800})
.setColor(Color.YELLOW)
.setTitle(new PdfString("Hello!"))
.setContents(new PdfString("I'm a popup."))
.setTitle(new PdfString("iText"))
.setOpen(true)
.setRectangle(new PdfArray(new float[]{100, 600, 200, 100}));
}
/**
* Gets the element result.
*
* #return the element result
*/
#Override
public IPropertyContainer getElementResult() {
return p;
}
}
}
HTML File:
<html>
<head>
<meta charset="UTF-8">
<title>QRCode Example</title>
<link rel="stylesheet" type="text/css" href="css/qrcode.css"/>
</head>
<body>
<span> The example of <qr> text markup </qr> annotation. </span>
</body>
</html>
CSS File:
qr {
border: solid 1px red;
height: 200px;
width: 200px;
}
Illustration of the final output
The easiest pragmatic way to proceed is make your <qr> tag behave as inline-block. This will make sure that we will not have the text from the tag wrap to the next line (in this case annotation is tricky to define), and also we will have a natural grouping element that we will be able to fetch the coordinates from.
I have modified the input HTML slightly, to get rid of <qr> tag in favor of <annot> and add the above mentioned display: inline-block behavior:
<html>
<head>
<style>
annot {
display: inline-block;
}
</style>
</head>
<body>
<span> The example of <annot> text markup </annot> annotation. </span>
</body>
</html>
We proceed with the definition of the custom tag worker factory and custom tag worker in the similar fashion as in the original post:
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if ("annot".equals(tag.name())) {
return new AnnotTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
}
private static class AnnotTagWorker extends PTagWorker {
public AnnotTagWorker(IElementNode element, ProcessorContext context) {
super(element, context);
}
#Override
public IPropertyContainer getElementResult() {
IPropertyContainer baseResult = super.getElementResult();
if (baseResult instanceof Paragraph) {
((Paragraph) baseResult).setNextRenderer(new AnnotTagRenderer((Paragraph) baseResult));
}
return baseResult;
}
}
Now the meaty part will be implemented in AnnotTagRenderer. Notice how we set the renderer to the resultant element in AnnotTagWorker. The renedrer implementation is aware of the physical coordinates of the text block corresponding to our <annot> tag on the PDF page. We can now fetch the coordinates from this.getOccupiedArea() in draw() method and this does the main trick for us - all we need to do as a remainder is create the right annotation object and add it to the page. Here is the implementation:
private static class AnnotTagRenderer extends ParagraphRenderer {
public AnnotTagRenderer(Paragraph modelElement) {
super(modelElement);
}
#Override
public IRenderer getNextRenderer() {
return new AnnotTagRenderer((Paragraph) modelElement);
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle occupiedArea = this.getOccupiedAreaBBox();
float[] quadPoints = new float[] {occupiedArea.getLeft(), occupiedArea.getTop(), occupiedArea.getRight(), occupiedArea.getTop(),
occupiedArea.getLeft(), occupiedArea.getBottom(), occupiedArea.getRight(), occupiedArea.getBottom()};
PdfAnnotation ann = PdfTextMarkupAnnotation.createHighLight(
new Rectangle(occupiedArea), quadPoints)
.setColor(ColorConstants.YELLOW)
.setTitle(new PdfString("Hello!"))
.setContents(new PdfString("I'm a popup."))
.setTitle(new PdfString("iText"));
drawContext.getDocument().getPage(this.getOccupiedArea().getPageNumber()).addAnnotation(ann);
}
}
Visual result looks as follows:
Finally, don't forget to plug the custom tag worker factory into the converter properties:
ConverterProperties properties = new ConverterProperties().setTagWorkerFactory(new CustomTagWorkerFactory());
HtmlConverter.convertToPdf(new File(sourceHTML), new File(targetPDF), properties);
How/can we make number of visibleSlides responsive in CSS? / not have to use JS to alter visibleSlides based on breakpoints.
For example;
Each slide has min-width: 100px; min-height: 100px; ie. image we want to see detail so shouldn't be smaller than 100px.
We set visibleSlides to 8 (for desktop). On mobile we want to show only 2 slides. Because we don't want the individual slides to be less than 100px height and width, nor have the slides overlapping.
I know we could use react to check screen width and set visibleSlides, however it's not easy for all apps to have access to this, especially server side rendered like next.js.
See this sandbox https://codesandbox.io/s/pure-react-carousel-responsive-visible-slides-k8cui
(Forked from https://codesandbox.io/s/withered-wood-4bx36?fontsize=14&hidenavigation=1&theme=dark)
I had that problem for my app and actually couldn't find a way to do this with CSS. However, I've implemented this using ResizeObserver and react-hooks.
P.S. I'm using next js, and it's not a big issue to implement it on the server-side.
Here's my solution, hope it could help.
Step 1. Create an observer hook to listen for resize events from the app.
import { useEffect, useState, RefObject } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
interface DOMRectReadOnly {
readonly bottom: number;
readonly height: number;
readonly left: number;
readonly right: number;
readonly top: number;
readonly width: number;
readonly x: number;
readonly y: number;
}
interface useResizeObserverProperties {
ref?: RefObject<Element> | null;
element?: Element | null | undefined;
callback?: (entry: ResizeObserverEntry) => void;
}
const IS_BROWSER = typeof window !== 'undefined';
/**
* Watch for the resizing of a React component or Element.
*
* #param hookProperties - Configuration optinos for the hook.
*
* #returns The `DOMRect` for the observed element.
*/
export const useResizeObserver = ({
ref,
element,
callback,
}: useResizeObserverProperties) => {
const [sizes, setSizes] = useState<DOMRectReadOnly>({
bottom: 0,
height: 0,
left: 0,
right: 0,
top: 0,
width: 0,
x: 0,
y: 0,
});
const handleResize = (entries: ResizeObserverEntry[]) => {
const [entry] = entries;
if (callback) callback(entry);
setSizes(entry.contentRect);
};
const [resizeObs] = useState(() =>
IS_BROWSER ? new ResizeObserver(handleResize) : undefined,
);
useEffect(() => {
if (!resizeObs) return;
let domNode;
if (ref) {
domNode = ref.current;
} else if (element) {
domNode = element;
}
if (domNode) {
resizeObs.observe(domNode);
}
return () => resizeObs.disconnect();
}, [ref, resizeObs, element]);
return sizes;
};
Step 2. In your component.tsx
import React, { useState, useRef } from 'react';
import { CarouselProvider, Slider, Slide } from 'pure-react-carousel';
import { useResizeObserver } from 'from previously created file';
const YourComponent = () => {
const [visibleSlides, setVisibleSlides] = useState(1);
const ref = useRef<HTMLDivElement>(null);
// Current width of element
const { width } = useResizeObserver({ ref });
switch (true) {
case width > 768 && width < 1280:
setVisibleSlides(2);
break;
/**
* Switch your cases here
*/
}
return (
<div ref={ref}>
<CarouselProvider
naturalSlideWidth={100}
naturalSlideHeight={125}
totalSlides={3}
visibleSlides={visibleSlides}
>
<Slider>
<Slide index={0}>Slide 1</Slide>
<Slide index={1}>Slide 2</Slide>
<Slide index={2}>Slide 3</Slide>
</Slider>
</CarouselProvider>
</div>
);
};
export default YourComponent;
Btw I'll recommend you throttle setVisibleSlides calls to avoid too much re-renders while resizing the window from dev-tools.
not an answer, but i'm trying to do the same.
How about using React hooks useState for the visibleSlides integer, and creating a window listener that listens for breakpoints and changes the state as needed....
How about setting a state and using useEffect to update the state on resize of window, then passing down the window size as a prop to the carousel component and choosing the number of visibleslides using the prop?
https://codesandbox.io/s/pure-react-carousel-responsive-visible-slides-forked-q29c1d?file=/src/App.js
Has anyone been able to use the React Leaflet Popup element to show a popup on mouseover rather than on click?
I can't seem to find a way to achieve this.
I've recently solved this problem using React Refs and the Leaflet API.
A barebones example:
import React, { Component } from 'react';
import { Circle } from 'react-leaflet';
class Foo extends Component {
render() {
const { center, radius } = this.props;
return (
<Circle
ref={circle => { this.circle = circle; }}
center={center}
radius={radius}
onMouseOver={() => {
this.circle.leafletElement.bindPopup('foo').openPopup();
}}/>
);
}
}
export default Foo;
I want to create a button with an icon and text, where icon is above text.
Looking for information I've found this answer from Juri.
With it I've created my own SquareButton class like below:
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Image;
/**
* Square Button class
* #author julio.palma.vazquez
*
*/
public class SquareButton extends Button {
/** Text to show. */
private String text;
/**
* Constructor.
*/
public SquareButton() {
super();
}
public SquareButton(String text, ClickHandler clickHandler, ImageResource imageResource) {
super(text, clickHandler);
setResource(imageResource);
setPixelSize(60, 60);
}
/**
* Set image resource.
* #param imageResource image resource
*/
public void setResource(ImageResource imageResource){
Image img = new Image(imageResource);
String definedStyles = img.getElement().getAttribute("style");
img.getElement().setAttribute("style", definedStyles + "; vertical-align:top;");
DOM.insertBefore(getElement(), img.getElement(), DOM.getFirstChild(getElement()));
}
/**
* Set text.
* #param text text to show
*/
#Override
public void setText(String text) {
this.text = text;
Element span = DOM.createElement("span");
span.setInnerText(text);
span.setAttribute("style", "vertical-align:bottom; text-align: center;");
DOM.insertChild(getElement(), span, 0);
}
/**
* Get text.
* #return text to show
*/
#Override
public String getText() {
return this.text;
}
}
Unfortunatelly it doesn't work as I expect and output text above image.
Could you please give me a hand?
You can set HTML in Button. You can try following:
Button button = new Button();
String html = "<div><center><img src = '"+GWT.getModuleBaseURL()+"/images/img1.png' height = '10px' width = '10px'></img></center><label>Text</label></br></div>";
button.setHTML(html);
Give proper size to your button as well as image.
You can see SquareButton class below, thanks for your help.
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.Button;
/**
* Square Button class
* #author julio.palma.vazquez
*
*/
public class SquareButton extends Button {
public SquareButton(String text, ClickHandler clickHandler, ImageResource imageResource) {
super();
String html = "<div><center><img src = '" + imageResource.getSafeUri().asString() + "' height = '32px' width = '32px'></img></center><label>" + text + "</label></br></div>";
addClickHandler(clickHandler);
setHTML(html);
setPixelSize(60, 60);
}
}
You don't need a custom button. You can do this with a GWT Button, ImageResource, and CSS.
The trick is to set the padding properly. For example,
Button btnHelp=new Button("Help");
btnHelp.setStyleName("buttonImageText");
// Separate style for each image resource
btnHelp.addStyleName("bgImageHelp");
In your stylesheet:
(Note: padding-top is at least as large as your image height.)
.buttonImageText{
background-repeat: no-repeat;
background-position: 50% 0%;
background-size: 20px 20px;
background-color: transparent;
border: none;
margin: 0 15px;
padding: 20px 0 0 0;
text-align: center;
}
.bgImageHelp {
background-image: helpUrl;
}
And you've also defined in your CSS file:
#url helpUrl help;
Finally, in your Resources class you have defined:
#Source("resources/images/help.png");
ImageResource help();
I want to show my own text hover in eclipse for some specific words? Please provide me some examples
You can start by looking at Koder examples.
E.g. this CEditorTextHoverDispatcher or this UCTextHover
package com.ut2003.uceditor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.swt.graphics.Point;
public class UCTextHover implements ITextHover
{
/* (non-Javadoc)
* Method declared on ITextHover
*/
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion)
{
if (hoverRegion != null)
{
try
{
if (hoverRegion.getLength() > -1)
return textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength());
}
catch (BadLocationException x)
{
}
}
return "Empty Selection";
}
/* (non-Javadoc)
* Method declared on ITextHover
*/
public IRegion getHoverRegion(ITextViewer textViewer, int offset)
{
Point selection = textViewer.getSelectedRange();
if (selection.x <= offset && offset < selection.x + selection.y)
return new Region(selection.x, selection.y);
return new Region(offset, 0);
}
}
You would set a TextHover in a SourceViewerConfiguration like this GasSourceViewerConfiguration or this CalcSourceViewerConfiguration
package com.example.calc.ui.editors;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.reconciler.MonoReconciler;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
/**
* #author cdaly
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class CalcSourceViewerConfiguration extends SourceViewerConfiguration {
private CalcEditor _editor;
public CalcSourceViewerConfiguration(CalcEditor editor){
_editor = editor;
}
/* (non-Javadoc)
* #see org.eclipse.jface.text.source.SourceViewerConfiguration#getReconciler(org.eclipse.jface.text.source.ISourceViewer)
*/
public IReconciler getReconciler(ISourceViewer sourceViewer) {
return new MonoReconciler(_editor.getReconcilingStrategy(), false);
}
/* (non-Javadoc)
* #see org.eclipse.jface.text.source.SourceViewerConfiguration#getTextHover(org.eclipse.jface.text.source.ISourceViewer, java.lang.String)
*/
public ITextHover getTextHover(
ISourceViewer sourceViewer,
String contentType) {
ITextHover hover;
if (_editor != null && _editor instanceof CalcEditor) {
hover = new CalcTextHover((CalcEditor)_editor);
} else {
hover = null;
}
return hover;
}
}
Beyond that, I have not much more information: the examples I have found are more programmatic than declarative (i.e. "plugin.xml"), so you may want to explore some more code.
Another good example: Eclipse: Rich Hovers Redux (it is for eclipse3.4 though, but the full example can give you another hint at how a custom ITextHover is added to the current editor)
The best thing is to use the java editor plugin along with eclipse first. Take eclipse help ->welcome->Samples->Java Editor plugin