0

I am developing a navigation system in Java. The map should be drawn in the middle, with indicators on the left and right.

How do I make the map slowly fade out on both sides?

enter image description here

As shown above, the roads are drawn across the entire window via Graphics2D. How can I make a gradient with left and right transparent and center color x?

for(Street street : streets){
    g2d.setColor(Color.BLACK);
    if(street.distanceToCurrentPosition() * factor < width * 2){
        Integer last_x = null;
        Integer last_y = null;
        street.setupGraphicSettings(g2d);
        if(street.getType() != ""){
            for(WayPoint wayPoint : street.getWayPoints()){
                int waypoint_x = (int) (wayPoint.getDistanceLongitudeTo(current_position) * factor) + middle_x;
                int waypoint_y = - (int) (wayPoint.getDistanceLatitudeTo(current_position) * (double) factor) + middle_y;

                if(last_x != null || last_y != null){;
                    g2d.drawLine(waypoint_x, waypoint_y, last_x, last_y);
                }
                last_x = waypoint_x;
                last_y = waypoint_y;
            }
        }
    }else return;

A working code solution

andrewJames
  • 19,570
  • 8
  • 19
  • 51
DevJones
  • 1
  • 1
  • maybe this answer helps: https://stackoverflow.com/a/34712493/1514647 – luckyluke Nov 20 '22 at 20:12
  • I would start by having a look at [2D Graphics Trail](https://docs.oracle.com/javase/tutorial/2d/index.html), in particular [Stroking and Filling Graphics Primitives](https://docs.oracle.com/javase/tutorial/2d/geometry/strokeandfill.html) – MadProgrammer Nov 20 '22 at 21:16
  • For [example](https://stackoverflow.com/questions/12139001/add-a-transparent-gradient-to-a-jpanel/12139170#12139170); [example](https://stackoverflow.com/questions/26961190/can-i-have-image-alpha-fade-from-left-to-right-in-java/26962173#26962173) – MadProgrammer Nov 20 '22 at 21:23

1 Answers1

0

The "basic" idea is to use a combination of LinearGradientPaint and AlphaComposite to apply an alpha based "mask" to the core map image - now, this assumes you have an image based map.

Start by taking a look at:

Basically, we create a alpha based "mask":

BufferedImage alphaMask = new BufferedImage(baseMap.getWidth(), baseMap.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = alphaMask.createGraphics();
Color opaqueColor = new Color(0, 0, 0, 255);
Color alphaColor = new Color(0, 0, 0, 0);

LinearGradientPaint lgp = new LinearGradientPaint(
        new Point(0, 0),
        new Point(baseMap.getWidth(), 0),
        new float[]{0f, 0.1f, 0.25f, 0.75f, 0.9f, 1f},
        new Color[]{alphaColor, alphaColor, opaqueColor, opaqueColor, alphaColor, alphaColor}
);
g2d.setPaint(lgp);
g2d.fillRect(0, 0, alphaMask.getWidth(), alphaMask.getHeight());
g2d.dispose();

Note, we're not really interested in the color, just there alpha values.

Next, we use a AlphaComposite.DST_IN to "mask" the source image, this done via a utility method...

public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
    BufferedImage maskedImage = null;
    if (sourceImage != null) {

        int width = maskImage.getWidth();
        int height = maskImage.getHeight();

        maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D mg = maskedImage.createGraphics();

        int x = (width - sourceImage.getWidth()) / 2;
        int y = (height - sourceImage.getHeight()) / 2;

        mg.drawImage(sourceImage, x, y, null);
        mg.setComposite(AlphaComposite.getInstance(method));

        mg.drawImage(maskImage, 0, 0, null);

        mg.dispose();
    }

    return maskedImage;
}

Runnable example

enter image description here

NB: The component's background is set to red to demonstrate the alpha masking

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                try {
                    frame.add(new TestPane());
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage maskedMap;

        public TestPane() throws IOException {
            BufferedImage baseMap = ImageIO.read(getClass().getResource("/images/MiddleEarth.jpeg"));
            BufferedImage alphaMask = new BufferedImage(baseMap.getWidth(), baseMap.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = alphaMask.createGraphics();
            Color opaqueColor = new Color(0, 0, 0, 255);
            Color alphaColor = new Color(0, 0, 0, 0);

            LinearGradientPaint lgp = new LinearGradientPaint(
                    new Point(0, 0),
                    new Point(baseMap.getWidth(), 0),
                    new float[]{0f, 0.1f, 0.25f, 0.75f, 0.9f, 1f},
                    new Color[]{alphaColor, alphaColor, opaqueColor, opaqueColor, alphaColor, alphaColor}
            );
            g2d.setPaint(lgp);
            g2d.fillRect(0, 0, alphaMask.getWidth(), alphaMask.getHeight());
            g2d.dispose();
            maskedMap = applyMask(baseMap, alphaMask, AlphaComposite.DST_IN);
            // Just to prove the point
            setBackground(Color.RED);
        }

        @Override
        public Dimension getPreferredSize() {
            return maskedMap == null ? new Dimension(200, 200) : new Dimension(maskedMap.getWidth(), maskedMap.getHeight());
        }

        public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
            BufferedImage maskedImage = null;
            if (sourceImage != null) {

                int width = maskImage.getWidth();
                int height = maskImage.getHeight();

                maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                Graphics2D mg = maskedImage.createGraphics();

                int x = (width - sourceImage.getWidth()) / 2;
                int y = (height - sourceImage.getHeight()) / 2;

                mg.drawImage(sourceImage, x, y, null);
                mg.setComposite(AlphaComposite.getInstance(method));

                mg.drawImage(maskImage, 0, 0, null);

                mg.dispose();
            }

            return maskedImage;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
            );
            g2d.setRenderingHints(hints);

            int x = (getWidth() - maskedMap.getWidth()) / 2;
            int y = (getHeight() - maskedMap.getHeight()) / 2;
            g2d.drawImage(maskedMap, x, y, this);

            g2d.setColor(Color.BLACK);
            g2d.setStroke(new BasicStroke(3f));
            // There's a nice and interesting effect ;)
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.9f));

            int diameter = getWidth() / 4;

            x = ((getWidth() / 2) - diameter) / 2;
            y = (getHeight() - diameter) / 2;

            g2d.fillOval(x, y, diameter, diameter);

            x = getWidth() - (((getWidth() / 2) + diameter) / 2);

            g2d.fillOval(x, y, diameter, diameter);

            g2d.dispose();
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366