There is a design consisting of an image, two buttons for its zoom, and green dots located on top of the blue marks in the image itself.

It is necessary to make the green points positioned on the blue marks, even when changing the image scale.

At the moment, when changing the position of the points in proportion to the zoom, I get a deviation from the blue marks. With more manipulations with the zoom, the deviation of the position of the green dots from the blue marks only increases.

Code example:

$(".zoo_in").click(function() { var width = $('.img').width(); width = width * 1.1; $('.img').css({ "width": width }); $('.point').each(function(i, elem) { l = $(this).css('left'); l = parseInt(l); $(elem).css({ "left": l * 1.1 }); t = $(this).css('top'); t = parseInt(t); $(elem).css({ "top": t * 1.1 }); }); }); $(".zoom_out").click(function() { var width = $('.img').width(); width = width / 1.1; $('.img').css({ "width": width }); $('.point').each(function(i, elem) { l = $(this).css('left'); l = parseInt(l); $(elem).css({ "left": l / 1.1 }); t = $(this).css('top'); t = parseInt(t); $(elem).css({ "top": t / 1.1 }); }); }); 
 body { width: 1080px; height: 1080px; margin: 0 auto; text-align: center; } .img { width: 900px; height: 900px; background: url(http://fs214.www.ex.ua/show/283368708529/263754406/263754406.png?800); background-repeat: no-repeat; background-size: 100%; } .zoo_in { width: 40px; font-size: 40px; position: absolute; top: 265px; z-index: 2; left: 55px; background: white; } .zoom_out { width: 40px; font-size: 40px; position: absolute; z-index: 2; top: 265px; left: 250px; background: white; } .points { position: absolute; z-index: 3; top: 0; } .point_1 { width: 10px; height: 10px; border-radius: 100%; background: green; position: relative; top: 49px; left: 216px; } .point_2 { width: 10px; height: 10px; border-radius: 100%; background: green; position: relative; top: 130px; left: 220px; } .point_3 { width: 10px; height: 10px; border-radius: 100%; background: green; position: relative; top: 15px; left: 241px; } .point_4 { width: 10px; height: 10px; border-radius: 100%; background: green; position: relative; top: 228px; left: 154px; } .point_5 { width: 10px; height: 10px; border-radius: 100%; background: green; position: relative; top: 275px; left: 348px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <body> <div class="img"></div> <div class="zoo_in">+</div> <div class="zoom_out">-</div> <div class="points"> <div class="point_1 point"></div> <div class="point_2 point"></div> <div class="point_3 point"></div> <div class="point_4 point"></div> <div class="point_5 point"></div> </div> </body> 

Is it possible to somehow remove the deviations in the distance, or at least minimize very much?

    2 answers 2

    In fact, in order for your code to work, it’s enough to change the position: relative; property of the points position: relative; on position: absolute; and add margin: -5px; for positioning from the center, and then re-adjust the coordinates.

    But I would recommend that you rewrite your code:

    1. arrange the script in the form of a reusable module;
    2. do what Mihanik71 says , and store the coordinates of points in the array;
    3. make common styles for points in a single class;
    4. develop a class naming methodology.

    It turns out something like this:

     (function($) { function customMap($target, options) { /** * Инициализация конструкции: * - для начала соберем координаты всех размещенных точек; * - и сохраним размеры изображения, это будет эталонный масштаб; */ var self = this; self.pointCoordSet = []; self.$img = $(options.img, $target); self.$pointSet = $(options.point, $target); self.mapWidth = self.$img.width(); self.mapHeight = self.$img.height(); self.scale = 1; self.$pointSet.each(function() { var $point = $(this); self.pointCoordSet.push({ left: parseInt($point.css('left'), 10), top: parseInt($point.css('top'), 10) }); }); /** * Добавляем слушателей событий */ $(options.zoomIn, $target).click(function() { self.zoomIn(); }); $(options.zoomOut, $target).click(function() { self.zoomOut(); }); } customMap.prototype.changeScale = function(scale) { var self = this; self.$img.css({ width: self.mapWidth * scale, height: self.mapHeight * scale }); self.$pointSet.each(function(i) { var $point = $(this); $point.css({ left: self.pointCoordSet[i].left * scale, top: self.pointCoordSet[i].top * scale }); }); self.scale = scale; }; customMap.prototype.zoomIn = function() { var self = this; self.changeScale(this.scale + .1); }; customMap.prototype.zoomOut = function() { var self = this; self.changeScale(this.scale - .1); }; var methods = { init: function(options) { var settings = $.extend({}, $.fn.customMap.defaults, options); return this.each(function() { var $target = $(this); if (!$target.data('customMap')) { $target.data('customMap', new customMap($target, settings)); } }); }, changeScale: function(scale) { return this.each(function() { var $target = $(this); if ($target.data('customMap')) { $target.data('customMap').changeScale(scale); } else { $.error('customMap not init'); } }); }, zoomIn: function(scale) { return this.each(function() { var $target = $(this); if ($target.data('customMap')) { $target.data('customMap').zoomIn(scale); } else { $.error('customMap not init'); } }); }, zoomOut: function(scale) { return this.each(function() { var $target = $(this); if ($target.data('customMap')) { $target.data('customMap').zoomOut(scale); } else { $.error('customMap not init'); } }); } }; $.fn.customMap = function() { if (arguments.length && methods[arguments[0]]) { return methods[arguments[0]].apply(this, Array.prototype.slice.call(arguments, 1)); } else { return methods.init.apply(this, arguments); } } $.fn.customMap.defaults = { img: '.custom-map_img', zoomIn: '.custom-map_zoom-in', zoomOut: '.custom-map_zoom-out', point: '.custom-map_point' } })(jQuery); // Применение (function($) { $('.js-map').customMap(); $('.js-map').customMap('changeScale', .5); })(jQuery); 
     /* Стили модуля ---------------------------*/ .custom-map { position: relative; width: 500px; height: 300px; overflow: hidden; } .custom-map_img { width: 900px; height: 900px; background: url(http://fs214.www.ex.ua/show/283368708529/263754406/263754406.png?800); background-repeat: no-repeat; background-size: 100%; } .custom-map_zoom-in { width: 40px; font-size: 40px; text-align: center; position: absolute; z-index: 2; bottom: 10px; left: 10px; background: white; cursor: pointer; } .custom-map_zoom-out { width: 40px; font-size: 40px; text-align: center; position: absolute; z-index: 2; bottom: 10px; left: 60px; background: white; cursor: pointer; } .custom-map_points { position: absolute; z-index: 3; left: 0; top: 0; } .custom-map_point { margin: -5px; position: absolute; width: 10px; height: 10px; border-radius: 50%; background: green; } /* Стили для использования ---------------------------*/ .point-1 { top: 42px; left: 200px; } .point-2 { top: 54px; left: 220px; } .point-3 { top: 40px; left: 247px; } .point-4 { top: 262px; left: 159px; } .point-5 { top: 320px; left: 353px; } 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <body> <div class="custom-map js-map"> <div class="custom-map_img"></div> <div class="custom-map_zoom-in">+</div> <div class="custom-map_zoom-out">-</div> <div class="custom-map_points"> <div class="custom-map_point point-1"></div> <div class="custom-map_point point-2"></div> <div class="custom-map_point point-3"></div> <div class="custom-map_point point-4"></div> <div class="custom-map_point point-5"></div> </div> </div> </body> 

    This is a foundation that you can refine and modify to implement your own tasks.

    To improve your own level, I recommend that you familiarize yourself with the following materials:

    And this is for the future https://new.vk.com/bashkos?w=note1981585_11784872

      There are 2 options:

      The first is to store the coordinates of the points in the array - thus you can avoid problems with the accumulation of errors during operations. Those. You need to store the initial coordinates for each point in the array and then simply multiply them by the scale.

      The second is to store the position of points in percent. Those. You need to first put the dot in the right place and then left / parent.width so we get the percentages and we can specify them instead of pixels, but here we need that the parent container would change the size.

      It turns out very even