Думаю, я понял, что ты ищешь. Есть несколько вещей, которые следует учитывать при решении этой проблемы:
Масштабирование ViewBox
Это основной вопрос, который необходимо учитывать. Поскольку вы используете свойство viewBox
в своем элементе svg и не используете width / height
, то независимо от размера окна браузера будет изменяться масштаб видимого холста svg. Это важно учитывать при отбрасывании клонированного изображения, поскольку вы не можете использовать абсолютные top / left
координаты. Это может выглядеть нормально на 0, 0
, но когда вы начнете отходить от него, вы заметите, что изображение не пропадает там, где вы думаете, что оно должно быть.
Способ обойти это - использовать d3.scaleLinear()
(документы здесь ). Это поможет перевести сбрасываемые координаты в координаты вашего SVG. То, как я это сформулировал, заключается в том, что для шкалы X значение domain
относится к свойству SVG left
к свойствам left + width
, а range
устанавливается к значениям viewbox x-min
и width
вашего SVG. , Аналогичный подход используется для шкалы Y (см. Код).
Где SVG находится на вашей странице
Это следующая вещь, которую следует рассмотреть. Это соответствует предыдущему пункту о окне просмотра. Например, если у SVG есть несколько полей, вам необходимо учитывать это при настройке шкалы d3.scaleLinear()
. Для этого нужно использовать getBoundingClientRectangle()
следующим образом:
const clientRect = document.getElementById('floor').getBoundingClientRect();
Если размер окна изменен
Если размер окна изменен, вам необходимо выполнить сброс шкалы.
Где вы берете изображение из перетаскиваемого элемента
Это может добавить некоторую работу, если вы хотите выяснить, как получить смещение x, y где вы взяли изображение, когда вы впервые захватили его с помощью мыши. Вместо этого я использую свойство cursorAt
в конфигурации метода draggable()
и задаю для него значение { left: 0, top: 0 }
, поэтому при перетаскивании изображения пользователь увидит курсор в левом верхнем углу изображения. Это избавляет вас от необходимости выяснять смещение места, где они захватили изображение.
Вот код, который я использовал в конце (ручка здесь ) (также мне пришлось используйте другой значок, потому что тот, который вы использовали, не загружался для меня).
let scaleX = getScaleX();
let scaleY = getScaleY();
function getScaleX() {
const clientRect = document.getElementById('floor').getBoundingClientRect();
return d3.scaleLinear()
.domain([clientRect.left, clientRect.left + clientRect.width])
.range([0, 1500])
}
function getScaleY() {
const clientRect = document.getElementById('floor').getBoundingClientRect();
return d3.scaleLinear()
.domain([clientRect.top, clientRect.top + clientRect.height])
.range([0, 800])
}
window.onresize = function() {
scaleX = getScaleX();
scaleY = getScaleY();
};
var svg = d3.select('#floor');
svg.append("svg:image")
.attr('xlink:href', 'https://wallpapershome.com/images/pages/pic_h/241.jpg')
.style('width', "100%");
$(function() {
$("#draggable" ).draggable({
helper: "clone",
cursor: 'move',
containment: "document",
cursorAt: { top: 0, left: 0 }
});
$( "#droppable" ).droppable({
drop: function( event, ui ) {
$( this ).addClass( "ui-state-highlight" );
svg.append("svg:image")
.attr('xlink:href', 'https://i2.wp.com/icons.iconarchive.com/icons/cornmanthe3rd/plex/512/Communication-RSS-icon.png')
.attr('x', scaleX(event.pageX))
.attr('y', scaleY(event.pageY))
.attr('width', '50px');
}
});
});