我正在实施基于Croppie的图像裁剪工具。我的问题是当我缩小太远时,图像离开视口或离裁剪区域太远。
所以我有一个函数,在线(下面的代码片段)363就像这样:
function _updateCenterPoint() { //borked
console.log("fire _updateCenterPoint()");
var self = this,
transform = Transform.parse(self.childElements.img.style[CSS_TRANSFORM]);
var imgRect = self.childElements.img.getBoundingClientRect(),
cropRect = self.childElements.enclosedCrop.getBoundingClientRect();
if (!isContainedByCrop(imgRect, cropRect, transform)) {
console.log("adjust center");
transform.x = //do a transform (I've tried many - see below)
transform.y = //do a transform (I've tried many - see below);
}
var newCss = {};
newCss['transform'] = transform.toString();
css(self.childElements.img, newCss);
}
在元素缩小太远之后定位元素由if (!isContainedByCrop(imgRect, cropRect, transform))
条件中的逻辑处理,其中记录了"adjust center"
。
我已经尝试了很多方法来做到这一点。我尝试使用距离公式,但感到困惑,因为我比较了翻译的值而不是(x,y)点。基本上,一旦它收缩到一定量以下,它应该适合裁剪工具。
但是,我无法让它始终如一。当我将其缩小到150 x 150像素时,它有时会在裁剪工具中居中,有时则不会。
扩展会增加复杂性(对我而言)。如果你没有缩放它,这将是一个简单的等式,只需通过.enclosedCrop
getBoundingClientRect().top
(白色居中的圆圈)减去图像来翻译{ {1}}(对于x值相同),它会到达应有的位置。但是因为我正在缩放它,它的位置正在改变,我不知道如何解释它。
只有当我不通过在某些方向上拖动鼠标来定位图像时,它在过去也有效(取决于我所确定的等式)。无论我如何翻译/缩放图像,等式都应该有效。
缩放更改元素的位置,如下所示:
这是尝试使用距离(例如)公式:
getBoundingClientRect().top
它没有用,因为我没有试图获得两点之间的距离。相反,我尝试适当地沿x和y轴平移以将图像定位在裁剪圆的顶部。当我尝试从左上方和顶部从左上方减去左边时,这似乎也不起作用。
鉴于这两张图,我不明白为什么:
transform.x = Math.sqrt( (cropRect.left - self.imgRectLeftOrig) * (cropRect.left - self.imgRectLeftOrig) - (imgRect.left * transform.scale) * (imgRect.left * transform.scale));
transform.y = Math.sqrt( (cropRect.top - self.imgRectTopOrig) * (cropRect.top - self.imgRectTopOrig) - (imgRect.top * transform.scale) * (imgRect.top * transform.scale));
不起作用......
此外,如果我有一个图像,并且我使用transform.x = cropRect.left - (imgRect.left * transform.scale);
transform.y = cropRect.top - (imgRect.top * transform.scale);
进行缩放,它似乎表现为css("transform","scale(1.1)
值下降而不是向上,这使得MDN图形对我来说更加混乱,到目前为止正如我所知,他们表明了相反的情况。也许这是一个CSS问题?
.getBoundingClientRect().top

function initAngularCrop() {
var self = this;
self.data = {};
self.childElements = {};
self.type = type = 'small';
viewBox = self.childElements.viewBox = document.createElement('div');
enclosedCrop = self.childElements.enclosedCrop = document.createElement('div');
img = self.childElements.img = document.createElement('img');
overlay = self.childElements.overlay = document.createElement('div');
viewBox.className = viewBox.className ? 'viewBox' + ' ' + viewBox.className : 'viewBox';
enclosedCrop.className = enclosedCrop.className ? 'enclosedCrop' + ' ' + enclosedCrop.className : 'enclosedCrop';
enclosedCrop.className = enclosedCrop.className ? enclosedCrop.className + ' ' + type : type;
overlay.className = overlay.className ? 'overlay' + ' ' + overlay.className : 'overlay';
overlay.className = overlay.className ? type + ' ' + overlay.className : type;
img.className = img.className ? 'bigTuna' + ' ' + img.className : 'bigTuna';
img.src = "https://images.genius.com/2774bb81e57abc5c808b50c45eaa75f2.600x600x1.jpg";
document.body.appendChild(viewBox);
viewBox.appendChild(img);
viewBox.appendChild(enclosedCrop);
viewBox.appendChild(overlay);
initDraggable.call(self);
zoomzoomwrap = self.childElements.zoomzoomwrap = document.createElement('div'),
zoomzoom = self.childElements.zoomzoom = document.createElement('input');
zoomzoomwrap.className = zoomzoomwrap.className ? 'zoomzoomboomboom' + ' ' + zoomzoomwrap.className : 'zoomzoomboomboom';
zoomzoom.className = zoomzoom.className ? 'littleTuna' + ' ' + zoomzoom.className : 'littleTuna';
zoomzoom.type = 'range';
zoomzoom.step = '0.0001';
zoomzoom.value = 5;
zoomzoom.style.display = '';
zoomzoom.setAttribute('aria-label', 'zoom');
zoomzoom.min = 0;
zoomzoom.max = 10;
viewBox.parentNode.insertBefore(zoomzoomwrap, viewBox.nextSibling);
zoomzoomwrap.appendChild(zoomzoom);
self._currentZoom = 1;
self.imgRectTopOrig = img.getBoundingClientRect().top;
self.imgRectLeftOrig = img.getBoundingClientRect().left;
function change() {
initZoom.call(self, {
value: parseFloat(zoomzoom.value / 5),
origin: new TransformOrigin(img),
viewportRect: enclosedCrop.getBoundingClientRect(),
transform: Transform.parse(img)
});
}
self.childElements.zoomzoom.addEventListener('input', change);
//self.childElements.zoomzoom.addEventListener('change', change);
//console.log(self.childElements.zoomzoom);
}
var _debouncetimer;
var _debounce = function(fn, delay, context) {
//console.log("debounce run",fn);
clearTimeout(_debouncetimer);
_debouncetimer = setTimeout(function() {
fn.call(context);
//console.log("debounce fire!");
}, delay);
};
function initZoom(ui) {
var self = this,
transform = ui ? ui.transform : Transform.parse(self.childElements.img),
vpRect = ui ? ui.viewportRect : self.childElements.viewport.getBoundingClientRect(),
origin = ui ? ui.origin : new TransformOrigin(self.childElements.img);
function applyCss(bar) {
if (self.type == "small") {
var size = 150;
}
//console.log("apply zoom CSS");
if (bar) {
if (transform.scale * self.childElements.img.width > size && transform.scale * self.childElements.img.height > size) {
var transCss = {};
transCss[CSS_TRANSFORM] = transform.toString();
css(self.childElements.img, transCss);
} else {
if (self.childElements.img.width > self.childElements.img.height) {
transform.scale = size / self.childElements.img.width;
} else {
transform.scale = size / self.childElements.img.height;
}
var transCss = {};
transCss[CSS_TRANSFORM] = transform.toString();
css(self.childElements.img, transCss);
}
_debounce(_updateCenterPoint, 500, self);
} else {
_debounce(_updateCenterPoint, 500, self);
}
}
if (self.type == "small") {
if ((self.childElements.img.getBoundingClientRect().width <= 150 || self.childElements.img.getBoundingClientRect().height <= 150) && (ui.value < 1 && ui.value < self._currentZoom)) {
applyCss(false);
return;
} else {
self._currentZoom = ui ? ui.value : self._currentZoom;
transform.scale = self._currentZoom;
self.childElements.zoomzoom.setAttribute('aria-valuenow', self._currentZoom);
applyCss(true);
return;
}
}
applyCss(); //othersizes
/* _debouncedOverlay.call(self);
_triggerUpdate.call(self);*/
}
function _getVirtualBoundaries(viewport) {
var self = this,
scale = self._currentZoom,
vpWidth = viewport.width,
vpHeight = viewport.height,
centerFromBoundaryX = self.childElements.viewBox.clientWidth / 2,
centerFromBoundaryY = self.childElements.viewBox.clientHeight / 2,
imgRect = self.childElements.img.getBoundingClientRect(),
curImgWidth = imgRect.width,
curImgHeight = imgRect.height,
halfWidth = vpWidth / 2,
halfHeight = vpHeight / 2;
var maxX = ((halfWidth / scale) - centerFromBoundaryX) * -1;
var minX = maxX - ((curImgWidth * (1 / scale)) - (vpWidth * (1 / scale)));
var maxY = ((halfHeight / scale) - centerFromBoundaryY) * -1;
var minY = maxY - ((curImgHeight * (1 / scale)) - (vpHeight * (1 / scale)));
var originMinX = (1 / scale) * halfWidth;
var originMaxX = (curImgWidth * (1 / scale)) - originMinX;
var originMinY = (1 / scale) * halfHeight;
var originMaxY = (curImgHeight * (1 / scale)) - originMinY;
return {
translate: {
maxX: maxX,
minX: minX,
maxY: maxY,
minY: minY
},
origin: {
maxX: originMaxX,
minX: originMinX,
maxY: originMaxY,
minY: originMinY
}
};
}
function initDraggable() {
var self = this,
isDragging = false,
originalX,
originalY,
originalDistance,
vpRect,
transform;
function assignTransformCoordinates(deltaX, deltaY) {
var imgRect = self.childElements.img.getBoundingClientRect(),
top = transform.y + deltaY,
left = transform.x + deltaX;
if (vpRect.top + 15 > imgRect.top + deltaY && vpRect.bottom < 15 + imgRect.bottom + deltaY) {
transform.y = top;
//console.log("shift!");
}
if (vpRect.left + 15 > imgRect.left + deltaX && vpRect.right < 15 + imgRect.right + deltaX) {
transform.x = left;
//console.log("shift!");
}
}
function mouseDown(ev) {
if (ev.button !== undefined && ev.button !== 0) return;
ev.preventDefault();
if (isDragging) return;
isDragging = true;
originalX = ev.pageX;
originalY = ev.pageY;
if (ev.touches) {
var touches = ev.touches[0];
originalX = touches.pageX;
originalY = touches.pageY;
}
transform = Transform.parse(self.childElements.img); //key point
window.addEventListener('mousemove', mouseMove);
window.addEventListener('touchmove', mouseMove);
window.addEventListener('mouseup', mouseUp);
window.addEventListener('touchend', mouseUp);
document.body.style['userSelect'] = 'none';
vpRect = self.childElements.enclosedCrop.getBoundingClientRect();
}
function mouseMove(ev) {
//shift it around with mouse/touch
ev.preventDefault();
var pageX = ev.pageX,
pageY = ev.pageY;
if (ev.touches) {
var touches = ev.touches[0];
pageX = touches.pageX;
pageY = touches.pageY;
}
var deltaX = pageX - originalX,
deltaY = pageY - originalY,
newCss = {};
if (ev.type == 'touchmove') {
if (ev.touches.length > 1) {
var touch1 = ev.touches[0];
var touch2 = ev.touches[1];
var dist = Math.sqrt((touch1.pageX - touch2.pageX) * (touch1.pageX - touch2.pageX) + (touch1.pageY - touch2.pageY) * (touch1.pageY - touch2.pageY));
//above is math :(
if (!originalDistance) {
originalDistance = dist / self._currentZoom;
}
var scale = dist / originalDistance;
_setZoomerVal.call(self, scale);
dispatchChange(self.childElements.zoomzoom);
return; //why
}
}
assignTransformCoordinates(deltaX, deltaY);
//console.log(pageX,originalX,pageY,originalY,deltaX,deltaY);
newCss['transform'] = transform.toString();
//console.log(newCss,transform.toString());
css(self.childElements.img, newCss);
//_updateOverlay.call(self);
originalY = pageY;
originalX = pageX;
}
function mouseUp() {
isDragging = false;
window.removeEventListener('mousemove', mouseMove);
window.removeEventListener('touchmove', mouseMove);
window.removeEventListener('mouseup', mouseUp);
window.removeEventListener('touchend', mouseUp);
document.body.style['userSelect'] = '';
//_updateCenterPoint.call(self);
//_triggerUpdate.call(self);
originalDistance = 0;
}
self.childElements.overlay.addEventListener('mousedown', mouseDown);
self.childElements.overlay.addEventListener('touchstart', mouseDown);
} //initDraggable()
var TRANSLATE_OPTS = {
'translate3d': {
suffix: ', 0px'
},
'translate': {
suffix: ''
}
};
var Transform = function(x, y, scale) {
this.x = parseFloat(x);
this.y = parseFloat(y);
this.scale = parseFloat(scale);
};
Transform.parse = function(v) {
if (v.style) {
return Transform.parse(v.style['transform']);
} else if (v.indexOf('matrix') > -1 || v.indexOf('none') > -1) {
return Transform.fromMatrix(v);
} else {
return Transform.fromString(v);
}
};
Transform.fromMatrix = function(v) {
var vals = v.substring(7).split(',');
if (!vals.length || v === 'none') {
vals = [1, 0, 0, 1, 0, 0];
}
return new Transform(num(vals[4]), num(vals[5]), parseFloat(vals[0]));
};
Transform.fromString = function(v) {
var values = v.split(') '),
translate = values[0].substring("translate3d".length + 1).split(','),
scale = values.length > 1 ? values[1].substring(6) : 1,
x = translate.length > 1 ? translate[0] : 0,
y = translate.length > 1 ? translate[1] : 0;
return new Transform(x, y, scale);
};
Transform.prototype.toString = function() {
var suffix = TRANSLATE_OPTS["translate3d"].suffix || '';
return "translate3d" + '(' + this.x + 'px, ' + this.y + 'px' + suffix + ') scale(' + this.scale + ')';
};
var TransformOrigin = function(el) {
//console.log(el.style[CSS_TRANS_ORG] + " Transform Origin");
if (!el || !el.style[CSS_TRANS_ORG]) {
this.x = 0;
this.y = 0;
return;
}
var css = el.style[CSS_TRANS_ORG].split(' ');
this.x = parseFloat(css[0]);
this.y = parseFloat(css[1]);
};
TransformOrigin.prototype.toString = function() {
return this.x + 'px ' + this.y + 'px';
};
function css(el, styles, val) {
if (typeof(styles) === 'string') {
var tmp = styles;
styles = {};
styles[tmp] = val;
}
for (var prop in styles) {
el.style[prop] = styles[prop];
}
}
function isContainedByCrop(imgRect, cropRect, transform) {
if ((imgRect.top > cropRect.top || imgRect.bottom < cropRect.bottom) || (imgRect.left > cropRect.left || imgRect.right < cropRect.right)) {
return false;
} else {
return true; //contained
}
}
var emptyStyles = document.createElement('div').style;
var cssPrefixes = ['Webkit', 'Moz', 'ms'];
function vendorPrefix(prop) {
if (prop in emptyStyles) {
return prop;
}
var capProp = prop[0].toUpperCase() + prop.slice(1),
i = cssPrefixes.length;
while (i--) {
prop = cssPrefixes[i] + capProp;
if (prop in emptyStyles) {
return prop;
}
}
}
var CSS_TRANSFORM = vendorPrefix('transform');
var CSS_TRANS_ORG = vendorPrefix('transformOrigin');
function _updateCenterPoint() { //borked
console.log("fire _updateCenterPoint()");
var self = this,
transform = Transform.parse(self.childElements.img.style[CSS_TRANSFORM]);
var imgRect = self.childElements.img.getBoundingClientRect(),
cropRect = self.childElements.enclosedCrop.getBoundingClientRect();
if (!isContainedByCrop(imgRect, cropRect, transform)) {
console.log("adjust center");
transform.x = self.imgRectLeftOrig - (cropRect.left - imgRect.left - (transform.x * transform.scale));
//console.log(self.childElements.enclosedCrop.offsetLeft,cropRect.left,self.childElements.img.offsetLeft,imgRect.left);
transform.y = self.imgRectTopOrig - (cropRect.top - imgRect.top - (transform.y * transform.scale));
}
var newCss = {};
//newCss['transformOrigin'] = center.x + 'px ' + center.y + 'px';
newCss['transform'] = transform.toString();
css(self.childElements.img, newCss);
}
new initAngularCrop();
&#13;
答案 0 :(得分:2)
transform
已应用于原始位置,因此进行计算会将transform
考虑在内以调整transform
,这一点很复杂。您必须考虑变换的顺序,原始位置和变换原点。
例如,在这里,向左平移100px并缩放到0.5的平方将位于125px位置。首先它移动到100px,然后从中心缩放到125px。如果你之前缩放,那么你是75px。从中心缩放到50像素(因此在25px左侧),然后将100px缩放到50px。因此,获得正确的坐标可能很复杂。
body {
margin: 0px;
}
#red {
transform: scale(0.5) translate(100px, 100px);
}
#blue {
transform: translate(100px, 100px) scale(0.5);
}
table {
border-collapse: collapse;
}
td {
height: 47px;
width: 47px;
border: solid 1px #aaa;
}
<div id="blue" style="position: absolute; width: 100px; height: 100px; background-color: blue;">
</div>
<div id="red" style="position: absolute; width: 100px; height: 100px; background-color: red;">
</div>
<table>
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
我认为,在您的案例中,更简单的方法是使用transform-origin
。您的updateCenter
函数正是transform-origin
所做的,它定义了中心。它是内置的。所有的计算都将由变换处理。您只需要定义所需的原点,而且非常简单。
假设您希望中心位于示例中圆圈中心的点。你需要找到百分比,这一点是你转型的图像。所以它基本上是
(half the width of the circle + left offset of the circle - left offset of the image) / (width of image) * 100
在你的情况下给出:
(cropRect.left + (cropRect.width / 2) - matrix.m41) / self.childElements.img.offsetWidth * 100;
matrix.41
是图片的左侧翻译,您可以通过这种方式找到它(请参阅此答案:How to get value translateX by javascript):
var transform = window.getComputedStyle(self.childElements.img).transform;
var matrix = new WebKitCSSMatrix(transform);
然后你分配:
self.childElements.img.style.transformOrigin = transformOriginX + "% " + transformOriginY + "%";
显然,只有在移动图像时才需要这样做,而不是在缩放上,因为这样就会处理原点。您也可以仅在某些条件下进行调整,但无论如何,您无需考虑平移和缩放。
function initAngularCrop() {
var self = this;
self.data = {};
self.childElements = {};
self.type = type = 'small';
viewBox = self.childElements.viewBox = document.createElement('div');
enclosedCrop = self.childElements.enclosedCrop = document.createElement('div');
img = self.childElements.img = document.createElement('img');
overlay = self.childElements.overlay = document.createElement('div');
viewBox.className = viewBox.className ? 'viewBox' + ' ' + viewBox.className : 'viewBox';
enclosedCrop.className = enclosedCrop.className ? 'enclosedCrop' + ' ' + enclosedCrop.className : 'enclosedCrop';
enclosedCrop.className = enclosedCrop.className ? enclosedCrop.className + ' ' + type : type;
overlay.className = overlay.className ? 'overlay' + ' ' + overlay.className : 'overlay';
overlay.className = overlay.className ? type + ' ' + overlay.className : type;
img.className = img.className ? 'bigTuna' + ' ' + img.className : 'bigTuna';
img.src = "https://images.genius.com/2774bb81e57abc5c808b50c45eaa75f2.600x600x1.jpg";
document.body.appendChild(viewBox);
viewBox.appendChild(img);
viewBox.appendChild(enclosedCrop);
viewBox.appendChild(overlay);
initDraggable.call(self);
zoomzoomwrap = self.childElements.zoomzoomwrap = document.createElement('div'),
zoomzoom = self.childElements.zoomzoom = document.createElement('input');
zoomzoomwrap.className = zoomzoomwrap.className ? 'zoomzoomboomboom' + ' ' + zoomzoomwrap.className : 'zoomzoomboomboom';
zoomzoom.className = zoomzoom.className ? 'littleTuna' + ' ' + zoomzoom.className : 'littleTuna';
zoomzoom.type = 'range';
zoomzoom.step = '0.0001';
zoomzoom.value = 5;
zoomzoom.style.display = '';
zoomzoom.setAttribute('aria-label', 'zoom');
zoomzoom.min = 0;
zoomzoom.max = 10;
viewBox.parentNode.insertBefore(zoomzoomwrap, viewBox.nextSibling);
zoomzoomwrap.appendChild(zoomzoom);
self._currentZoom = 1;
self.imgRectTopOrig = img.getBoundingClientRect().top;
self.imgRectLeftOrig = img.getBoundingClientRect().left;
function change() {
initZoom.call(self, {
value: parseFloat(zoomzoom.value / 5),
origin: new TransformOrigin(img),
viewportRect: enclosedCrop.getBoundingClientRect(),
transform: Transform.parse(img)
});
}
self.childElements.zoomzoom.addEventListener('input', change);
//self.childElements.zoomzoom.addEventListener('change', change);
//console.log(self.childElements.zoomzoom);
}
var _debouncetimer;
var _debounce = function(fn, delay, context) {
//console.log("debounce run",fn);
clearTimeout(_debouncetimer);
_debouncetimer = setTimeout(function() {
fn.call(context);
//console.log("debounce fire!");
}, delay);
};
function initZoom(ui) {
var self = this,
transform = ui ? ui.transform : Transform.parse(self.childElements.img),
vpRect = ui ? ui.viewportRect : self.childElements.viewport.getBoundingClientRect(),
origin = ui ? ui.origin : new TransformOrigin(self.childElements.img);
function applyCss(bar) {
if (self.type == "small") {
var size = 150;
}
//console.log("apply zoom CSS");
if (bar) {
if (transform.scale * self.childElements.img.width > size && transform.scale * self.childElements.img.height > size) {
var transCss = {};
transCss[CSS_TRANSFORM] = transform.toString();
css(self.childElements.img, transCss);
} else {
if (self.childElements.img.width > self.childElements.img.height) {
transform.scale = size / self.childElements.img.width;
} else {
transform.scale = size / self.childElements.img.height;
}
var transCss = {};
transCss[CSS_TRANSFORM] = transform.toString();
css(self.childElements.img, transCss);
}
_debounce(_updateCenterPoint, 500, self);
} else {
_debounce(_updateCenterPoint, 500, self);
}
}
if (self.type == "small") {
if ((self.childElements.img.getBoundingClientRect().width <= 150 || self.childElements.img.getBoundingClientRect().height <= 150) && (ui.value < 1 && ui.value < self._currentZoom)) {
applyCss(false);
return;
} else {
self._currentZoom = ui ? ui.value : self._currentZoom;
transform.scale = self._currentZoom;
self.childElements.zoomzoom.setAttribute('aria-valuenow', self._currentZoom);
applyCss(true);
return;
}
}
applyCss(); //othersizes
/* _debouncedOverlay.call(self);
_triggerUpdate.call(self);*/
}
function _getVirtualBoundaries(viewport) {
var self = this,
scale = self._currentZoom,
vpWidth = viewport.width,
vpHeight = viewport.height,
centerFromBoundaryX = self.childElements.viewBox.clientWidth / 2,
centerFromBoundaryY = self.childElements.viewBox.clientHeight / 2,
imgRect = self.childElements.img.getBoundingClientRect(),
curImgWidth = imgRect.width,
curImgHeight = imgRect.height,
halfWidth = vpWidth / 2,
halfHeight = vpHeight / 2;
var maxX = ((halfWidth / scale) - centerFromBoundaryX) * -1;
var minX = maxX - ((curImgWidth * (1 / scale)) - (vpWidth * (1 / scale)));
var maxY = ((halfHeight / scale) - centerFromBoundaryY) * -1;
var minY = maxY - ((curImgHeight * (1 / scale)) - (vpHeight * (1 / scale)));
var originMinX = (1 / scale) * halfWidth;
var originMaxX = (curImgWidth * (1 / scale)) - originMinX;
var originMinY = (1 / scale) * halfHeight;
var originMaxY = (curImgHeight * (1 / scale)) - originMinY;
return {
translate: {
maxX: maxX,
minX: minX,
maxY: maxY,
minY: minY
},
origin: {
maxX: originMaxX,
minX: originMinX,
maxY: originMaxY,
minY: originMinY
}
};
}
function initDraggable() {
var self = this,
isDragging = false,
originalX,
originalY,
originalDistance,
vpRect,
transform;
function assignTransformCoordinates(deltaX, deltaY) {
var imgRect = self.childElements.img.getBoundingClientRect(),
top = transform.y + deltaY,
left = transform.x + deltaX;
if (vpRect.top + 15 > imgRect.top + deltaY && vpRect.bottom < 15 + imgRect.bottom + deltaY) {
transform.y = top;
//console.log("shift!");
}
if (vpRect.left + 15 > imgRect.left + deltaX && vpRect.right < 15 + imgRect.right + deltaX) {
transform.x = left;
//console.log("shift!");
}
}
function mouseDown(ev) {
if (ev.button !== undefined && ev.button !== 0) return;
ev.preventDefault();
if (isDragging) return;
isDragging = true;
originalX = ev.pageX;
originalY = ev.pageY;
if (ev.touches) {
var touches = ev.touches[0];
originalX = touches.pageX;
originalY = touches.pageY;
}
transform = Transform.parse(self.childElements.img); //key point
window.addEventListener('mousemove', mouseMove);
window.addEventListener('touchmove', mouseMove);
window.addEventListener('mouseup', mouseUp);
window.addEventListener('touchend', mouseUp);
document.body.style['userSelect'] = 'none';
vpRect = self.childElements.enclosedCrop.getBoundingClientRect();
}
function mouseMove(ev) {
//shift it around with mouse/touch
ev.preventDefault();
var pageX = ev.pageX,
pageY = ev.pageY;
if (ev.touches) {
var touches = ev.touches[0];
pageX = touches.pageX;
pageY = touches.pageY;
}
var deltaX = pageX - originalX,
deltaY = pageY - originalY,
newCss = {};
if (ev.type == 'touchmove') {
if (ev.touches.length > 1) {
var touch1 = ev.touches[0];
var touch2 = ev.touches[1];
var dist = Math.sqrt((touch1.pageX - touch2.pageX) * (touch1.pageX - touch2.pageX) + (touch1.pageY - touch2.pageY) * (touch1.pageY - touch2.pageY));
//above is math :(
if (!originalDistance) {
originalDistance = dist / self._currentZoom;
}
var scale = dist / originalDistance;
_setZoomerVal.call(self, scale);
dispatchChange(self.childElements.zoomzoom);
return; //why
}
}
assignTransformCoordinates(deltaX, deltaY);
//console.log(pageX,originalX,pageY,originalY,deltaX,deltaY);
newCss['transform'] = transform.toString();
//console.log(newCss,transform.toString());
css(self.childElements.img, newCss);
//_updateOverlay.call(self);
originalY = pageY;
originalX = pageX;
_updateCenterPoint.call(self);
}
function mouseUp() {
isDragging = false;
window.removeEventListener('mousemove', mouseMove);
window.removeEventListener('touchmove', mouseMove);
window.removeEventListener('mouseup', mouseUp);
window.removeEventListener('touchend', mouseUp);
document.body.style['userSelect'] = '';
//_triggerUpdate.call(self);
originalDistance = 0;
}
self.childElements.overlay.addEventListener('mousedown', mouseDown);
self.childElements.overlay.addEventListener('touchstart', mouseDown);
} //initDraggable()
var TRANSLATE_OPTS = {
'translate3d': {
suffix: ', 0px'
},
'translate': {
suffix: ''
}
};
var Transform = function(x, y, scale) {
this.x = parseFloat(x);
this.y = parseFloat(y);
this.scale = parseFloat(scale);
};
Transform.parse = function(v) {
if (v.style) {
return Transform.parse(v.style['transform']);
} else if (v.indexOf('matrix') > -1 || v.indexOf('none') > -1) {
return Transform.fromMatrix(v);
} else {
return Transform.fromString(v);
}
};
Transform.fromMatrix = function(v) {
var vals = v.substring(7).split(',');
if (!vals.length || v === 'none') {
vals = [1, 0, 0, 1, 0, 0];
}
return new Transform(num(vals[4]), num(vals[5]), parseFloat(vals[0]));
};
Transform.fromString = function(v) {
var values = v.split(') '),
translate = values[0].substring("translate3d".length + 1).split(','),
scale = values.length > 1 ? values[1].substring(6) : 1,
x = translate.length > 1 ? translate[0] : 0,
y = translate.length > 1 ? translate[1] : 0;
return new Transform(x, y, scale);
};
Transform.prototype.toString = function() {
var suffix = TRANSLATE_OPTS["translate3d"].suffix || '';
return "translate3d" + '(' + this.x + 'px, ' + this.y + 'px' + suffix + ') scale(' + this.scale + ')';
};
var TransformOrigin = function(el) {
//console.log(el.style[CSS_TRANS_ORG] + " Transform Origin");
if (!el || !el.style[CSS_TRANS_ORG]) {
this.x = 0;
this.y = 0;
return;
}
var css = el.style[CSS_TRANS_ORG].split(' ');
this.x = parseFloat(css[0]);
this.y = parseFloat(css[1]);
};
TransformOrigin.prototype.toString = function() {
return this.x + 'px ' + this.y + 'px';
};
function css(el, styles, val) {
if (typeof(styles) === 'string') {
var tmp = styles;
styles = {};
styles[tmp] = val;
}
for (var prop in styles) {
el.style[prop] = styles[prop];
}
}
function isContainedByCrop(imgRect, cropRect, transform) {
if ((imgRect.top > cropRect.top || imgRect.bottom < cropRect.bottom) || (imgRect.left > cropRect.left || imgRect.right < cropRect.right)) {
return false;
} else {
return true; //contained
}
}
var emptyStyles = document.createElement('div').style;
var cssPrefixes = ['Webkit', 'Moz', 'ms'];
function vendorPrefix(prop) {
if (prop in emptyStyles) {
return prop;
}
var capProp = prop[0].toUpperCase() + prop.slice(1),
i = cssPrefixes.length;
while (i--) {
prop = cssPrefixes[i] + capProp;
if (prop in emptyStyles) {
return prop;
}
}
}
var CSS_TRANSFORM = vendorPrefix('transform');
var CSS_TRANS_ORG = vendorPrefix('transformOrigin');
function _updateCenterPoint() { //borked
//console.log("fire _updateCenterPoint()");
var self = this;
var imgRect = self.childElements.img.getBoundingClientRect(),
cropRect = self.childElements.enclosedCrop.getBoundingClientRect();
var transform = window.getComputedStyle(self.childElements.img).transform;
var matrix = new WebKitCSSMatrix(transform);
var transformOriginX = (cropRect.left + (cropRect.width / 2) - matrix.m41) / self.childElements.img.offsetWidth * 100;
var transformOriginY = (self.childElements.enclosedCrop.offsetTop + (cropRect.height / 2) - matrix.m42) / self.childElements.img.offsetHeight * 100;
self.childElements.img.style.transformOrigin = transformOriginX + "% " + transformOriginY + "%";
}
new initAngularCrop();
body {
margin: 0px;
}
.viewBox {
position: relative;
overflow: hidden;
display: inline-block;
margin: 0 auto;
width: 500px;
height: 500;
}
.enclosedCrop {
position: absolute;
width: 150px;
height: 150px;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 2px solid #fff;
background: rgba(0, 0, 0, 0.5);
border-radius: 100%;
}
.overlay.small,
.overlay.large {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}