首页 经验

下载鸿蒙版“诗词速通”,领红包,点此下载


d3js 坐标轴和抛物线(可以拖拽改变形状,复制 删除)

时间: 2024-12-07 17:13:17

(部分内容来自网络,其真实性存疑,为了避免对您造成误导,请谨慎甄别。)

要使用 D3.js 实现带有坐标轴的抛物线,并且可以通过拖拽改变抛物线的形状、复制和删除它,下面是一个完整的示例。

示例代码

以下代码创建了一个 SVG 画布,添加坐标轴,并在上面绘制可拖拽的抛物线。用户可以通过按钮复制、删除抛物线以及拖拽来改变它的形状。

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <script src="https://d3js.org/d3.v7.min.js"></script>  
    <title>D3.js 坐标轴与可拖拽抛物线示例</title>  
    <style>  
        svg {  
            border: 1px solid #ccc;  
        }  
        .curve {  
            fill: none;  
            stroke: orange;  
            stroke-width: 2;  
            cursor: pointer;  
        }  
        .control-point {  
            fill: red;  
            cursor: pointer;  
        }  
    </style>  
</head>  
<body>  
    <button id="addParabola">添加抛物线</button>  
    <button id="deleteParabola">删除抛物线</button>  
    <button id="cloneParabola">复制抛物线</button>  
    <svg width="800" height="400"></svg>  

    <script>  
        const svg = d3.select("svg");  
        const width = +svg.attr("width");  
        const height = +svg.attr("height");  

        // 添加坐标轴  
        const xScale = d3.scaleLinear().domain([0, 800]).range([0, width]);  
        const yScale = d3.scaleLinear().domain([400, 0]).range([0, height]);  
        
        // 绘制 X 轴  
        svg.append("g")  
            .attr("transform", "translate(0," + height + ")")  
            .call(d3.axisBottom(xScale));  
        
        // 绘制 Y 轴  
        svg.append("g")  
            .call(d3.axisLeft(yScale));  

        let parabolas = []; // 存储抛物线的控制点  
        let selectedParabola = null;  

        // 添加抛物线  
        d3.select("#addParabola").on("click", function() {  
            const points = [  
                { x: 100, y: 300 }, // 顶点  
                { x: 400, y: 100 }, // 控制点  
                { x: 700, y: 300 }  // 终点  
            ];  
            parabolas.push(points);  
            renderParabola(points);  
        });  

        // 渲染抛物线  
        function renderParabola(points) {  
            const lineGenerator = d3.line()  
                .curve(d3.curveBasisX)  
                .x(d => xScale(d.x))  
                .y(d => yScale(d.y));  

            // 绘制抛物线路径  
            const path = svg.append("path")  
                .attr("class", "curve")  
                .attr("d", lineGenerator(points))  
                .on("click", function() {  
                    if (selectedParabola) {  
                        selectedParabola.classed("selected", false);  
                    }  
                    selectedParabola = d3.select(this);  
                    selectedParabola.classed("selected", true);  
                })  
                .call(d3.drag()  
                    .on("start", dragstarted)  
                    .on("drag", dragged)  
                    .on("end", dragended));  

            // 绘制控制点  
            const controlPoints = svg.selectAll(".control-point")  
                .data(points)  
                .enter().append("circle")  
                .attr("class", "control-point")  
                .attr("r", 5)  
                .attr("cx", d => xScale(d.x))  
                .attr("cy", d => yScale(d.y))  
                .call(d3.drag()  
                    .on("start", dragControlPointStarted)  
                    .on("drag", dragControlPointDragged)  
                    .on("end", dragControlPointEnded));  

            // 更新路径  
            function updatePath() {  
                path.attr("d", lineGenerator(points));  
                controlPoints  
                    .attr("cx", d => xScale(d.x))  
                    .attr("cy", d => yScale(d.y));  
            }  

            function dragstarted(event) {  
                d3.select(this).raise();  
            }  

            function dragged(event) {  
                const dx = event.dx * (width / xScale.domain()[1]);  
                const dy = -event.dy * (height / yScale.domain()[1]);  
                points.forEach(p => {  
                    p.x += dx;  
                    p.y += dy;  
                });  
                updatePath();  
            }  

            // 控制点拖拽  
            function dragControlPointStarted(event) {  
                d3.select(this).raise().classed("active", true);  
            }  

            function dragControlPointDragged(event, d) {  
                const newX = xScale.invert(d3.pointer(event)[0]);  
                const newY = yScale.invert(d3.pointer(event)[1]);  
                d.x = newX;  
                d.y = newY;  
                updatePath();  
            }  

            function dragControlPointEnded(event) {  
                d3.select(this).classed("active", false);  
            }  
        }  

        // 删除选中的抛物线  
        d3.select("#deleteParabola").on("click", function() {  
            if (selectedParabola) {  
                selectedParabola.remove();  
                selectedParabola = null;  
                svg.selectAll(".control-point").remove(); // 移除控制点  
                parabolas.pop(); // 从数组中移除抛物线  
            }  
        });  

        // 复制选中的抛物线  
        d3.select("#cloneParabola").on("click", function() {  
            if (selectedParabola) {  
                const selectedPoints = parabolas.find(points => {  
                    const path = svg.selectAll(".curve").nodes().indexOf(selectedParabola.node());  
                    return points === path;  
                });  
                if (selectedPoints) {  
                    const newPoints = selectedPoints.map(p => ({ x: p.x + 20, y: p.y + 10 })); // 复制偏移  
                    parabolas.push(newPoints);  
                    renderParabola(newPoints);  
                }  
            }  
        });  
    </script>  
</body>  
</html>

代码解释

  1. SVG 和坐标轴:

    • 创建一个 800x400 大小的 SVG,并在其上面添加 X 轴和 Y 轴。

  2. 存储抛物线:

    • 用一个数组 parabolas 存储所有的抛物线的控制点,selectedParabola 用于存储当前选中的抛物线。

  3. 添加抛物线:

    • 点击“添加抛物线”按钮时,初始化一条抛物线并在 SVG 上渲染。

  4. 渲染抛物线:

    • 使用 D3 的 line 生成器和 curveBasisX 来创建一条平滑的抛物线,并根据控制点绘制。

  5. 拖拽功能:

    • 通过拖拽事件,用户可以整体改变抛物线的位置,或移动控制点以改变其形状。

  6. 删除和复制抛物线:

    • 可以通过按钮删除当前选中的抛物线,或复制当前选中的抛物线。

使用说明

  1. 添加抛物线: 点击 "添加抛物线" 按钮将创建一条新的抛物线。

  2. 拖动抛物线: 点击并拖动已绘制的抛物线来移动它。

  3. 拖动控制点: 可以拖动红色的控制点来修改抛物线的形状。

  4. 删除和复制: 点击 "删除抛物线" 按钮删除选中的抛物线;点击 "复制抛物线" 按钮将复制选中的抛物线,并略微偏移位置。

将上述代码粘贴到一个 HTML 文件中并在浏览器中打开,就可以体验整个功能。如果你有其他需求或者想了解更多细节,欢迎随时告诉我!

还有问题,向AI提问。


上一个 d3js拖拽添加 三角形 矩形 圆弧 椭圆等曲线 文章列表 下一个 d3js坐标轴的line和text没有显示 需要style

(汉语/英语/日语/法语/德语)语音助手(识别/合成),智能翻译,高中物理动画,数据分析,数据可视化,电话: 18201798243(同v)

最新

工具

© 2019-至今 适观科技

沪ICP备17002269号