Circle Cropper
A good example of how transform origin does its bizniz
HTML
<div id="cropper">
<img id="cropper-img" src="https://i.imgur.com/rpEuuFI.jpg">
<div class="drag-and-drop-preventer"></div>
<div class="white-circle"></div>
<div class="black-circle"></div>
</div>
<input type="range" min="10" max="400" value="100"/>
<hr style="clear:both">
<form id="cropping_result">
<input id="top" type="number" disabled>
<label for="top">top</label>
<br>
<input id="left" type="number" disabled>
<label for="left">left</label>
<br>
<input id="bottom" type="number" disabled>
<label for="bottom">bottom</label>
<br>
<input id="right" type="number" disabled>
<label for="right">right</label>
</form>
CSS
::-moz-selection { background-color: transparent; }
::selection { background-color: transparent; }
#cropper{
width:500px;
height:500px;
border:solid 4px black;
position:relative;
cursor: -webkit-grab;
overflow:hidden;
}
#cropper-img{
position:absolute;
top:50%;
left:50%;
-webkit-transform-origin:0 0;
transform-origin:0 0;
-webkit-transition:-webkit-transform 2.0;
transition:-webkit-transform 2.0;
}
.drag-and-drop-preventer{
position:absolute;
width:100%;
height:100%;
background-color:transparent;
}
.white-circle,
.black-circle{
position:absolute;
border-radius:50%;
}
.white-circle{
top:50px;
left:50px;
width:398px;
height:398px;
border:solid 1px white;
}
.black-circle{
top:49px;
left:49px;
width:400px;
height:400px;
border:solid 1px black;
}
input[type=range]{
width:500px;
}
JavaScript
/**
* Circle Cropper 4000
* built for Mozillians.org
* Wray Bowling [:wbowling] Jun 2014
*/
// DOM
var cropper = document.querySelector('#cropper');
var cropperImage = document.querySelector('#cropper img');
var slider = document.querySelector('input');
var originalWidth, originalHeight;
var originalScale, slideScale, reverseScale;
var x,y,px,py;
var top,bottom,left,right;
slideScale = 1.0;
function update(){
//translate based on inverse scale
//transform stays fixed (see CSS)
//scale based on scale
var transformString = [];
scale = originalScale * slideScale;
transformString.push('scale('+ scale +')');
transformString.push('translate('+x+'px,'+y+'px)');
//console.log(transformString);
cropperImage.style.webkitTransformOrigin = '0 0';
cropperImage.style.transformOrigin = '0 0';
cropperImage.style.webkitTransform = transformString.join(' ');
cropperImage.style.transform = transformString.join(' ');
console.log(
'scale:'+scale.toFixed(4),
'reverse:'+reverseScale.toFixed(4),
'x',x,
'y',y
);
document.getElementById('top').value = Math.round(-200 * reverseScale - y);
document.getElementById('left').value = Math.round(-200 * reverseScale - x);
document.getElementById('bottom').value = Math.round(200 * reverseScale - y);
document.getElementById('right').value = Math.round(200 * reverseScale - x);
}
cropperImage.onload = function(){
originalWidth = cropperImage.width;
originalHeight = cropperImage.height;
//console.log('original WxH',originalWidth,originalHeight);
if(originalWidth >= originalHeight){
originalScale = 500 / originalWidth;
}else{
originalScale = 500 / originalHeight;
}
x = -originalWidth / 2;
y = -originalHeight / 2;
//console.log('originalScale',originalScale);
update();
};
var dragging = false;
// EVENTS
cropper.onmousedown = function(event){
dragging = true;
};
window.onmouseup =...