Увеличьте изображение при движении мыши: охватывая все углы

Я работаю над масштабированием. Этот масштаб является фиксированным блоком со 100% размера окна и внутри изображения с 200% ширины фиксированного блока.

Этот зум должен работать так:

Когда курсор находится в центре окна, изображение должно быть в центре.Когда курсор находится в верхнем правом углу, изображение должно оставаться в верхнем правом углу окна (поэтому дотянитесь до изображения с помощью угла)Когда курсор находится в среднем нижнем углу, изображение должно центрироваться горизонтально и достигать общего дна, чтобы мы могли видеть среднюю нижнюю часть изображения.И так далее.

Я делаю приближение, но я не могу достичь углов идеально. Это мой фрагмент (см. Комментарии в функции onmousemove):

var Zoom = function(imageZoom) {
  this.urlImage = imageZoom;
  this.img = undefined;
  this.$img = undefined;

  this.init = function() {
    this.loaders("on");
    this.calcs();
  };
  this.calcs = function() {
    var self = this;
    this.img = new Image();
    this.img.onload = function() {
      self.build();
    };
    this.img.src = this.urlImage;
  };
  this.loaders = function(status) {
    switch(status) {
      case "on":
        $('#loader').fadeIn(200);
        break;
      case "off":
        $('#loader').fadeOut(200);
        break;
    }
  };
  this.build = function() {
    var self = this;
    this.$img = $(self.img);
    
    $('#zoom').fadeIn(200).append(this.$img);
    
    this.$img.on('mousedown', function(e) {
      e.preventDefault();
    });
    
    // this is the problematic function
    $('body').on('mousemove', function(e) {
      e.preventDefault();
      // calc the percents of the window where
      var px = 100 * e.pageX / $(window).width(); 
      var py = 100 * e.pageY / $(window).height();

      // calc of the percent pixel of the image
      var fx = self.$img.width() * px / 100;
      var fy = self.$img.height() * py / 100;

      // render it left / 2 and top / 1.5 (the 1.5 value is imaginary!!)
      self.$img.css({'transform': 'translate('+ -(fx/2) +'px, '+ -(fy/1.5)+'px)'});
    });
    self.loaders("off");
  };
};

var zoom = new Zoom("http://dummyimage.com/2000x1230/000/fff");
zoom.init();
#zoom {
	position: fixed;;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 1000000;
	display: none;
}
#zoom img {
	width: 200%;
	height: auto;
	position: absolute;
	cursor: crosshair;
	-webkit-touch-callout: none;
	-webkit-user-select: none;
	-khtml-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">Loading</div>
<div id="zoom"></div>

Проблема в том, что я поставилfx/1.5 так какfx/2 не работает Но горизонтальное значение работает идеально.

Какое значение я могу настроить, чтобы охватить все углы? Почему левое значение (деление пикселей на 2) отлично работает, а верхнее значение - нет?

 Marcos Pérez Gude01 авг. 2016 г., 21:52
Нет проблем, я не тороплюсь с этой задачей, только я застрял. Спасибо ;)
 Marcos Pérez Gude01 авг. 2016 г., 18:57
Я пытаюсь сначала перевести, но с некоторыми изменениями мой окончательный код выглядит так! лол
 Marcos Pérez Gude26 сент. 2016 г., 13:34
Не волнуйтесь, @LGSon, все в порядке, однако, если у вас есть лучшее решение, чем принятый ответ, вы получите награду. Принятый ответ - это хорошо, но не идеально, некоторые горизонтальные позиции не могут быть достигнуты никогда. Спасибо!
 Marcos Pérez Gude09 авг. 2016 г., 13:05
