我对 d3 相当陌生,我知道 React 和 d3 之间可能存在一些冲突。这可能是其中之一。
我有一个 svg,它实现了 d3 的可缩放行为。我想让 svg 内的元素可拖动。我的第一次尝试是放置一个 onClick 侦听器在控制台中记录某些内容,但它不起作用。你能解释一下我在这里缺少什么吗?我怀疑 d3 缩放行为劫持了点击事件。谢谢。 下面是代码:
具有缩放功能的网格。
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
矩形组件。我尝试了 g 元素和 rect 元素。没有工作。
const Rect = (props) => {
    return (
        <g onClick={(event) => { console.log({ event }); }}>
            <rect {...props} onClick={(event) => { console.log({ event }); }} />
        </g>
    )
}
export default Rect            Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
在您的代码中,useEffect 钩子将在 Rect 组件渲染后被触发,这意味着 useEffect 中的图案和相关背景矩形将渲染在 Rect 组件的顶部。然后,它们阻止事件传播到下面的矩形组件。
要解决这个问题,有两种选择。第一个是将模式的“pointer-events”属性和相关的东西设置为“none”,第二个是将这些东西放在底部。这是现场演示。 Int 屏幕截图 演示链接
const D3Grid = () => { useEffect(() => { const background = svg.select(".background") background.append("pattern"); background.append("rect"); }); return (); }