如何使用 GWT 的 Context2d 绘制虚线?

How to draw dashed line with GWT's Context2d?

如何用GWT的Context2d绘制虚线? HTML5canvas有方法setLineDash,但是GWT的wrapper context2d好像没有这个功能?

似乎没有现成的 解决方案。您需要沿着这条线并绘制虚线和间隙。

Javatips.net (Example #17, source code 上找到的示例):

/**
     * Draw a dashed line from (fromX, fromY) to (toX, toY).
     * 
     * @param context
     * @param fromX x-coordinate of the starting point
     * @param fromY y-coordinate of the starting point
     * @param toX x-coordinate of the ending point
     * @param toY y-coordinate of the ending point
     * @param dashLength length of the dash
     * @param gapLength length of the gap in between dashes
     */
public static void drawDashedLine(Context2d context, double fromX, double fromY, double toX, double toY, double dashLength, double gapLength) {
    DashedLineHelper checkX = GreaterThanHelper.instance;
    DashedLineHelper checkY = GreaterThanHelper.instance;
    if (fromY - toY > 0) {
        checkY = LessThanHelper.instance;
    }
    if (fromX - toX > 0) {
        checkX = LessThanHelper.instance;
    }
    context.moveTo(fromX, fromY);
    double offsetX = fromX;
    double offsetY = fromY;
    boolean dash = true;
    double ang = Math.atan2(toY - fromY, toX - fromX);
    while (!(checkX.isThereYet(offsetX, toX) && checkY.isThereYet(offsetY, toY))) {
        double len = (dash) ? dashLength : gapLength;
        offsetX = checkX.getCap(toX, offsetX + (Math.cos(ang) * len));
        offsetY = checkY.getCap(toY, offsetY + (Math.sin(ang) * len));
        if (dash) {
            context.lineTo(offsetX, offsetY);
        } else {
            context.moveTo(offsetX, offsetY);
        }
        dash = !dash;
    }
}

/**
 * Helper class for checking the dash line.
 */
private interface DashedLineHelper {

    /**
     * Checks whether the point has been reached yet.
     * 
     * @param from
     * @param to
     * @return
     */
    boolean isThereYet(double from, double to);

    /**
     * Gets the cap of the two values. If the line is increasing, this will
     * return max(v1, v2). If the line is decreasing, this will return
     * min(v1, v2).
     * 
     * @param v1
     * @param v2
     * @return
     */
       double getCap(double v1, double v2);
}

/**
 * Helper for a decreasing line.
 */
private static class LessThanHelper implements DashedLineHelper {
    private static DashedLineHelper instance = new LessThanHelper();

    @Override
    public double getCap(double v1, double v2) {
        return Math.max(v1, v2);
    }

    @Override
    public    boolean isThereYet(double from, double to) {
        return from <= to;
    }       
}

/**
 * Helper for an increasing line.
 */
private static class GreaterThanHelper implements DashedLineHelper {
    private static DashedLineHelper instance = new GreaterThanHelper();

    @Override
    public double getCap(double v1, double v2) {
        return Math.min(v1, v2);
    }

    @Override
    public boolean isThereYet(double from, double to) {
        return from >= to;
    }       
}

正如 Colin Alworth 在他的 中指出的那样,您可以使用 JavaScript canvas.[=18 的内置虚线功能轻松实现虚线=]

首先您需要扩展 GWT 的 Context2d class 并为虚线添加 JSNI 方法(/*-{}-*/ 标记在这里很重要):

import com.google.gwt.canvas.dom.client.Context2d;

public class MyContext2d extends Context2d {

    protected MyContext2d() {}

    public final native void setLineDash(int[] segments) /*-{
        this.setLineDash(segments);
    }-*/;
}

然后你可以在你的Java代码中使用Context2d扩展class的setLineDash()方法来配置破折号模式,它会显示在浏览器:

Canvas canvas = Canvas.createIfSupported();
MyContext2d context = canvas.getContext2d().cast();
context.setLineDash(new int[]{20, 20, 5, 20});
// draw line etc...