Maison  >  Questions et réponses  >  le corps du texte

React + d3 - Pourquoi mon élément <g> ne répond-il pas à l'écouteur onClick

Je suis assez nouveau sur d3 et je sais qu'il peut y avoir des conflits entre React et d3. C'est peut-être l'un d'entre eux.

J'ai un svg qui implémente le comportement évolutif de d3. Je veux rendre les éléments à l'intérieur du svg déplaçables. Ma première tentative a été de mettre un écouteur onClick pour enregistrer quelque chose dans la console, mais cela n'a pas fonctionné. Pouvez-vous expliquer ce qui me manque ici ? Je soupçonne que le comportement de mise à l'échelle d3 détourne l'événement click. Merci. Voici le code :

Grille avec fonction zoom.

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

Composant rectangulaire. J'ai essayé les éléments g et les éléments rect. pas de travail.

const Rect = (props) => {
    return (
        <g onClick={(event) => { console.log({ event }); }}>
            <rect {...props} onClick={(event) => { console.log({ event }); }} />
        </g>

    )
}

export default Rect

P粉504080992P粉504080992236 Il y a quelques jours447

répondre à tous(1)je répondrai

  • P粉773659687

    P粉7736596872024-01-30 00:06:32

    Dans votre code, le hook useEffect sera déclenché après le rendu du composant Rect, ce qui signifie que le motif et le rectangle d'arrière-plan associé dans useEffect seront rendus au-dessus du composant Rect. Ils empêchent alors l'événement de se propager au composant rectangulaire sous-jacent.

    Pour résoudre ce problème, il existe deux options. La première consiste à définir la propriété "pointer-events" du mode et les éléments associés sur "aucun", et la seconde consiste à placer ces éléments en bas. Il s'agit d'une démonstration en direct. Int Capture d'écran Lien démo

    const D3Grid = () => {
      useEffect(() => {
        const background = svg.select(".background")
        background.append("pattern");
        background.append("rect");
      });
      return (
        
        {...rects}
      );
    }

    répondre
    0
  • Annulerrépondre