I'm using konva.js to draw elements on an HTML Canvas. When the user finishes its design in the canvas, the creation can be exported into a PDF file. In this context, my HTML structure is the following:
a div "canvas" to append all the canvas
a div "canvas0/canvas1" and so on to append each konva-canvas
an auto-generated div "konvajs-content"
and finally, multiple canvases depending on the number of layers
So, to export the PDF I have to go through each div "canvas + number" and then go through each canvas childNodes to use the getContext('2d') and drawImage function to draw an Image with the contents of each canvas (hopefully this description is not too confusing...).
Well, I'm able to export the pdf with multiple pages according to the number of canvases drawn, but the image drawn from the canvas has very low quality. Finally, my doubt is, how can I export it with higher quality?
Theres a clever trick to i crease the resolution.
step 1
make your canvas twice bigger like this:
canvas.width=innerWidth*2;
canvas.height=innerHeight*2;
step 2
to make canvas cover entire width set its width and height from css like this:
canvas{ width:100%; }
thats it . At the end you will have doubled the image resolution and make sure you use width:100%; in css not as its attribute in html.
Hope that works for you.
If you are using Konva you should use its method to do an export.
stage.toDataURL()
If you want to increase quality of output image you can use pixelRatio property.
// it will produce 4x bigger image
stage.toDataURL({ pixelRatio: 2})
https://konvajs.org/docs/data_and_serialization/High-Quality-Export.html
Related
I am using Fabric JS to allow the user to have an interactive experience on my React app. Is it possible to apply a frame around a Fabric JS that is taken from an image? For instance, if the canvas is 400x400 px I can resize an image of a frame that is transparent in the middle to 410x410px and apply it on top of the canvas for the user to see? I have attached two images for reference.
Edit: This is the code I am using for zooming in
const zoomIn = useCallback(() => {
// Get original height of canvas
const canvasDimensions = getInitialCanvasSize()
let zoom = HTML5Canvas.getZoom()
zoom += 0.2
if (zoom >= 2) zoom = 2
HTML5Canvas.setZoom(zoom)
HTML5Canvas.setWidth(canvasDimensions.width * HTML5Canvas.getZoom());
HTML5Canvas.setHeight(canvasDimensions.height * HTML5Canvas.getZoom());
}, [HTML5Canvas])
There is no option for canvas's border in fabricjs canvas docs
But you can still achieve this easily using following steps.
PART 1: Creating the Illusion of border
CSS Method
First one can easily create CSS border around the canvas.
Best way to do this is to create div around canvas, as fabricjs split canvas in 2 while running.
You can create slider to control width and color/image for div's border.
This will looks like exactly your second image with customization.
OR
Another Canvas Method
Behind current canvas put this second canvas and control its width and image.
I don't recommend this one, as this will make it more complex to implement.
PART 2: Making Illusion real
If you used CSS METHOD
Now you get what your canvas looks like. You have width of border, image/color of border.
Steps:
Create new canvas (lets' call it 2nd Canvas) of 410px if canvas's width 400px with border of 5px.
Export main canvas as image and put it over 2nd Canvas. And now you can export this as final image.
For 2nd step check my answer on this stack
If you used Another Canvas Method
Directly follow above 2nd step
Export main canvas as image and put it over 2nd Canvas. And now you can export this as final image.
For 2nd step check my answer on this stack
I do have some pictures, and I need to crop them in a circular shapes before using them in React Native to use as ViroImage in react-viro (a library that render 360Images).
I can not apply much styles to the pictures and the borderRadius doesn't seem to solve my problem.
create a container with border radius = 30 and then place your image inside it
I've created react-native-image-tools-wm library when I had to process an image on the client and couldn't find anything worth using. Try it.
Example:
const image = Image.resolveAssetSource(require('./my-image.jpg)).uri;
const maskImage = Image.resolveAssetSource(require('./mask-image.png)).uri;
RNImageTools.mask(image, maskImage).then(({ uri, width, height }) => {
// Sync with your app state
});
Please note that your mask image should be black on white on iOS and black on transparent on Android. Black part will be replaced with your image and white/transparent will become transparent. You can use .android and .ios suffix on names and RN will load them conditionally.
You can also create a mask using createMaskFromShape method but you'll have to generate shape points yourself.
Actually. I have created two canvas one containing some static content & over that another canvas containing some dynamic content. Now I have show snap of both the canvas with zoom in a separate canvas where the snap will change according to the moving object. I am using getImage & putImage but unable to zoom the image content. Even getImage is not working for the canvas contating dynamic content because security error is showing.
context.drawImage can use another canvas as its source image.
context.drawImage can scale the source image when drawing.
context.drawImage does not run afoul of CORS security like getImageData does.
For example, assume sourceCanvas has the original image located at coordinate[20,30] sized at 100x140.
If you have a context to the destination canvas, you can scale it 2X and draw it on the destination canvas at [50,60] like this:
context.drawImage(
sourceCanvas,
20,30,100,140, // grabs 100x140 pixels from sourceCanvas at [20,30]
50,60,200,280 // scale the grabbed pixels to 200x280 and draw it at [50,60]
);
For a Project I want to take the content of a canvas (Called SAVE_CV) and display it in another, smaller canvas.
Some things that I am aware of so far that could be causing me problems: resizing a canvas clears its content, the JS-size of a canvas is different from the CSS-size.
I want the smaller canvas to be 500px wide and appropriately high.
function restoreTaggingCV() {
var cv = document.getElementById( 'taggingCV' );
var ctx = cv.getContext( "2d" );
var styleHeight = SAVE_CV.height * 500 / SAVE_CV.width;
ctx.drawImage(SAVE_CV, 0, 0, cv.width, cv.height);
}
This is my Code so far. Whenever I try to resize the smaller canvas appropriately it only gives me a blank canvas with nothing in it. I tried to set the size with "cv.height = X" and "cv.style.height = styleHeight + 'px'" but neither worked. Also I would love to set the width of the canvas using CSS.
Appreciate any help.
EDIT
I want the image in a picture because later I want the user to mark areas in the smaller version which I then want to use to create individual imaged from the big version. I want to visualise thise area to the user. I probably could do all this by using an image and putting divs over it or something but I just fell more comfident using a canvas since I am pritty new to HTML and CSS.
Try using the CanvasRenderingContext2d.prototype.scale method. It sets the scale factor of the canvas and renders anything in the current state with it's dimensions multiplied by the factor.
So before you use the drawImage function, you scale the context appropriately (in this case, down). For example:
context.save();
context.scale(0.5, 0.5);
context.drawImage(canvas, 0, 0);
context.restore();
This would render the canvas on the context at 0.5 times it's current size. See in this fiddle how I used it to mirror a larger canvas onto a smaller, separate one.
Canvas objects don't like to be resised. After drawing Your image simply convert it toDataURL() and set as image source. They You may resize image as you want.
$img.attr('src',canvas.toDataURL());
Does anybody know if there is a way to 'export' an entire KineticJS layer (or group) and not just the part that is in the visible canvas?
I have a simple 'image editor' that allows the user to scale the image in the canvas, the image can deliberately be scaled larger than the visible canvas stage area allowing the user to pan the image sections into view. The problem is that when they come to export the image (currently using the toDataURL) only the section of the image in the visible canvas stage is saved, the rest of the image is discarded!
I effectively want to save the whole layer, not just what is rendered in the visible canvas stage.
Well, You need a temporary workaround.
I assume you have a function or something that does .toDataURL().
Right before you do toDataURL(), change the stage size or scale, then save, then change back.
Example:
function save(){
stage.setScale(newX,newY); //rescale to new values
stage.setWidth(newWidth);
stage.setHeight(newHeight);
stage.toDataURL(); // <----- save
stage.setScale(oldX,oldY); //rescale to old values
stage.setWidth(oldWidth);
stage.setHeight(oldHeight);
}
This will resize or rescale your stage and then put it back the way it was.