Сценарий изменения размера увеличивается, а не уменьшается. Использование определителя делает его нервным
Я построил следующий скрипт изменения размера - как вы можете видеть из скрипки, он работает для увеличения, но не для уменьшения:
https://jsfiddle.net/calipoop/a37aeb08/
var item = document.getElementById('item'),
btn = document.getElementById('resizeBtn'),
s = 1;
btn.addEventListener('mousedown', initResize);
function initResize(e) {
var startS = s, startX = e.clientX, startY = e.clientY, dx, dy, d;
window.addEventListener('mousemove', resize);
window.addEventListener('mouseup', killResize);
function resize(e) {
dx = startX - e.clientX;
dy = startY - e.clientY;
d = Math.round(Math.sqrt(dx * dx + dy * dy));
s = startS + (d * .001);
item.style.transform = "scale(" + s + ")";
}
function killResize() {
window.removeEventListener('mousemove', resize);
window.removeEventListener('mouseup', killResize);
}
}
Я попытался решить проблему, используя определитель / перекрестный продукт для положительного / отрицательного направления:
https://jsfiddle.net/calipoop/zbx3us36/
det = (startX*e.clientY) - (e.clientX*startY);
dir = (det >= 0) ? 1 : -1; //get direction from sign of determinant
d = Math.round(Math.sqrt(dx * dx + dy * dy)) * dir;
Как вы можете видеть из скрипки, теперь она "иногда" уменьшается, и она всегда нервная.
Какие-нибудь математические специальности с идеями? Я получаю определитель неправильно? Заранее спасибо за любые идеи.
1 ответ
Когда я впервые посмотрел на него, я увидел, что нельзя использовать отрицательное целое число, поэтому я изменил вашу функцию следующим образом:
function initResize(e) {
var startS = s,
startX = e.clientX,
startY = e.clientY,
dx, dy, d;
window.addEventListener('mousemove', resize);
window.addEventListener('mouseup', killResize);
function resize(e) {
dx = startX - e.clientX;
dy = startY - e.clientY;
negative = false;
if (dx < 0 || dy < 0) negative = true;
d = Math.abs(Math.round(Math.sqrt(dx * dx + dy * dy))); //Always postive, need a way to determine if should be negative.
if (!negative) d = (d * -1);
s = startS + (d * .001);
item.style.transform = "scale(" + s + ")";
}
Вы можете увидеть это здесь: https://jsfiddle.net/gregborbonus/a37aeb08/5/
Поэтому после вашего комментария я сделал еще одно редактирование, чтобы избавиться от проблемы с исходной позицией.
Все, от чего вы масштабировали, определялось на основании расстояния от начальной точки, так как далеко или к точке изменения размера вы перемещали мышь?
Это означает, что даже если вы перестали двигаться в направлении Y, но немного переместили X, Y все равно будет больше, чем ваш ход из X, делая масштабирование по оси Y, но вы не двигали Y, вы только переместили X.
Итак, эта функция показывает, насколько далеко вы переместили вашу мышь от последнего изменения размера:
function initResize(e) {
var startS = s,
startX = e.clientX,
startY = e.clientY,
dx, dy, d;
window.addEventListener('mousemove', resize);
window.addEventListener('mouseup', killResize);
function resize(e) {
//The problem with this logic is that while resizing, you calculate based on distance FROM your start, this is not always the best approach, so what you need is the difference from your last recorded position.
dx = startX - e.clientX;
dy = startY - e.clientY;
startX=e.clientX; //for the next run
startY=e.clientY; //for the next run
negative = false;
if (dx < 0 || dy < 0) negative = true;
//d = Math.abs(Math.round(Math.sqrt(dx * dx + dy * dy))); //Always postive, need a way to determine if should be negative.
d=Math.max(Math.abs(dx),Math.abs(dy))*3; //Lets figure out which is the max and do the math off that.
if (!negative) d = (d * -1);
s = startS + (d * .001);
startS=s; //Set the scale for the next run.
item.style.transform = "scale(" + s + ")";
}
function killResize() {
window.removeEventListener('mousemove', resize);
window.removeEventListener('mouseup', killResize);
}
}