铅笔般的功能

时间:2015-05-14 15:05:09

标签: d3.js

我一直在寻找一种使用D3和手绘铅笔的方法。这是可行的吗?我查看了mbostock网站上的不同示例,但找不到允许您在可缩放区域内手动绘制的任何内容。

2 个答案:

答案 0 :(得分:5)

这可能会好起来......
(它是一个改进的粒子模式,重力,电荷和摩擦力设置为零)



;(function() {
      var w = 900, h = 400, nodes = [], touch,

          svg = d3.select("#vizcontainer").append("svg")
          .attr("width", w)
          .attr("height", h),

          force = d3.layout.force()
          .size([w, h])
          .gravity(0)
          .charge(0)
          .friction(0),

          outputDiv = d3.select("body").insert("div", "#vizcontainer").attr("id", "output").attr("class", "output"),
          touchesDiv = d3.select("body").insert("div", "#output").attr("id", "touches")
          .style("margin-right", "10px").attr("class", "output");

      force.on("tick", function (e) {

        outputDiv.text("alpha:\t" + d3.format(".3f")(force.alpha())
          + "\tnodes:\t" + force.nodes().length)

        svg.selectAll("circle")
        .attr("cx", function (d) { return d.x; })
        .attr("cy", function (d) { return d.y; });
      });

      svg.on("mousemove", onMove);
      svg.on("touchmove", onTouch);
      svg.on("touchstart", onTouch);

      function onMove() {
        updateMethod.call(this)
      }
      function onTouch() {
        d3.event.preventDefault();
        d3.event.stopPropagation();
        updateMethod.call(this)
      }

      function idiomatic() {
        force.nodes(nodes);
        return function () {
          var pointM = d3.mouse(this), pointT = d3.touches(this),
              point = pointT.length ? pointT[0] : pointM,
          node = { x: point[0], y: point[1] };

          nodes.push(node);

          svg.selectAll("circle")
          .data(nodes)
          .enter().append("circle")
          .attr("r", 3)
          .each((function (n) {
            return function (d, i) {
              var i = nodes.indexOf(n);
              nodes.splice(i, 1)
            }
          })(node));

          force.start();
        }
      } /*idiomatic*/


      updateMethod = idiomatic();
    })()

body, html {
      width:100%;
      height:100%;
  }
    #vizcontainer {
      width: 100%;
      height: 100%;
    }

   svg {
      outline: 1px solid red;
      width: 100%;
      height: 100%;
    }

    .output {
      pointer-events: none;  
      display: inline-block;
      z-index: 1;
      margin: 10px;
    }

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
  <div id="vizcontainer"></div>
&#13;
&#13;
&#13;

试图接触Mark的解决方案......

&#13;
&#13;
var svg = d3.select('body')
      .append('svg')
      .attr('width', 1000)
      .attr('height', 1000);

    var color = d3.scale.category20();

    var line = d3.svg.line();

    var drawObj = {
      isDown: false,
      isTouched: false,
      dataPoints: [],
      currentPath: null,
      color: 0
    }

    svg.on("mousedown", function () {
      drawObj.isDown = true;
    });

    svg.on("mousemove", function () {
      if (drawObj.isTouched) {
        lift(); drawObj.isTouched = false
      };
      draw.call(this);

    });

    svg.on("touchmove", function () {
      d3.event.preventDefault();
      d3.event.stopPropagation();
      drawObj.isDown = drawObj.isTouched = true;
      draw.call(this);
    });
    svg.on("touchstart", function () {
      if (drawObj.isTouched) {
        lift(); drawObj.isTouched = false
      };
    })


    function draw() {
      if (drawObj.isDown) {
        var pointM = d3.mouse(this), pointT = d3.touches(this),
            point = pointT.length ? pointT[0] : pointM,
            node = { x: point[0], y: point[1] };

        drawObj.dataPoints.push(
          [node.x, node.y]
        );
        if (!drawObj.currentPath) {
          drawObj.currentPath = svg.append("path")
            .attr("class", "currentPath")
            .style("stroke-width", 1)
            .style("stroke", color(drawObj.color))
            .style("fill", "none");
        }
        drawObj.currentPath
          .datum(drawObj.dataPoints)
          .attr("d", line);
      }
    };
    svg.on("mouseup", lift)
    function lift () {
      drawObj.isDown = false;
      drawObj.currentPath && drawObj.currentPath.attr("class", "oldPath");
      drawObj.dataPoints = [];
      drawObj.currentPath = null;
      if (++drawObj.color > 19) {
        drawObj.color = 0;
      }
    }
&#13;
svg {
      outline: 1px solid red;
    }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:4)

我喜欢@ coolblue的解决方案,但这里有另一种选择。它使用一个路径元素来真正感觉像绘图:

&#13;
&#13;
<!DOCTYPE html>
<html>

<head>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>

<body>
  <script>
    var svg = d3.select('body')
      .append('svg')
      .attr('width', 1000)
      .attr('height', 1000);
      
    var color = d3.scale.category20();
    
    var line = d3.svg.line()
        .interpolate("basis");
    
    var drawObj = {
      isDown: false,
      dataPoints: [],
      currentPath: null,
      color: 0
    }
    
    svg.on("mousedown", function(){
      drawObj.isDown = true;
      
    });
    svg.on("mousemove", function(){
      if (drawObj.isDown){
        drawObj.dataPoints.push(
          [d3.event.x, d3.event.y]
        );
        if (!drawObj.currentPath){
          drawObj.currentPath = svg.append("path")
            .attr("class","currentPath")
            .style("stroke-width", 1)
            .style("stroke",color(drawObj.color))
            .style("fill", "none");
        }
        drawObj.currentPath
          .datum(drawObj.dataPoints)
          .attr("d", line);
      }
    });
    svg.on("mouseup", function(){
      drawObj.isDown = false;
      drawObj.currentPath.attr("class","oldPath");
      drawObj.dataPoints = [];
      drawObj.currentPath = null;
      if (++drawObj.color > 19) {
        drawObj.color = 0;
      }
    })
  </script>
</body>

</html>
&#13;
&#13;
&#13;

Plunker here