Как нарисовать изображение под прямоугольниками на холсте Ваадина? - PullRequest
0 голосов
/ 17 декабря 2018

В настоящее время у меня есть холст, на котором я сначала нарисую изображение, прежде чем появятся все остальные функции рисования мышью холста (для рисования прямоугольников).У меня также есть функция отмены, которая удаляет последний нарисованный блок, очищает весь холст и перерисовывает все оставшиеся блоки обратно на холст.Однако после удаления изображение каким-то образом появится поверх полей и покрывает их, а не внизу, как должно быть.Я мог исправить это с помощью z-index в HTML5 ранее, но не знаю, как это сделать, используя способ Java.

Это мой Canvas.java (метод отмены ближе к концу):

package com.vaadin.starter.beveragebuddy.ui.components;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;
import com.vaadin.flow.shared.Registration;
import com.vaadin.starter.beveragebuddy.backend.MainLayout;
import elemental.json.JsonObject;
import java.util.ArrayList;
import java.util.List;

/**
 * Canvas component that you can draw shapes and images on. It's a Java wrapper
 * for the
 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">HTML5
 * canvas</a>.
 * <p>
 * Use {@link #getContext()} to get API for rendering shapes and images on the
 * canvas.
 * <p>
 */
@Tag("canvas")
@SuppressWarnings("serial")
public class Canvas extends Component implements HasStyle, HasSize {

    private static CanvasRenderingContext2D context;
    private Element element;
    private boolean mouseSelect = false;
    private boolean mouseIsDown = false;
    private double endX;
    private double endY;
    public static int boxCount = 0;
    public static boolean undoCalled = false;

    public static ArrayList <BoundingBox> arrayBoxes = new ArrayList<BoundingBox>();
    public static ArrayList <MousePosition> mousePosArray = new ArrayList<MousePosition>();
    public static ArrayList <SelectBox> selectBoxes = new ArrayList<SelectBox>();
    private List<Runnable> mouseMoveListeners = new ArrayList<>(0);

    public static ArrayList<BoundingBox> getArrayBoxes() {
        return arrayBoxes;
    }

    public static ArrayList<MousePosition> getMousePosArray() {
        return mousePosArray;
    }

    public static void setMousePosArray(ArrayList<MousePosition> mousePosArray) {
        Canvas.mousePosArray = mousePosArray;
    }

    /**
     * Creates a new canvas component with the given size.
     * <p>
     * Use the API provided by {@link #getContext()} to render graphics on the
     * canvas.
     * <p>
     * The width and height parameters will be used for the canvas' coordinate
     * system. They will determine the size of the component in pixels, unless
     * you explicitly set the component's size with {@link #setWidth(String)} or
     * {@link #setHeight(String)}.
     *
//     * @param width
//     *            the width of the canvas
//     * @param height
//     *            the height of the canvas
//     */

    public Registration addMouseMoveListener(Runnable listener) {
        mouseMoveListeners.add(listener);
        return () -> mouseMoveListeners.remove(listener);
    }

    public Canvas(int width, int height) {

        context = new CanvasRenderingContext2D(this);

        context.drawImage("https://freedesignfile.com/upload/2016/10/Red-Clouds-and-Prairie-Background.jpg", 0, 0);

        element = getElement();
        element.getStyle().set("border", "1px solid");

        getElement().setAttribute("width", String.valueOf(width));
        getElement().setAttribute("height", String.valueOf(height));

        element.addEventListener("mousedown", event -> {  // Retrieve Starting Position on MouseDown

            Element boundingBoxResult = ElementFactory.createDiv();
            element.appendChild(boundingBoxResult);

            JsonObject evtData = event.getEventData();

            double xBox = evtData.getNumber("event.x");
            double yBox = evtData.getNumber("event.y");
            boundingBoxResult.setAttribute("data-x", String.format("%f", xBox));
            boundingBoxResult.setAttribute("data-y", String.format("%f", yBox));

            BoundingBox newBox = new BoundingBox("","", xBox, yBox, 0.0, 0.0);
            arrayBoxes.add(newBox);

            SelectBox select = new SelectBox(xBox, 0.0, yBox, 0.0);
            selectBoxes.add(0, select);

            mouseIsDown=true;

            mouseMoveListeners.forEach(Runnable::run);

        }).addEventData("event.x").addEventData("event.y");


        element.addEventListener("mouseup", event -> {  // Draw Box on MouseUp

            Element boundingBoxResult2 = ElementFactory.createDiv();
            element.appendChild(boundingBoxResult2);

            JsonObject evtData2 = event.getEventData();

            endX = evtData2.getNumber("event.x");
            endY = evtData2.getNumber("event.y");
            boundingBoxResult2.setAttribute("end-x", String.format("%f", endX));
            boundingBoxResult2.setAttribute("end-y", String.format("%f", endY));

//            System.out.println(endX);
//            System.out.println(endY);

            double xcoordi = 0;
            double ycoordi = 0;
            double boxWidth = 0;
            double boxHeight = 0;

//            for (int i = 0; i < arrayBoxes.size(); i++) {
                System.out.println(endX);
                System.out.println(endY);
                    arrayBoxes.get(boxCount).setWidth(endX, arrayBoxes.get(boxCount).xcoordi);
                    arrayBoxes.get(boxCount).setHeight(endY, arrayBoxes.get(boxCount).ycoordi);
                    xcoordi = arrayBoxes.get(boxCount).getXcoordi();
                    ycoordi = arrayBoxes.get(boxCount).getYcoordi();
                    boxWidth = arrayBoxes.get(boxCount).getWidth();
                    boxHeight = arrayBoxes.get(boxCount).getHeight();
                    boxCount++;


            mouseIsDown=false;

            context.beginPath();
            context.setStrokeStyle("green");
            context.setLineWidth(2);
            context.strokeRect(xcoordi, ycoordi, boxWidth, boxHeight);
            context.stroke();
            context.fill();



            SelectBox select = new SelectBox(endX, 0.0, endY, 0.0);
            selectBoxes.add(1, select);

//            if (selectBoxes.get(1).getSelectEndX() == selectBoxes.get(0).getSelectStartX()){
//                mouseSelect = true;
//                context.beginPath();
//                context.setStrokeStyle("yellow");
//                context.setLineWidth(2);
//                context.strokeRect(arrayBoxes.get(i).xcoordi, arrayBoxes.get(i).ycoordi, arrayBoxes.get(i).boxWidth, arrayBoxes.get(i).boxHeight);
//                context.fill();
//            }

            System.out.println(arrayBoxes.toString());
//
//            for (int i = 0; i < arrayBoxes.size(); i++){
//                if(arrayBoxes.get(i).xcoordi)
//                if (endX > arrayBoxes.get(i).xcoordi){
//                    if (endX < arrayBoxes.get(i).endY)
//                }
//            }

            mouseMoveListeners.forEach(Runnable::run);

        }).addEventData("event.x").addEventData("event.y");

        element.addEventListener("mousemove", event -> {  // Retrieve Mouse Position when Moving

                JsonObject mousePos = event.getEventData();

                double mouseX = mousePos.getNumber("event.x");
                double mouseY = mousePos.getNumber("event.y");

                MousePosition currentPos = new MousePosition(mouseX, mouseY);
                mousePosArray.add(0, currentPos);
                setMousePosArray(mousePosArray);
            mouseMoveListeners.forEach(Runnable::run);

     }).addEventData("event.x").addEventData("event.y");

    }


