Constraining aspect ratios of images
by Admiral Potato
HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
<form id="size">
<div>
<label for="maxHeight">maxHeight</label>
<input id="maxHeight" v-model="maxHeight" />
</div>
<div>
<label for="x">x</label>
<input id="x" v-model="imageSize.x" />
</div>
<div>
<label for="y">y</label>
<input id="y" v-model="imageSize.y" />
</div>
</form>
<div
class="aspectre"
:style="instanceStyles"
>
<div
class="ratio"
:style="ratio"
></div>
<canvas
ref="canvas"
:width="imageSize.x"
:height="imageSize.y"
></canvas>
<span
class="aspect-label"
>{{imageSize.x + ' x ' + imageSize.y}}</span>
</div>
</div>
CSS
* {
font-family: monospace;
color: #ddd;
}
body {
background-color: #262626;
}
form#size {
position: fixed;
top: 10px;
left: 10px;
z-index: 10;
}
form#size label,
form#size input {
border: 1px solid #666;
background-color: #262626;
padding: 2px;
}
form#size label {
display: inline-block;
width: 96px;
text-align: right;
}
.aspectre {
margin: auto;
position: relative;
background-color: #000;
border: 1px solid #f00;
}
.aspectre .ratio {
position: relative;
}
.aspectre canvas,
.aspectre .aspect-label {
position: absolute;
display: block;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #333;
}
.aspectre canvas {
min-width: 100%;
max-width: 100%;
height: auto;
}
.aspectre .aspect-label {
position: absolute;
width: 128px;
height: 32px;
}
JavaScript
var app = new Vue({
el: '#app',
data: {
maxHeight: 400,
imageSize: {
x: 15,
y: 20
}
},
computed: {
aspect: function () {
return this.imageSize.y / this.imageSize.x
},
ratio: function () {
return {
paddingBottom: (this.aspect * 100) + '%'
}
},
instanceStyles: function () {
return {
maxHeight: this.maxHeight + 'px',
maxWidth: (this.maxHeight / this.aspect) + 'px'
}
},
},
mounted: function () {
this.generateImage()
},
updated: function () {
this.generateImage()
},
methods: {
generateImage: function () {
var canvas = this.$refs.canvas
var ctx = canvas.getContext('2d')
var grd = ctx.createLinearGradient(
0,
0,
this.imageSize.x,
this.imageSize.y,
);
// Add colors
grd.addColorStop(0.000, 'rgba(0, 255, 255, 1)');
grd.addColorStop(1.000, 'rgba(127, 255, 0, 1)');
// Fill with gradient
ctx.fillStyle = grd;
ctx.fillRect(0, 0, this.imageSize.x, this.imageSize.y);
}
}
})