ОБНОВЛЕНИЕ
Мне наконец-то удалось найти рабочее решение этой проблемы. Zoom включает в себя event.stopPropagation (). Это означает, что любые события в элементах, содержащихся в родительском элементе, не будут «пузыриться» по отношению к родительскому элементу в соответствии с:
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture
Вот как Я понимаю, что это работает, и что я рационализировал, чтобы сделать свое решение функциональным: для чистки событие будет распространяться до элементов-предков. В моем случае я добавил элемент 'rect' в svg, как показано в примерах, и добавил поведение zoom к прямоугольнику. Поэтому элемент с действием масштабирования не является родителем элемента с действием bru sh.
Я изменил код, вместо этого прикрепив поведение масштабирования к svg (а не к прямоугольнику), чтобы это предок группового элемента с действием bru sh, это позволит действию на элемент g всплыть до svg. Теперь зум также может сработать, так как событие всплывет из элемента g.
Затем я поставил галочку, чтобы проверить, был ли нажат элемент управления, и в зависимости от результата я запустил соответствующий зум или bru * 1045. * функция. Я предполагаю, что другой метод может заключаться в том, чтобы проверить исходное событие, запущенное, и затем запускать только в том случае, если это событие было тем, которое мы хотим активировать, или масштабирование, или действие bru sh.
Добрый день,
У меня возникла проблема, когда действие масштабирования потребляет события на линейном графике. Я видел несколько примеров использования контекста и фокуса, а также масштабирования и перетаскивания с дискретными элементами, но ни одного с разрешением масштабирования и чистки на одной и той же линии / диаграмме области.
Цель: Для разрешить пользователю либо удерживать клавиши ctrlKey или shiftKey, чтобы включить панорамирование, и без удержания клавиши нажатой диаграмма будет панорамировать (используя d3-zoom).
Проблема: Масштабирование потребляет события согласно документации d3. js. Это предотвращает запуск чистки. Это означает, что даже если я использую фильтр и разрешу использовать ctrlKey, а затем использую блок if, чтобы определить, была ли нажата ctrlKey или нет, событие все равно никогда не будет передано обработчику масштабирования в bru sh .
Я заметил, что в ранних версиях d3 (кажется, до v4) это сосуществование событий не было проблемой для моего варианта использования, но, похоже, вызывало проблемы с одновременным срабатыванием нескольких событий для другого использования. - случаи, которые вызывали проблемы. Похоже, что для разрешения проблем в поведении d3-zoom были реализованы предотвращение дефолта и остановка пропуска. Это предотвращает распространение события на обработчик bru sh и последующее использование настраиваемой логики c для масштабирования (в моем случае просто панорамирования) или bru sh.
Вопрос: Кто-нибудь знает какие-либо средства, позволяющие распространяться событиям без изменения самого кода d3. js? Мне бы очень хотелось иметь возможность панорамирования или масштабирования в зависимости от того, нажата ли клавиша ctrlKey, без использования переключателя для отключения событий указателя.
Код:
const MARGIN = { TOP: 10, BOTTOM: 80, LEFT: 120, RIGHT: 10 }
const WIDTH = 1000 - MARGIN.LEFT - MARGIN.RIGHT;
const HEIGHT = 500 - MARGIN.TOP - MARGIN.BOTTOM;
svg = d3.select(element.current)
.append("svg")
.attr("width", WIDTH + MARGIN.LEFT + MARGIN.RIGHT)
.attr("height", HEIGHT + MARGIN.TOP + MARGIN.BOTTOM);
graph = svg.append("g")
.attr("transform", `translate(${MARGIN.LEFT-50}, ${MARGIN.TOP})`)
.attr("class", "graph")
svg.append("defs")
.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", WIDTH )
.attr("height", HEIGHT );
x = d3.scaleTime()
.range([0, WIDTH]);
y = d3.scaleLinear()
.range([HEIGHT , 0]);
panBehaviour = d3.zoom()
.extent([[0, 0], [WIDTH, HEIGHT]])
.translateExtent([[0, 0], [WIDTH, HEIGHT]])
.scaleExtent([1, 1])
.filter( ()=>!d3.event.button)
.on('zoom', panPlot)
pan = svg.append('rect')
.attr('class', 'pan')
.attr("transform", `translate(${MARGIN.LEFT-50}, ${MARGIN.TOP})`)
.attr("width", WIDTH )
.attr("height", HEIGHT )
.call(panBehaviour);
brush = d3.brushX()
.extent([ [0, 0], [WIDTH, HEIGHT] ])
.on("end", zoom)
graph.append('g')
.attr('class', 'brush')
.call(brush)
path = graph.append('path');
path.attr("clip-path", "url(#clip)");
// The panning function replaced with a log statement
panPlot() {
if (d3.event.sourceEvent.ctrlKey){
console.log("PANNING");
}
};
// The zoom function replaced with a log statement
zoom(){
if (!d3.event.sourceEvent.ctrlKey){
console.log("ZOOMING");
}
};
Здесь был задан очень похожий вопрос, но без решения. D3 v4 Bru sh и Zoom на одном и том же элементе (без конфликта событий мыши)