@ LGS нет больше новостей об этом? :(
 Marcos Pérez Gude04 авг. 2016 г., 00:04
Я играл с соотношением сторон, но с плохими результатами. Я ценю вашу помощь. Можно предположить, что изображения будут иметь масштаб эскалации 1: 1 (например, 1000 × 1000), но будет лучше, если мы не сделаем никаких предположений относительно размеров изображения. Спасибо.
 LGSon01 авг. 2016 г., 21:34
Я посмотрю немного позже, сейчас нет времени ... дам знать, когда закончите
 LGSon03 авг. 2016 г., 22:28
Как видите, я разместил ответ, но мне пришлось временно его удалить, так как я также забыл компенсировать соотношение сторон изображения. Это займет больше времени для меня, так как я сейчас немного занят. Если вы проверите мои заметки, которые я добавил после того, как я их удалил, вы увидите, куда я иду с этим.
 Marcos Pérez Gude01 авг. 2016 г., 21:26
Ну, я снова изменилtranslate(), но, очевидно, это не проблема. Как я могу реализовать соотношение сторон здесь, @LGSon?
 LGSon25 сент. 2016 г., 21:43
Я отсутствовал здесь со 2 августа до прошлой недели, поэтому я рад, что вы получили ответы на некоторые вопросы. Не ожидал, что это займет так много времени.
 LGSon01 авг. 2016 г., 18:56
Если я что-то не пропустил, так как область просмотра не квадрат, вам может понадобиться вычислить его соотношение сторон. Кроме того, не будетtranslate лучше использовать?

Ответы на вопрос(2)

что вы можете достичь того, что вы хотите с помощью модификации CSS. Если вы попытаетесь использовать клип, трансформировать и трансформировать масштаб вместе в событии onmousemove, вы можете сместить изображение, как указано в вашем вопросе. Пожалуйста, дайте мне знать, если это желаемое поведение, спасибо.

var divPos = {left:0,top:0};
var offset = $("#loader").offset();
$(document).mousemove(function(e){
  divPos = {
    left: e.pageX - offset.left,
    top: e.pageY - offset.top
  };

  console.log("x:" + divPos.left + " y: " + divPos.top);
});

var Zoom = function(imageZoom) {
  this.urlImage = imageZoom;
  this.img = undefined;
  this.$img = undefined;

  this.init = function() {
    this.loaders("on");
    this.calcs();
  };
  
  this.calcs = function() {
    var self = this;
    this.img = new Image();
    this.img.onload = function() {
      self.build();
    };
  
    this.img.src = this.urlImage;
  };
  this.loaders = function(status) {
    switch(status) {
      case "on":
        $('#loader').fadeIn(200);
        break;
      case "off":
        $('#loader').fadeOut(200);
        break;
    }
  };
  this.build = function() {
    var self = this;
    this.$img = $(self.img);
                
    $('#zoom').fadeIn(200).append(this.$img);
                
    this.$img.on('mousedown', function(e) {
      e.preventDefault();
    });

                
    // this is the problematic function
    $('body').on('mousemove', function(e) {
      e.preventDefault();

      var width = $(self.img).width();
      var height = $(self.img).height();
      // img center calculation
      var imgCenterX = width/2;
      var imgCenterY = height/2;
      // translate calculation
      var tx = imgCenterX-divPos.left;
      var ty = imgCenterY-divPos.top;

      // clip calculation
      var c0 = divPos.top/2;
      var c1 = divPos.left/2 + width/2;
      var c2 = divPos.top/2 + height/2;
      var c3 = divPos.left/2;

      console.log(c0 + ',' + c1 + ',' + c2 + ',' + c3);

      var t = 'translate('+ tx +'px, '+ ty +'px)';
      var c = 'rect('+ c0 +'px,'+ c1 +'px,'+ c2 +'px,'+ c3 +'px)';
      self.$img.css({'transform': t + ' scale(2,2)'});
      self.$img.css({'clip': c});
    });
    self.loaders("off");
  };
};

var zoom = new Zoom("http://dummyimage.com/2000x1230/000/fff");
zoom.init();
#zoom {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1000000;
            display: none;
}
#zoom img {
            width: 100%;
            height: 100%;
            position: absolute;
            cursor: crosshair;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">Loading</div>
<div id="zoom"></div>

 Marcos Pérez Gude11 авг. 2016 г., 08:56
И высота изображения должна бытьauto чтобы избежать деформации
 peebee10 авг. 2016 г., 22:46
Я думаю, что теперь это работает, как вы хотели. Единственной проблемой сейчас является деформация изображения, вызванная различным соотношением сторон div и image.
 peebee10 авг. 2016 г., 22:08
Я постараюсь обновить свой ответ, спасибо за сообщение, я новичок здесь :). А пока, пожалуйста, проверьтеjsfiddle.net/wznpL539/1
 Marcos Pérez Gude10 авг. 2016 г., 21:56
Хм, кажется отличной идеей, но она не работает должным образом, по крайней мере, в этой скрипкеjsfiddle.net/wznpL539 с сенсорным устройством. Сверху, слева и снизу отлично работает, когда с правой стороны нет. Спасибо. Я возбуждаю вас, потому что ваш фантастический способ сделать это.
 Marcos Pérez Gude10 авг. 2016 г., 22:02
Пожалуйста, попробуйте использовать stacksnippets, как я в вопросе, вы должны нажать на иконку фрагмента кода в верхней части редактора. Вы можете добавить javascript, css и html коды, разделенные на три окна с четвертым для предварительного просмотра. Когда все будет в порядке, сохраните запись, и все мы сможем воспроизвести код.
 Marcos Pérez Gude11 авг. 2016 г., 08:40
Если вы видите, в низких разрешениях области просмотра, изображение не достигает больше половины самого себя. В высоких разрешениях работает нормально, но мой код работает точно так же, мой код работает в высоких разрешениях, но плох в высоту в низких разрешениях.
Решение Вопроса

