提问者:小点点

使用加工创建自定义绘图工具


我目前正在处理中编写一种绘图工具。我希望能够用鼠标绘制一条黑线,但让它再次消失。为此,我首先想到了使用一个从黑色渐变到白色的黑色椭圆。然后,这个椭圆通过mouseX和mouseY链接到鼠标指针。因为我希望每个绘制的椭圆单独从黑色渐变到白色(以创建线条再次渐变的效果),所以我想到了使用对象。到目前为止,这是可行的,但渐变还不起作用。我希望鼠标指针处的椭圆始终是黑色的,然后只有在鼠标指针移动得更远或绘制得更远时才变为白色…就像淡出一样…

我应该为此使用ArrayList吗?并说应该在每帧的MouseX和MouseY位置绘制一个新对象?我需要PVector吗?

到目前为止,这就是我想出来的:

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

共2个答案

匿名用户

您在这里遇到的问题是,您只能在绘制线条后知道如何淡化线条,但您在用户移动鼠标时绘制它。

为了解决这个问题,我建议存储在对象中绘制线条所需的所有信息,并在用户绘制时更新它。正如您所猜测的,您完全可以使用ArrayList来实现这一点。

为了简化我自己的生活,我对你的代码进行了相当大的修改,并对结果进行了注释,这样你就可以更容易地按照自己的条件将其重新转换到你自己的项目中。

我使用对象来保持一切整洁。这里的逻辑如下:Canvas对象包含绘图。它由Line对象组成,这些对象本身就是由Dot组成的。

这是注释的代码:

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

希望这有帮助。如果您对代码有任何疑问,我会在附近。玩得开心!

匿名用户

这是一个带有ArrayList和Object的版本…这里的问题是所有椭圆对象同时消失…我想实现每个椭圆首先被绘制成黑色,然后在时间X变成白色…例如传感器上的指纹…很大的压力:黑色,很小的压力(或没有压力):褪色为白色…后来我想在PGraphics图层上绘制所有东西——因此已经有这个变量了…

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