I have a red container which initially is at bottom right of black container. I have a scale function that gradually scales the container. I want to make the bottom right position of red container to be fixed and scale it towards top left. How can I do that?
const box = document.getElementById("box") const initHeight = 200 const initWidth = 200 const centerX = initWidth / 2 const centerY = initHeight / 2 function transform(scale, translate) { if (translate) { translate[0] = -centerX + translate[0] translate[1] = -centerY + translate[1] } box.style.transform = `scale(${scale})${ translate ? ` translate(${translate.map((x) => x + "px").toString()})` : "" }` } let initX = initWidth let initY = initHeight let scaleVal = 0.5 transform(scaleVal, [initX, initY]) function scale() { scaleVal = scaleVal + 0.01 transform(scaleVal, [ initX - scaleVal * initWidth, initY - scaleVal * initHeight ]) if (scaleVal <= 1) { setTimeout(() => { requestAnimationFrame(scale) }, 50) } } scale()
* { box-sizing: border-box; } .box { height: 200px; width: 200px; background-color: black; position: absolute; } .box:nth-child(2) { background-color: red; }
<div id="app"> <div class="box"></div> <div class="box" id="box"></div> </div>
Advertisement
Answer
Okay so I finally figured it out,
const box = document.getElementById("box") let scale = 0 const initWidth = 50 const initHeight = 50 function fixed(num, fix = 1) { return Number(parseFloat(num).toFixed(fix)) } function scaleBox() { const [x, y] = [ fixed((initWidth - scale * initWidth) / 2), fixed((initHeight - scale * initHeight) / 2) ] box.style.transform = `translate(${x}px, ${y}px) scale(${scale})` scale = scale + 0.1 if (scale < 1) { setTimeout(() => { requestAnimationFrame(scaleBox) }, 500) } } scaleBox()
* { box-sizing: border-box; } .box { height: 50px; width: 50px; background-color: black; position: absolute; } .box:nth-child(2) { background-color: red; transform: translate(0, 0) scale(0); }
<div id="app"> <div class="box"></div> <div class="box" id="box"></div> </div>
Explanation
The trick is to translate the container in such a way that when its scaled after the translation, it always places itself in the bottom right of purple container.
To figure out the translation amount, let’s first scale the container to 0.5 without any translation. It looks like this,
As you can see the container’s width is 25 as 0.5(scale) * 50(init_width)=25
and position from container from all sides(top left, bottom left, top right, bottom right) will be (25/2, 25/2)=(12.5,12.5)
since the container is scaled equally from all sides.
Since the position from bottom right is (12.5,12.5)
, we need to translate the container to (+12.5,+12.5) and then scale it to exactly place it at bottom right.