d3js 鼠标 绘制 可编辑的折线

最终效果:


点击 “绘线”开启绘线模式,点击屏幕开始绘制折线。再次点击关闭绘线功能

点击“”编辑“开启关闭线编辑功能,编辑功能下,线为虚线,且可拖动圆点编辑路径。非编辑模式下,线为实线不可编辑。

点击“删除”删除折线。

可以在下拉列表中选择不同的样式,改变折线样式。

代码:

<!--
参考:
http://bl.ocks.org/mbostock/4342190
增加点
http://bl.ocks.org/mbostock/3902569
-->

<!DOCTYPE html>
<meta charset="utf-8">
<title>Spline Editor</title>
<style>

    body {
        font: 13px sans-serif;
        position: relative;
        width: 960px;
        height: 500px;
    }

    form {
        position: absolute;
        bottom: 10px;
        left: 10px;
    }


    circle,
    .line {
        fill: none;
        stroke: steelblue;
        stroke-width: 1.5px;
    }

    circle {
        fill: #fff;
        fill-opacity: .2;
        cursor: move;
    }

    .selected {
        fill: #ff7f0e;
        stroke: #ff7f0e;
    }

</style>
<form>
    <label for="interpolate">样式:</label>
    <select id="interpolate"></select><br>

    <input type='button' class='btn-text' id ='gis_del' value='删除' />
    <input type='button' class='btn-text' id ='gis_edit' value='编辑' />
    <input type='button' class='btn-text' id ='drag_line' value='绘线' />
</form>
<script src="d3.v3.min.js"></script>
<script src="jquery-1.9.1.js"></script>
<script>

    var width = 960,
            height = 500;

    var points = []


    var dragged = null;     //拖拽的热点
    var selected = points[0];   //当前选中的热点
    var lineSelect = false; //线路选中

    var isDrawingLine = false;
    var gis_edit = false;


    $("#drag_line").click(function(){

        if(isDrawingLine){
            isDrawingLine = false;
        }else {
            isDrawingLine = true;
        }

    });

    $("#gis_edit").click(function(){
        //removeHotPoint();
        if(gis_edit){
            gis_edit = false;

            d3.selectAll("circle").remove();
            d3.select("path").style("stroke-dasharray",null)
        }else {
            gis_edit = true;
        }
    });

    $("#gis_del").click(function(){

        points = [];
        redraw();

    });

    var line = d3.svg.line();

    var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height)
            .attr("tabindex", 1)
            .on("mousedown", mousedown);


    svg.append("path")
            .datum(points)
            .attr("class", "line")
            .call(redraw);

    d3.select(window)
            .on("mousemove", mousemove)
            .on("mouseup", mouseup)
            .on("keydown", keydown);

    d3.select("#interpolate")
            .on("change", change)
            .selectAll("option")
            .data([
                "linear",
                "step-before",
                "step-after",
                "basis",
                "basis-open",
                "basis-closed",
                "cardinal",
                "cardinal-open",
                "cardinal-closed",
                "monotone"
            ])
            .enter().append("option")
            .attr("value", function(d) { return d; })
            .text(function(d) { return d; });

    svg.node().focus();


    //点击线路,开启编辑模式
    function lineOnClick() {
        if(gis_edit){
            d3.select(this)
                    .style("stroke-dasharray","10 5")

            drawHotPoint();
        }
    }

    //绘制线路拖动点
    function  drawHotPoint() {
        svg.selectAll("circle")
                .data(points, function(d) { return d; })
                .enter().append("circle")
                .on("mousedown", function(d) { selected = dragged = d; redraw(); })
                .attr("r", 6.5)
                .attr("cx", function(d) { return d[0]; })
                .attr("cy", function(d) { return d[1]; });
    }

    //重新绘制折线
    function redraw() {
        svg.select("path")
                .attr("d", function (d,i) {
                    return line(points);
                })
                .style("stroke-dasharray","10 5")
                .on("click", lineOnClick)      //全局鼠标点击
                .on("mouseover", function(d,i) {
                    d3.select(this).style("stroke-width",3)
                    lineSelect = true
                })
                .on("mouseout", function(d,i) {
                    d3.select(this).style("stroke-width",1)
                    lineSelect = false
                });

        var circle = svg.selectAll("circle")
                .data(points, function(d) { return d; });

        circle.enter().append("circle")
                .attr("r", 1e-6)
                .on("mousedown", function(d) { selected = dragged = d; redraw(); })
                .transition()
                .duration(750)
                .ease("elastic")
                .attr("r", 6.5);

        circle
                .classed("selected", function(d) { return d === selected; })
                .attr("cx", function(d) { return d[0]; })
                .attr("cy", function(d) { return d[1]; });

        circle.exit().remove();

        if (d3.event) {
            d3.event.preventDefault();
            d3.event.stopPropagation();
        }
    }

    function change() {
        line.interpolate(this.value);
        redraw();
    }

    //鼠标点击--增加一个新热点
    function mousedown() {

        //没有开启编辑
        if(!isDrawingLine) return;

        points.push(selected = dragged = d3.mouse(svg.node()));
        redraw();
    }

    //鼠标移动--拖动热点
    function mousemove() {
        if (!dragged) return;
        var m = d3.mouse(svg.node());
        dragged[0] = Math.max(0, Math.min(width, m[0]));
        dragged[1] = Math.max(0, Math.min(height, m[1]));
        redraw();
    }

    //鼠标抬起-停止移动
    function mouseup() {
        if (!dragged) return;
        mousemove();
        dragged = null;
    }

    //处理键盘事件
    function keydown() {
        if (!selected) return;
        switch (d3.event.keyCode) {
            case 8: // backspace
            case 46: { // delete
                var i = points.indexOf(selected);
                points.splice(i, 1);
                selected = points.length ? points[i > 0 ? i - 1 : 0] : null;
                redraw();
                break;
            }
        }
    }

</script>

说明:

待续...


待完成功能:

1)绘制状态提示

2)双击在折线任意位置添加拐点,现在只能在尾部添加

3)绘制多条折线功能

4)升级到d3.v4,用canvas如何绘制?

4)在d3.geo 地图上绘制


等等


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值