小弟近日在做一个JavaFX项目。需要涉及到canvas的重绘,方案如下:
首先利用clearRect清除需要擦除的部分,这时候有可能会擦掉一些不应该擦除的某个图形对象的一部分,所以要重绘这一对象。
本来想的是和HTML5 Canvas同样的办法,用画笔XOR模式,直接再把残缺的对象整个再画一边即可。但是奈何JavaFX的stroke没有XOR模式。
如果不用XOR模式,那么重绘的时候原本没有被擦除的部分颜色会加深(据我实际观察,应该和渲染器有关,其实颜色的rgb是不变的,不过画一条线的时候,这条线的边缘是有一定模糊的,而非一条实实在在的实线,如果多画几次,模糊的边缘就被实化了,看起来颜色就加深了)。
而如果先使用背景色画笔重画这一部分图形,则莫名其妙会出现一个线条的边框。
那么问题来了。。有什么别的解决方案吗,求各位大神解答。。。下面贴上我的test代码。
package test;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.BlendMode;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.FillRule;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Test extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Group root = new Group();
Canvas canvas = new Canvas(300, 400);
canvas.setTranslateY(0);
root.getChildren().add(canvas);
Scene scene = new Scene(root,600,400);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.scale(2,2);
gc.setStroke(Color.GREY);
gc.setFill(Color.GREY);
// 样板
gc.strokeLine(60, 0, 60, 100);
gc.fillText("hello", 120, 140);
// 需要混合的部分
gc.strokeLine(80, 0, 80, 100);
gc.fillText("hello", 120, 150);
// 清除部分
gc.clearRect(0, 0, 120, 20);
// 设置混合模式
// gc.setGlobalBlendMode(BlendMode.DARKEN);
// 重绘元件。为了更清楚的突出混合色,所以循环100遍。
for (int i = 0; i<100; i++)
gc.strokeLine(80, 0, 80, 100);
for (int i = 0; i<100; i++)
gc.fillText("hello", 120, 150);
}
}