How to scale image to KonvaJS canvas without stretching? - javascript

I'm trying to show images with different aspect ratios on 1080x1920 canvas. So when I try to show 9:16 images, it scales perfectly, but if aspect ratio is 4:3 or 3:4, scaled image stretches.
What I want to do is, if aspect ratio is 3:4, scaling and showing image as 9:16 on center and cutting edges. (So if original width is 1440, showing only 1080 and leaving 180px at each side off the screen. And if original width is 3024, scaling it down to 1440 and then cut)
And if image is not portrait but landscape, showing it on center and filling remaining space with some color.
How can I achive this? Does KonvaJS provides easy way to do this?

No konvaJS does not provide a way around that, you need to use your own logic for positioning the image at the center for different resolutions.
I have used logic for finding the image resolution which fits the provided dimensions in my personal project. Check if it helps.
function getScaledImageCoordinates(
containerWidth,
containerHeigh,
widt,
height,
) {
var widthRatio = (containerWidth) / width,
heightRatio = (containerHeight) / height
var bestRatio = Math.min(widthRatio, heightRatio)
var newWidth = width * bestRatio,
newHeight = height * bestRatio
return {newWidth, newHeight}
}
You can find the image resolution that fits your container (say 1080x1920) and then center position the image on Konva Stage

Related

GraphicsMagick (GM) resize into square without changing ratio and add background

I'm trying to get GraphicsMagick to resize my various images into a standard square. The input is always variable - vertical, horizontal images, different sizes etc.
I want to basically have:
- A white background canvas # 600px x 600px
- The image sits in the center of that canvas # 500px x 500px
I've tried so many from the docs but I can't get it working correctly.
This is what I have working so far (JavaScript):
gm(content)
.autoOrient()
.resize(600, 600)
.gravity('Center')
.extent([600, 600])
.background('#FFFFFF')
.flatten();
And it just comes out the correct width, but keeps the ratio so for a rectangle, it comes out at 600px wide and 240px high (as it kept the ratio).
Any help appreciated!
The solution to my issue was simply that I set extent as an array. Final solution:
gm(content)
.autoOrient()
.resize(550, 550)
.gravity('Center')
.background('#FFFFFF')
.extent(600, 600)
.flatten();

Reactjs: how to minimally crop an image to a certain aspect ratio in client side?

