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.


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!