Проблема с захватом мышью
Вложений: 2
Стал решать задачу с этого сайта, где картинку нужно таскать за правый нижний угол, изменяя её размер. Для этого в углу создаётся элемент для захвата. Но при выходе за его пределы mousedown не срабатывает, а срабатывает лишь при повторном нажатии. Изучение решения на сайте не помогло, т. к. оно существенно отличается от моего. Помогите, пожалуйста. Текст ниже. Картинки присоединяю.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div style="width:503px;height:285px;background-color:grey;position:relative" id="skin">
<img style="width:500px;height:282px;position:absolute" id="heroes" src="heroes.jpg">
<img style="position:absolute;right:0;bottom:0" id="corner" src="handle-se.png">
</div>
<div id="info"></div>
<script>
function Resizeable(options) {
var elem = options.elem;
elem.move=false;
elem.on('mousedown', capture);
elem.on('mousemove', cursorMove);
elem.on('mouseup', release);
function capture(e){
if($(e.target).attr('id')=='corner' && elem.move==false){
elem.move=true;
getCoords(e);
console.log(elem.x+' '+elem.y);
}
}
function cursorMove(e){
if(elem.move==true){
size($('#skin'), e);
size($('#heroes'), e);
}
getCoords(e);
}
function release(e){
elem.move=false;
}
function size(rect, e){
rect.css('height',rect.height()-(elem.y-e.pageY))
.css('width',rect.width()-(elem.x-e.pageX));
}
function getCoords(e){
elem.x=e.pageX;
elem.y=e.pageY;
}
}
</script>
</body>
</html>
|
Моя попытка:
<!DOCTYPE html>
<style>
.resizeable{
padding: 10px;
position: relative;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.resizeable .resizer{
position: absolute;
bottom: 0;
right: 0;
width: 16px;
height: 16px;
background: url(http://javascript.ru/forum/attachments/jquery/2137d1394200133-problema-s-zakhvatom-myshyu-handle-se-png);
cursor: se-resize;
}
.resizeable img{
width: 100%;
height: 100%;
}
</style>
<div class="resizeable" style="width: 750px; height: 258px">
<img src="http://upload.wikimedia.org/wikipedia/commons/a/aa/Logo_Google_2013_Official.svg" alt="" />
</div>
<script>
function Resizeable(element) {
this.element = element;
this.resizer = document.createElement('div');
this.resizer.className = 'resizer';
this.element.appendChild(this.resizer);
this.resizer.addEventListener('mousedown', this);
this.startMousePosition = null;
this.startElementDimension = null;
}
Resizeable.prototype.handleEvent = function(event) {
this['handle' + event.type.charAt(0).toUpperCase() + event.type.slice(1) + 'Event'](event);
};
Resizeable.prototype.handleMousedownEvent = function(event) {
if (this.element.setCapture)
this.element.setCapture();
window.addEventListener('mousemove', this);
window.addEventListener('mouseup', this);
this.startMousePosition = {x: event.pageX, y: event.pageY};
this.startElementDimension = {width: this.element.offsetWidth, height: this.element.offsetHeight};
event.preventDefault();
};
Resizeable.prototype.handleMousemoveEvent = function(event) {
var offset = {
x: event.pageX - this.startMousePosition.x,
y: event.pageY - this.startMousePosition.y,
};
console.log(event);
this.element.style.width = this.startElementDimension.width + offset.x + 'px';
this.element.style.height = this.startElementDimension.height + offset.y + 'px';
};
Resizeable.prototype.handleMouseupEvent = function(event) {
window.removeEventListener('mousemove', this);
window.removeEventListener('mouseup', this);
if (this.element.releaseCapture)
this.element.releaseCapture();
this.startMousePosition = null;
};
new Resizeable(document.querySelector('.resizeable'));
</script>
Для работы в IE8 нужен костыль для addEventListener |
Рабочий вариант есть и на сайте. Хотелось бы понять, почему мой вариант не работает в Mozilla. У меня пока небольшой опыт работы с jQuery
|
Цитата:
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div style="width:503px;height:285px;background-color:grey;position:relative" id="skin">
<img style="width:500px;height:282px;position:absolute" id="heroes" src="http://javascript.ru/forum/attachments/jquery/2136d1394200133t-problema-s-zakhvatom-myshyu-heroes-jpg">
<img style="position:absolute;right:0;bottom:0" id="corner" src="http://javascript.ru/forum/attachments/jquery/2137d1394200133-problema-s-zakhvatom-myshyu-handle-se-png">
</div>
<div id="info"></div>
<script>
function Resizeable(options) {
var elem = options.elem;
elem.move=false;
elem.on('mousedown', capture);
*!*
//mousemove и mouseup нужно отслеживать на документе а не конкретно на этом элементе.
$(document).on('mousemove', cursorMove);
$(document).on('mouseup', release);
*/!*
function capture(e){
if($(e.target).attr('id')=='corner' && elem.move==false){
elem.move=true;
getCoords(e);
console.log(elem.x+' '+elem.y);
return false;
}
}
function cursorMove(e){
if(elem.move==true){
size($('#skin'), e);
size($('#heroes'), e);
}
getCoords(e);
}
function release(e){
elem.move=false;
}
function size(rect, e){
rect.css('height',rect.height()-(elem.y-e.pageY))
.css('width',rect.width()-(elem.x-e.pageX));
}
function getCoords(e){
elem.x=e.pageX;
elem.y=e.pageY;
}
}
*!*
//тут строчку нужно было дописать
*/!*
Resizeable({'elem': $('#corner')});
</script>
</body>
</html>
|
Zuenf,
неплохобы return false поставить в строку 38 а то браузер картинку копирует |
рони, поправил.
|
:write:
ещё можно убрать строку 35 и стиль из строки 10 и заменить на
<style type="text/css">
#skin #heroes{
width: 100%;
height: 100%;
}
</style>
|
Если уж так хочется jQuery, то есть готовое: http://jqueryui.com/resizable/
|
Zuenf, вот как раз такой вариант у меня в Mozille и не работает. Я зацепляю мышью за угол, сдвигаю, отпускаю мышь, после этого размер резко меняется, и дальше меняется плавно, хотя мышь не зажата; а хотелось бы без этого бага. А насчёт строчки
Resizeable({'elem': $('#corner')}); - по ошибке удалил при отправке сообщения. У меня была Resizeable({'elem': $('html')}); danik.js, спасибо, но хочется для начала освоить базовый js без надстроек. |
Добавил в 24 строке запрет переноса элементов.
|
Цитата:
Цитата:
Цитата:
|
Цитата:
30 строка добавил. |
Спасибо, Zuenf.
danik.js, конечно я имел ввиду jQuery без надстроек (описАлся). А про DOM я читал на этом сайте и более или менее понял (даже примеры делал) |
Сделал опцию сохранения пропорции (жмём Shift в процессе ресайза).
И обертка создается автоматом.
<!DOCTYPE html>
<style>
.resizeable{
position: relative;
display: inline-block;
overflow: hidden;
min-width: 16px;
min-height: 16px;
}
.resizeable .resizer{
position: absolute;
bottom: 0;
right: 0;
width: 16px;
height: 16px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEX///9/f38/Pz8NdHQxAAAAAXRSTlMAQObYZgAAAC9JREFUeNpNyDENADAMBLGoY5mESuAFwwOtvPWGG1z1d+xaW9CiQSxBiwY1Clo0D+HwCieH9fp/AAAAAElFTkSuQmCC);
cursor: se-resize;
}
</style>
<img width="200" height="193" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/86/TUX-G2-SVG.svg/610px-TUX-G2-SVG.svg.png" alt="" />
<script>
function Resizeable(element, preserveAspectRatio) {
if (!(this instanceof Resizeable))
return new Resizeable(element, preserveAspectRatio);
this.top = NaN;
this.left = NaN;
this.preserveAspectRatio = Boolean(preserveAspectRatio);
this.aspectRatio = element.offsetWidth / element.offsetHeight;
this.element = element;
this.wrapper = document.createElement('div');
this.wrapper.className = 'resizeable';
this.resizer = document.createElement('div');
this.resizer.className = 'resizer';
this.resizer.addEventListener('mousedown', this);
element.parentNode.replaceChild(this.wrapper, element);
this.wrapper.appendChild(element);
this.wrapper.appendChild(this.resizer);
}
Resizeable.prototype.resize = function(width, height) {
width = width > 0 ? width : 0;
height = height > 0 ? height : 0;
if (this.preserveAspectRatio) {
if (width > height) {
width = height * this.aspectRatio;
} else {
height = width / this.aspectRatio;
}
}
this.element.style.width = width + 'px';
this.element.style.height = height + 'px';
};
Resizeable.prototype.handleEvent = function(event) {
switch (event.type) {
case 'mousedown':
return this.handleMouseDownEvent(event);
case 'mousemove':
return this.handleMouseMoveEvent(event);
case 'mouseup':
return this.handleMouseUpEvent(event);
}
};
Resizeable.prototype.handleMouseDownEvent = function(event) {
if (this.resizer.setCapture)
this.resizer.setCapture();
document.addEventListener('mousemove', this);
document.addEventListener('mouseup', this);
this.top = event.pageX - this.element.offsetWidth;
this.left = event.pageY - this.element.offsetHeight;
event.preventDefault();
};
Resizeable.prototype.handleMouseMoveEvent = function(event) {
this.resize(event.pageX - this.top, event.pageY - this.left);
};
Resizeable.prototype.handleMouseUpEvent = function(event) {
document.removeEventListener('mousemove', this);
document.removeEventListener('mouseup', this);
if (this.resizer.releaseCapture)
this.resizer.releaseCapture();
this.top = NaN;
this.left = NaN;
};
Resizeable.prototype.setPreserveAspectRatio = function(preserveAspectRatio) {
if (this.preserveAspectRatio != preserveAspectRatio) {
this.preserveAspectRatio = preserveAspectRatio;
this.resize(this.element.offsetWidth, this.element.offsetHeight);
}
}
var resizeable = new Resizeable(document.querySelector('img'), false);
var shiftKeyListener = function(event) {
resizeable.setPreserveAspectRatio(event.shiftKey);
};
document.addEventListener('keydown', shiftKeyListener);
document.addEventListener('keyup', shiftKeyListener);
window.focus();
</script>
|
Цитата:
|
danik.js,
а понял сначала нажать Shift до ресайза - если в процессе то никак |
Цитата:
Цитата:
|
| Часовой пояс GMT +3, время: 09:32. |