In, I'd like to crop an image, in a minimal fashion, so that it fits a given aspect ratio.
Example: given an image of, say, 3038 x 2014 px, I want to crop it to have a 1:2 aspect ratio. The resulting image would then be 3021 x 2014 px, cropped from the, say, center of the original image.
I've written an article on cropping images with JavaScript to fit a certain aspect ratio (in the center as you requested).
This will create a clone of the original image given the aspect ratio supplied. The function we create in the article can be called like this:
crop('url/to/image.jpg', 1).then(canvas => {
// canvas is a new image canvas based
// on the source image and the supplied aspect ratio
})
// or use async/await
const canvas = await crop('url/to/image.jpg', 1);
I've also set up a Codepen demo
You can use CSS to crop an image, it's called "clipping" in CSS and the property is clip.
clip: rect(top-left-pixel-x, top-left-pixel-y, bottom-right-pixel-x, bottom-right-pixel-y);
If this weren't responsive, you'd just put in the pixels you want manually. The image is 3/2 so you need to enter in what part of the image you want to show.
Let's do the middle horizontal section here.
clip: rect(0, 1007px, 2014px, 2014px);
Of course, this becomes harder when you're doing responsive design. You'll need to calculate the positions off the current height and width..
componentDidMount() {
const height = this.divElement.clientHeight;
const width = this.divElement.clientWidth;
this.setState({ style: `clip: rect(0, ${heigh/3}, width, ${2*height/3}` );
// Note: if the starting img is always 3:2 ratio, the final value could be the width because 3:2 -> 2:! has that natural property, but this code is more flexible
}
render() {
return (
<img src="[your file source]" style={style}/>
)
}

Pixel as decimal for aspect ratio of a div with CSS

Currently using the aspect ratio of a background image to size the Div containing it.
I'm using padding-bottom (imgwidth / imgheight * w) to give it it's "responsive height".
It lines up perfectly until I start zooming in and out for different screen sizes. 100% width and above is perfect (only because I lock the max size at 1500 or I guess I'd have the same issue otherwise).
But zooming in at for example 90% I start getting gaps between the two as I have two background divs one on top of the other.
It's being caused because, for example:
padding-bottom: calc(100% * 600 / 1500);
Is returning a decimal point when zoomed in and the value is being rounded up for pixels.
Is there a solution to this? Or some javascript that can correct it?

banner design creator - measurements

I'm creating a banner design creator (so people would be able to make their own designs with it's own texts, background, images, shapes and so on). I have various of sizes of my producs for example: 800x2000 mm, A4(210 x 297mm), 3300x2200mm.
For painting I'm using html canvas. I stucked on sizing the canvas. What's the best way how to handle different measurements with proper user experience? (canvas with width 3300 would not be the good).
Currently I have this code:
var proportion = variant.width >= variant.height ? variant.width / variant.height : variant.height / variant.width;
canvas.setDimensions({width: variant.width * proportion, height: variant.height * proportion});
This is one way to have your banner creator be responsive to display size:
Calculate the proportional scaling factor required to make your banner fit on the display size.
var displayWidth=1366;
var displayHeight=768;
var bannerWidth=3300;
var bannerHeight=2200;
// calculate the scaling factor required to make the banner fit on the display
var scalingFactor = Math.min((displayWidth/bannerWidth),(displayHeight/bannerHeight));
Resize your canvas (it now fits the display but has the same proportions as your banner).
canvas.width=bannerWidth*scalingFactor;
canvas.height=bannerHeight*scalingFactor;
Apply a background color to your banner (if desired).
context.fillStyle='Gainsboro';
context.fillRect(0,0,canvas.width,canvas.height);
Apply the scaling factor to your actual banner text font size.
// Scale a real banner 300pt font to display proportionally on the canvas
// The text on the canvas will be proportionally sized to the real banner size
var fontSizeInPoints=300;
fontSizeInPoints*=scalingFactor;
context.font=fontSizeInPoints+'pt Verdana';
Let the user position text on the banner.
// draw the text "Fun!" at the mouse position
context.textAlign='left';
context.textBaseline='top';
context.fillText('Fun!',mouseX,mouseY);
After the user has positioned their text on the scaled-down canvas, you can convert their mouse position back to "real world" coordinates by dividing the mouse coordinates by the scaling factor.
// convert mouse coordinates back to coordinates on the real banner size
var realBannerX = mouseX/scaleFactor;
var realBannerY = mouseY/scaleFactor;

Everything inside my canvas got bigger after canvas resize

When I first started this project that I'm working on, my canvas size with 1400px wide and 480px tall. I realized that I am going to need to make the canvas the same size as the window itself later, so I did that and everything inside of the canvas zoomed in or something. I set a drawImage(); to be 300 px wide and 180 px tall, and it is a LOT bigger than that, the image is actually the same width as the canvas now. Any suggestions? Here's the link to the project:
http://brycemckenney.com/animation-app
Thank you guys!
You have set the dimensions through css, instead of the physical dimensions of the (image) canvas.
The relevant piece (for others to read in the future) of your code is:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var windowHeight = $(window).height();
var windowWidth = $(window).width();
$(canvas).css({
height: windowHeight - 8,
width: windowWidth - 8
});
Think of it like this: suppose you have a normal jpg-image.
That jpg has it's own 'physical' dimensions (aka width and height).
In both HTML and CSS you can set the dimensions (in px, percent, etc) that you'd like the browser to render (scale) the picture (hey, the picture already has a immutable size right?).
Now for canvas:
In order for canvas to have a physical width/height, you have to set the .width and .height of the canvas-element itself, either in HTML or per javascript (a side-effect is that setting the physical dimensions is that the canvas will clear itself, as per spec).
Then to scale the image (like you did with the above jpg example) you use css (again in px/percent/etc).
I think this is a clever solution by the way to add that new canvas-element to the HTML-Spec!
So, rounding up:
A canvas with a width and a height of 300 px rendered as 100% of a container (like document.body) that measures 900x900px will be scaled-up 3 times!
The reverse (scaling down) will let you draw even more crisp lines by the way!
Hope this helps your understanding!

Categories

Resources