Pencil functionality

I was looking for a way to use D3 and the ability to draw with a pencil. Is this something you can do? I looked through various examples on the mbostock site, but I couldn't find anything that allowed me to draw by hand within the scaled area.

+3


source to share


2 answers


I like @coolblue's solution, but here's an alternative. It uses a path element to really look like the picture:



<!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>
      

Run code


Plunker is here .

+4


source


It might be ok to go ... (this is a modified particle pattern with gravity, charge and friction set to zero)

;(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>
      

Run code




Trying to touch Mark's solution ...

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;
      }
    }
      

svg {
      outline: 1px solid red;
    }
      

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
      

Run code


+5


source







All Articles