我是d3的新手,我知道react和d3之间可能会有一些冲突,这可能是其中之一。
我有一个svg,它实现了d3中的可缩放行为。我想让svg中的元素可拖动。我的第一次尝试是在控制台中放置一个onClick侦听器记录一些东西,但它不起作用。你能解释一下我在这里错过了什么吗?我怀疑d3的缩放行为劫持了click事件。谢谢。下面是代码:
带缩放的网格。
import React, { useState, useEffect, useRef } from 'react'
import * as d3 from 'd3';
import Rect from './Rect';
import './d3-grid.css';
const zoomBehaviour = (width, height, gridSize, gridRef) => d3
.zoom()
.scaleExtent([0.5, 2])
.translateExtent([[0, 0], [width, height]])
.on('zoom', (event) => {
const svg = d3.select(gridRef.current)
svg.select('#grid-pattern')
.attr('x', event.transform.x)
.attr('y', event.transform.y)
.attr('width', gridSize * event.transform.k)
.attr('height', gridSize * event.transform.k)
.selectAll('line')
.attr('opacity', Math.min(event.transform.k, 1));
d3.selectAll('g').attr('transform', event.transform);
})
const D3Grid = ({ data, width, height }) => {
const [shapes, setShapes] = useState(data);
const svgGridRef = useRef();
const content = useRef();
const gridSize = 25;
const gridColor = '#a4a4a4';
useEffect(() => {
const svg = d3.select(svgGridRef.current);
var pattern = svg.append('pattern')
.attr('id', 'grid-pattern')
.attr('patternUnits', 'userSpaceOnUse')
.attr('x', 0)
.attr('y', 0)
.attr('width', gridSize)
.attr('height', gridSize);
pattern.append('line')
.attr('stroke', gridColor)
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', gridSize * 16)
.attr('y2', 0);
pattern.append('line')
.attr('stroke', gridColor)
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', 0)
.attr('y2', gridSize * 16);
svg.append('rect')
.attr('fill', 'url(#grid-pattern)')
.attr('width', '100%')
.attr('height', '100%');
return () => {
// Clean up any D3 elements or listeners
};
}, [])
useEffect(() => {
const svg = d3.select(svgGridRef.current);
svg.call(zoomBehaviour(width, height, gridSize, svgGridRef));
return () => {
svg.on('.zoom', null);
};
}, []);
return (
<svg
className='main-svg'
ref={svgGridRef}
viewBox={`0 0 ${width} ${height}`}
>
{
shapes.map((shape, index) => (
<Rect
key={index}
id={shape.id}
fill={shape.fill}
rx={shape.rx}
width={shape.width}
height={shape.height}
x={shape.posX}
y={shape.posY}
/>
))
}
</svg >
)
}
export default D3Grid
字符串
Rect组件。我尝试了g元素和rect元素。没有工作。
const Rect = (props) => {
return (
<g onClick={(event) => { console.log({ event }); }}>
<rect {...props} onClick={(event) => { console.log({ event }); }} />
</g>
)
}
export default Rect
型
1条答案
按热度按时间chy5wohz1#
在您的代码中,useEffect钩子将在Rect组件渲染后触发,这意味着useEffect中的模式和相关背景rect将在Rect组件的顶部渲染。然后,它们阻止事件传播到下面的rect组件。
要解决这个问题,有两个选择。第一个是将模式的“pointer-events”属性和相关内容设置为“none”,第二个是将这些内容放在底部。下面是现场演示。Int screen shotdemo link
字符串