Есть несколько вещей:
Первый
d3.event.translate
не содержит значений x и y преобразования, используйте d3.event.transform для полученияэти значения.Объект преобразования имеет свойства x, y и k.
Секунда
Если вы используете .style()
для размещения преобразования, вам нужно указать, что единица измеренияпикселей для смещения:
var t = d3.event.transform;
d3.select("zoomedElement")
.style('transform', 'translate('+t.x+"px,"+t.y + 'px)scale(' + t.k + ')');
В качестве альтернативы, вы можете использовать .attr()
без px
:
var t = d3.event.transform;
d3.select("zoomedElement")
.style('transform', 'translate('+[t.x,t.y]+')scale(' + t.k + ')');
Давайте посмотрим на ваш поршень с этими изменениями (и без степени перевода):
var zoom = d3.zoom()
.scaleExtent([1, 100])
.on('zoom', zoomFn);
d3.select('svg')
.select('g')
.style("transform-origin", "50% 50% 0");
function zoomFn() {
var t = d3.event.transform;
d3.select('svg').select('g')
.style('transform', 'translate('+t.x+"px,"+t.y + 'px)scale(' + t.k + ')');
}
d3.select('svg')
.select('rect')
.call(zoom);
.zoom-layer {
fill: #EEE;
fill-opacity: 0.25;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js"></script>
<svg width="300" height="300">
<g>
<circle cx=150 cy=150 r=20 style="fill:#F22"></circle>
<rect x=0 y=0 width=300 height=300 class="zoom-layer"></rect>
</g>
</svg>
Вы, вероятно, хотите сделать выделение, которое не включает прямоугольник, - оно должно остаться таким же, чтобы вся поверхность SVGостается интерактивным
Третий
Выглядит так, как будто вы хотите перевести экстент, иногда это немного сложно установить. Этот ответ углубляется в степень увеличения / степени масштабирования, но я расскажу, как ограничить ваш круг на экране:
С переводом [0,0] вашегокруг сидит в середине SVG.Если мы переведем [-150, -150], ваш круг будет в верхнем левом углу svg.Если круг центрируется на cx = 150 cy = 150, то верхний левый угол видимой области теперь равен [150,150].Следовательно, справа внизу - [450,450].Видимый экстент: [[150,150],[450,450]]
.
С переводом [150,150] ваш круг находится в правом нижнем углу SVG.Поскольку круг все еще находится в [150,150], нижний правый угол находится в [150,150] (не помогает ясность, что перевод и положение круга имеют одинаковое значение здесь) .Верхний левый угол на [-150,-150]
.В этом случае видимый экстент должен быть: [[-150,-150],[150,150]]
.
. Мы берем экстремумы из пределов видимого экстента, так как это экстент перевода, который сохраняет круг:
var translateExtent = [[-150,-150],[450,450]]
Естественно, если бы у вас были вещи во всех углах, а не в середине, вы бы имели больший экстент.
И мы можем применить к фрагменту все:
var zoom = d3.zoom()
.scaleExtent([1, 100])
.translateExtent([[-150,-150],[450, 450]])
.on('zoom', zoomFn);
d3.select('svg')
.select('g')
.style("transform-origin", "50% 50% 0");
function zoomFn() {
var t = d3.event.transform;
d3.select('svg').select('g')
.style('transform', 'translate('+t.x+"px,"+t.y + 'px)scale(' + t.k + ')');
console.log(t.x,t.y)
}
d3.select('svg')
.select('rect')
.call(zoom);
.zoom-layer {
fill: #aaa;
fill-opacity: 0.25;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="300">
<g>
<circle cx=150 cy=150 r=20 style="fill:#F22"></circle>
</g>
<rect x=0 y=0 width=300 height=300 class="zoom-layer"></rect>
</svg>