Вы были очень близки Вам просто нужно рассчитать дляimage.height - window.height при получении вертикального процента.

Это также будет работать с различными пропорциями изображения, поскольку при расчете учитывается высота изображения. Ширина не является проблемой, поскольку она всегда вдвое больше ширины окна.

var Zoom = function(imageZoom) {
  this.urlImage = imageZoom;
  this.img = undefined;
  this.$img = undefined;

  this.init = function() {
    this.loaders("on");
    this.calcs();
  };
  this.calcs = function() {
    var self = this;
    this.img = new Image();
    this.img.onload = function() {
      self.build();
    };
    this.img.src = this.urlImage;
  };
  this.loaders = function(status) {
    switch (status) {
      case "on":
        $('#loader').fadeIn(200);
        break;
      case "off":
        $('#loader').fadeOut(200);
        break;
    }
  };
  this.build = function() {
    var self = this;
    this.$img = $(self.img);

    $('#zoom').fadeIn(200).append(this.$img);

    this.$img.on('mousedown', function(e) {
      e.preventDefault();
    });

    // this is the problematic function
    $('body').on('mousemove', function(e) {
      e.preventDefault();

      var wx = $(window).width();
      var wy = $(window).height();
      var iy = self.$img.height();

      var px = e.pageX;
      var py = e.pageY;

      var tx = -1 * (px / wx) * wx;
      var ty = -1 * (py / wy) * (iy - wy);

      self.$img.css({
        'transform': 'translate(' + tx + 'px, ' + ty + 'px)'
      });
    });
    self.loaders("off");
  };
};

var zoom = new Zoom("http://dummyimage.com/2000x1200/000/fff");
zoom.init();
#zoom {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000000;
  display: none;
}
#zoom img {
  width: 200%;
  height: 100%;
  height: auto;
  position: absolute;
  cursor: crosshair;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
body {
  margin: 0;
}
* {
  box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">Loading</div>
<div id="zoom"></div>

В качестве бонуса:

Если вы хотите избавиться от свободного места, оставшегося при высоком соотношении сторон изображения (jsfiddle), вы можете убедиться, что высота изображения по крайней мере равна высоте окна (jsfiddle). Но вам нужно будет установитьwidth: auto в этом случае изображение не всегда будет в два раза шире окна.

 Ozan12 авг. 2016 г., 20:57
Добро пожаловать. Просто сделайте предположение: если у вас есть другие элементы в вашем живом примере (я полагаю, что у вас есть, так как у вас есть проблемы, которых нет в фрагменте), проблема может быть вызвана установкой размеров блока и / или заполнением / полем значений к некоторым другим элементам, влияющим на размещение изображения.
 Ozan11 авг. 2016 г., 12:47
Если вы можете поделиться своим тестовым кодом с проблемами, я могу взглянуть на него, чтобы попытаться выяснить, в чем проблема. Расчеты ширины в коде не так специфичны, как могли бы быть, они упрощены, поскольку ширина изображений всегда считается двойной ширины окна.
 Marcos Pérez Gude15 авг. 2016 г., 12:56
Нет, размер рамки установлен на рамку рамки на всей странице :(
 Ozan11 авг. 2016 г., 12:36
@ MarcosPérezGude, я изменил изображение во фрагменте, и это кажется хорошим. В чем проблема?
 Marcos Pérez Gude11 авг. 2016 г., 08:42
Мне нужно сделать тест, но это действительно хорошо. Мой upvote, пока я его реализую.
 Marcos Pérez Gude11 авг. 2016 г., 12:50
Да, эта предпосылка верна, изображение всегда будет200% родительской ширины, поэтому переменная неизвестного размера является высотой. Сейчас я не могу поделиться с вами URL-адресом, возможно, через час или два я могу дать вам URL-адрес для его проверки. Еще раз спасибо
 Marcos Pérez Gude11 авг. 2016 г., 12:42
Во фрагменте все идеально, в моей реализации (я точно копирую ваши расчеты) правая сторона не полностью достигнута, и изображение, которым я делюсь с вами, имеет широкую правую сторону, поэтому очень раздражает, что пользователь не может добраться до правой сторона изображения. Я проверю еще раз, когда приеду домой, и, вероятно, это ответ с щедростью. Может быть, мой код создает конфликты. Еще раз спасибо!
 Marcos Pérez Gude12 авг. 2016 г., 19:28
Хорошо, наконец-то я все заработал, но мне нужно компенсировать некоторые несоответствия'left': '-5%', Я не знаю, почему правая сторона не достигает полностью. Однако это верный ответ. Вы получите награду;) Спасибо!

Ваш ответ на вопрос