D3渲染坐标文字防止重叠

23 阅读1分钟
<!DOCTYPE html>
<html>
<head>
    <title>D3 Canvas Text Collision</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
    <canvas id="myCanvas" width="600" height="600"></canvas>

    <script>
        const data = [
            {
                "name": "你在干嘛",
                "x": 233.0,
                "y": 131.0,
                "id": "1",
                "color": "#ffffff"
            },
            {
                "name": "东西呢",
                "x": 156.0,
                "y": 891.0,
                "id": "2",
                "color": "#000000"
            },
            {
                "name": "桌子上",
                "x": 453.0,
                "y": 465.0,
                "id": "3",
                "color": "#ff0"
            },
            {
                "name": "我看见了",
                "x": 233.0,
                "y": 131.0,
                "id": "4",
                "color": "#f0f"
            },
            {
                "name": "OK",
                "x": 158.0,
                "y": 131.0,
                "id": "5",
                "color": "#f00"
            }
        ];

        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        
        const textPadding = 5; // 在文字周边填充防止文字重叠

        data.forEach(d => {
            ctx.fillText(d.name, d.x, d.y);
        });

        function detectCollision(text1, text2) {
            return Math.abs(text1.x - text2.x) < (ctx.measureText(text1.name).width + textPadding) &&
                   Math.abs(text1.y - text2.y) < parseInt(ctx.font) + textPadding;
        }

        for (let i = 0; i < data.length; i++) {
            for (let j = i + 1; j < data.length; j++) {
                if (detectCollision(data[i], data[j])) {
           
                    data[j].y += parseInt(ctx.font) + textPadding;
                }
            }
        }

    
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        data.forEach(d => {
            ctx.fillText(d.name, d.x, d.y);
        });
    </script>
</body>
</html>