如何使用线性插值和链表创建颜色渐变?

4
我目前正在尝试制作一个彩虹轨迹,跟随你的鼠标移动。我使用了LinkedList来绘制鼠标的点,以便轨迹沿着鼠标移动。轨迹本身看起来很完美,只是轨迹中的颜色看起来不对劲。我希望它们能够淡入淡出。有人告诉我要使用线性插值,经过一段时间的研究,似乎它可以工作,只是我不知道如何实现它。
这是我目前的代码:
import impsoft.bots.ColorBot;
import impsoft.scripting.ibot.interfaces.AutoPaint;
import impsoft.scripting.types.ColorScript;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.Deque;
import java.util.LinkedList;

import impsoft.scripting.ibot.structs.XY;
import impsoft.scripting.types.ColorSkeltonScriptable;
import impsoft.scripting.types.parallel.scriptjobs.ScriptJob;


public class MouseTrail extends ColorScript implements AutoPaint {
     public MouseTrail(ColorBot c) {
      super(c);

     }
    public void script() throws InterruptedException {
     while(true) {
         mt.setSize(500);
         mt.exec();

      sleep(100);
     }
    }

    public static String name = "Mouse trail test";
    public static String author = "Llaver";
    public static String description = "test for mouse trail";
    public static double version = 1.00;


public class MouseTrail2 extends ScriptJob implements AutoPaint {


    private int size;
    private final ColorSkeltonScriptable cs;
    private final Deque<XY> trail = new LinkedList<XY>();
    private final Color[] rainbow = new Color[]{
            Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE, Color.magenta
        };

    public MouseTrail2(ColorSkeltonScriptable cs) {
        super(cs);
        this.cs = cs;
    }

    public void setSize(int s) {
        size = s;
        s = 200;
    }

    public void runV() {
        try {
            while (true) {

                synchronized (trail) {
                    if (trail.size() >= size) {
                        trail.pop();
                    }
                    trail.offer(cs.getCurrentMouseXY());
                }
                sleep(1);
            }

        } catch (InterruptedException e) {
        }
    }

    @Override
    public void paint(Graphics g) {
        final Graphics2D g2d = (Graphics2D) g;
        g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        synchronized (trail) {
                float perc;
                int idx;
                for(int i = 1 ; i < trail.size() - 1 ; i++){
        XY current = ((LinkedList<XY>) trail).get(i);
        XY next = ((LinkedList<XY>) trail).get(i - 1);
        perc = ((float)i / trail.size()) * 100f;
       idx = Math.round((perc * (float)rainbow.length) / 100f);
       if(idx >= rainbow.length)idx -= 1;       
       g2d.setColor(rainbow[idx]);
        g.drawLine(current.x, current.y, next.x, next.y);
    }
            }
        }

    }


@Override
public void paint(Graphics arg0) {  
}
private MouseTrail2 mt = new MouseTrail2(this);

}

一些图片:

这是我现在拥有的内容:

http://img11.imageshack.us/img11/3031/mousetrailhavenow.png

这是我正在尝试获取的内容:

http://img594.imageshack.us/img594/7381/mousetrailtryingtoget.png

这样可能让情况更加清晰吗?


当我尝试这样做时,路径的颜色取决于其在屏幕上的位置,而不是它后面跟随的路径位置。我需要它可以从LinkedList获取点,并根据那个点来确定颜色...如果这有意义的话。 - Ryan - Llaver
你可以在这里找到任何有用的东西吗?(https://dev59.com/tVrUa4cB1Zd3GeqPgRF7#6996263) - trashgod
不太行=/ 我已经尝试过LinearGradientPaint,但它不能按照我需要的方式工作。它会生成一个框而不是按照指定的点进行绘制。 - Ryan - Llaver
我添加了一些图片来展示我正在尝试做什么,如果这样可以使事情更加清晰。 - Ryan - Llaver
哈哈,我终于通过胡乱尝试搞定了。结果比我想象的简单得多,我只需要在公式中使用我的链表长度就可以得到我所需的所有颜色((: 感谢你的帮助((: - Ryan - Llaver
2
为什么不更新你的问题或者添加一个带有修订代码的答案呢? - trashgod
1个回答

3
为了达到想要的效果,您可能需要创建一个自定义渐变画笔,该画笔跨越hue范围的一个轴和alpha透明度范围的另一个轴。作为相关示例,此KineticModel使用RadialGradientPaint创建一系列GradientImage实例。在每个图像中,alpha沿径向从中心变化为0xff(1.0)到边缘的0x3f(0.25)。
补充说明:根据您的图片,只需将图形上下文的Stroke设置为适当的宽度,将绘画设置为来自您的颜色查找表(clut)中的下一个色调,并drawLine()。您可以改变色调,保持饱和度和亮度不变。
float N = 360;
Queue<Color> clut = new LinkedList<Color>();
for (int i = 0; i < N; i++) {
    clut.add(Color.getHSBColor(i / N, 1, 1));
}

您需要根据空间或时间来决定何时更改颜色。对于后者,javax.swing.Timer 是一个不错的选择。


虽然那不是你的代码,但它让我思考并帮助我找到了答案,所以我还是会这样做(: 其实比你发布的要简单得多lol。 - Ryan - Llaver
听起来这可能是一个很好的答案;如果你发布了,请通知我。类似于 clut.add(clut.remove()) 的操作可以有效地旋转查找表。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接