JSFiddle - React, Tailwind, and code Playground
by brigand
HTML
<div id="first">
<img src="" alt="" id="inner">
</div>
<div id="second"></div>
<h2>full image</h2>
<img src="" alt="" id="full">
CSS
#first, #second {
width: 20em;
height: 5em;
box-shadow: 0 0 3px black;
overflow: hidden;
margin: 2em;
}
#inner {
width: 100%;
}
JavaScript
function makeImage(width, height) {
const hw = Math.floor(width / 2);
const hh = Math.floor(height / 2);
const src = `<?xml version="1.0" standalone="no"?>
<svg viewBox="0 0 ${width} ${height}" width="${width}" height="${height}"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<rect width="${width}" height="${height}" fill="#999" />
<rect width="${hw}" height="${hh}" fill="hotpink" />
<rect x="${hw}" y="${hh}" width="${hw}" height="${hh}" fill="limegreen" />
<rect x="1" y="1" width="${width - 2}" height="${height - 2}" stroke="blue" stroke-width="4" stroke-location="inside" fill="none" />
</svg>`
const url = `data:image/svg+xml;base64,${btoa(src)}`;
return { url, width, height, aspect: width / height, crop: 0.5 }
}
function test(width, height, crop) {
const inner = document.querySelector("img#inner");
const full = document.querySelector("img#full");
const { url, aspect } = makeImage(width, height);
inner.src = url;
full.src = url;
inner.style.transform = `translateY(${crop * 100}%)`;
let r_dst = 4 / 1;
let w_dst = width;
let h_dst = width / r_dst;
let xform = 1 - h_dst / height;
let c_dst = Math.abs(crop);
let y_pos = c_dst / xform;
let y_per = (y_pos * 100).toFixed(2);
second.style.backgroundImage = `url("${url}")`;
second.style.backgroundSize = "100%";
second.style.backgroundPosition = `0 ${y_per}%`;
}
test(500, 400, -0.3);