    public static void undoLast() {

        undoCalled = true;

        if (arrayBoxes.size() > 0) {
            arrayBoxes.remove(arrayBoxes.size() - 1);
        }
        System.out.println(arrayBoxes.toString());
        System.out.println(arrayBoxes.size());

        context.clearRect(0, 0, 1580, 700);
        context.drawImage("https://freedesignfile.com/upload/2016/10/Red-Clouds-and-Prairie-Background.jpg", 0, 0);

        for (int i = 0; i < arrayBoxes.size(); i++){
            context.beginPath();
            context.setStrokeStyle("green");
            context.setLineWidth(2);
            context.strokeRect(arrayBoxes.get(i).xcoordi, arrayBoxes.get(i).ycoordi, arrayBoxes.get(i).boxWidth, arrayBoxes.get(i).boxHeight);
            context.fill();
        }

        boxCount--;
        System.out.println("Box Count: " + boxCount);
    }

    /**
     * Gets the context for rendering shapes and images in the canvas.
     * <p>
     * It is a Java wrapper for the <a href=
     * "https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">same
     * client-side API</a>.
     *
     * @return the 2D rendering context of this canvas
     */
    public CanvasRenderingContext2D getContext() {
        return context;
    }

    /**
     * {@inheritDoc}
     * <p>
     * <b>NOTE:</b> Canvas has an internal coordinate system that it uses for
     * drawing, and it uses the width and height provided in the constructor.
     * This coordinate system is independent of the component's size. Changing
     * the component's size with this method may scale/stretch the rendered
     * graphics.
     */
    @Override
    public void setWidth(String width) {
        HasSize.super.setWidth(width);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <b>NOTE:</b> Canvas has an internal coordinate system that it uses for
     * drawing, and it uses the width and height provided in the constructor.
     * This coordinate system is independent of the component's size. Changing
     * the component's size with this method may scale/stretch the rendered
     * graphics.
     */
    @Override
    public void setHeight(String height) {
        HasSize.super.setHeight(height);
    }

    /**
     * {@inheritDoc}
     * <p>
     * <b>NOTE:</b> Canvas has an internal coordinate system that it uses for
     * drawing, and it uses the width and height provided in the constructor.
     * This coordinate system is independent of the component's size. Changing
     * the component's size with this method may scale/stretch the rendered
     * graphics.
     */
    @Override
    public void setSizeFull() {
        HasSize.super.setSizeFull();
    }

    public void addComponent(Label label) {
    }
}

Любая помощь очень ценится, спасибо!

1 Ответ

0 голосов
/ 17 декабря 2018

Я полагаю, что ваша проблема связана с одной или обеими из этих проблем

  1. При рисовании изображения вы ожидаете его правильную загрузку, прежде чем фактически нарисовать его на холсте (image.onload = ...).Это означает, что ваш код может начать загружать изображение, затем он рисует все поля, а затем изображение загружается так, что оно рисуется сверху.

  2. Вы запускаете скрипт рисования изображения наbeforeClientResponse, что означает, что он может быть вызван после того, как будет вызван весь код для рисования блоков.

Самое простое решение, если вы всегда хотите иметь изображение в качестве фона, этоиспользовать два холста друг над другом (например, с абсолютным позиционированием).Таким образом, вы всегда можете нарисовать изображения на фоне холста, а все поля на холсте переднего плана.Бонусом этого является то, что вам не нужно перерисовывать фон, даже если вы очистите холст переднего плана.

...