Home > Net >  Create custom drawing tool with processing
Create custom drawing tool with processing

Time:04-10

I am currently in the process of coding a kind of drawing tool in Processing. I want to be able to draw a black line with the mouse, but have it fade away again. For this I first thought of working with a black ellipse that fades from black to white. This ellipse is then linked to the mouse pointer via mouseX and mouseY. Because I want each drawn ellipse to fade from black to white individually (to create the effect that the line fades again), I thought of working with objects. This works so far, but the fading does not work yet. I want the ellipse at the mouse pointer to always be black and then only change to white once the mouse pointer has been moved further or drawn further... just like a fade...

Should I use an ArrayList for this? And say that a new object should be drawn at the MouseX and MouseY position per frame? Do I need PVector for this?

This is what I came up for this so far:

float counter;
PGraphics pg;

Brush myBrush;

void setup() {
  size(600, 600);
  pg = createGraphics(width, height);
}


void draw() {
  //background(255);
  color from = color(0);
  color to = color(255);
  color faded = lerpColor(from, to, counter);
  myBrush = new Brush(faded, mouseX, mouseY); 
  myBrush.display();
}

class Brush {
  color tempC;
  float xpos;
  float ypos;
  color c;

  Brush(color tempC, float tempXpos, float tempYpos) {
    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
  }
  void display() {
    noStroke();
    fill(c);
    ellipse(xpos, ypos, 50, 50);
    counter = counter   0.01;
  }
}

CodePudding user response:

The issue you're struggling with here is that you can only know how to fade the line once the line has been drawn, but you draw it while the user move the mouse.

To deal with this issue, I would suggest to store every information needed to draw the line in an object, and update it as the user is drawing. As you guessed, you could totally use an ArrayList to achieve this.

Faaaading

More than one line

I modified your code quite heavily to simplify my own life, and I commented the result so it would be easier for you to re-cast it into your own project on your own terms.

I used objects to keep everything tidy. The logic here goes as follow: The Canvas object contains the drawing. It's made of Line objects, which are themselves made of Dots.

Here's the commented code:

Canvas canvas;

void setup() {
  size(600, 600);
  canvas = new Canvas();
}

void draw() {
  // instead of drawing only once, we're going to save every line the user draw in teh canvas object
  background(255);

  // the canvas object has to calculate stuff, then display itself
  canvas.Update();
  canvas.Display();
}

// setting up the mousePressed and mouseReleased events so the canvas object "knows"
void mousePressed() {
  canvas.mouseDown = true;
}
void mouseReleased() {
  canvas.mouseReleased = true;
  canvas.mouseDown = false;
}

class Canvas {
  boolean mouseDown;
  boolean mouseReleased = true;
  ArrayList<Line> lines = new ArrayList<Line>(); // every line will be stored in this list
  Brush brush; // the brush object can be modified with different sizes or colors

  Canvas() {
    // here i use a default brush, but you can experiment different colors or sizes
    brush = new Brush(color(0, 200, 0), color(0), color(255), 50);
  }

  void Update() {
    brush.highlight = mouseDown; // so the user has visual feedback while drawing

    if (mouseDown) {      
      if (mouseReleased) { // if this is a "new" line, add a line object to store it
        lines.add(new Line(brush.colorFrom, brush.colorTo));
        mouseReleased = false;
      }
      // add a dot at the mouse's current position, then update the fading
      lines.get(lines.size()-1).Add(new Dot(mouseX, mouseY, brush.diameter, brush.colorFrom));
      lines.get(lines.size()-1).ApplyFade();
    }
  }

  void Display() {
    // for every Line, draw every Dot... then don't forget to display the brush!
    for (Line l : lines) {
      for (Dot d : l.dots) {
        d.Display();
      }
    }
    brush.Display();
  }
}

// A line is a bunch of dots and two colord (for the fade effect)
class Line {
  ArrayList<Dot> dots = new ArrayList<Dot>();
  color colorFrom, colorTo;

  Line(color colorFrom, color colorTo) {
    this.colorFrom = colorFrom;
    this.colorTo = colorTo;
  }

  void Add(Dot d) {
    dots.add(d);
  }

  // This method calculate how many dots there are in the line to better distribute the shades of the fade
  void ApplyFade() {
    for (int i=0; i<dots.size(); i  ) {
      Dot d = dots.get(i);
      d.c = lerpColor(colorFrom, colorTo, (float) i/dots.size());
    }
  }
}

// a Dot has a size, a position and a color
class Dot {
  float xpos;
  float ypos;
  float diameter;
  color c;

  Dot(float xpos, float ypos, float diameter, color c) {
    this.xpos = xpos;
    this.ypos = ypos;
    this.diameter = diameter;
    this.c = c;
  }

  void Display() {
    noStroke();
    fill(c);
    ellipse(xpos, ypos, diameter, diameter);
  }
}

// this class is overdesigned so in the future you can change the brush's characteristics like the fade'S colors or simply it's size
class Brush {
  boolean highlight;
  float diameter, xpos, ypos;
  color circleColor, colorFrom, colorTo;

  Brush(color circleColor, color colorFrom, color colorTo, float diameter) {
    this.circleColor = circleColor;
    this.colorFrom = colorFrom;
    this.colorTo = colorTo;
    this.diameter = diameter;
  }

  void Display() {
    stroke(circleColor);
    strokeWeight(5);
    noFill();
    ellipse(mouseX, mouseY, diameter, diameter);
    if (highlight) { // if the mouse's button is down, give visual feedback about the brush
      stroke(0);
      strokeWeight(4);
      ellipse(mouseX, mouseY, diameter, diameter);
      stroke(255);
      strokeWeight(3);
      ellipse(mouseX, mouseY, diameter, diameter);
    }
  }
}

Hope this helps. I'll be around if you have questions about the code. Have fun!

CodePudding user response:

Here is a version with an ArrayList and Object... The problem here is that all ellipse objects fade away at the same time... I would like to achieve that each ellipse is first drawn black and then after time X becomes white... Like a fingerprint on a sensor for example... A lot of pressure: black, little pressure (or no pressure): fade to white... Later on I want to draw everything on a PGraphics layer – therefore there is alyready this variable...

float counter;
PGraphics pg;
ArrayList<PVector> positionsList;

Brush myBrush;

void setup() {
  size(600, 600);
  positionsList = new ArrayList<PVector>();
  pg = createGraphics(width, height);
}


void draw() {
  background(255);
  color from = color(0);
  color to = color(255);
  color faded = lerpColor(from, to, counter);

  for (PVector p : positionsList) {
    myBrush = new Brush(faded, p.x, p.y);
   myBrush.display();
 
  }
    positionsList.add(new PVector(mouseX, mouseY));
      counter = counter   0.01;
}

class Brush {
  color tempC;
  float xpos;
  float ypos;
  color c;

  Brush(color tempC, float tempXpos, float tempYpos) {
    
    
    
    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
  }
  void display() {
    noStroke();
    fill(c);
    ellipse(xpos, ypos, 50, 50);
 
  }
}
  • Related