質問: ### 前提・実現したいこと javafxのCanvasのスケールを拡大した際に、描画内容がぼやけてしまいます。 スケールを拡大しても、描画内容がぼやけないようにする方法を見つけたいです。 ### 発生している問題・エラーメッセージ Canvasのスケールを縦横2倍にするクリックイベントがあり、 クリックするたびに描画内容(例えばfillrect)が2倍ずつ拡大するのですが、 同時に、徐々に描画内容もぼやけていきます。 アンチエイジングがかかるように、境界線があいまいになる感じです。 ``` エラーメッセージ 特になし ``` ### 該当のソースコード ``` <クリックイベント(抜粋)> canvas.setScaleX(canvas.getScaleX()*2); canvas.setScaleY(canvas.getScaleY()*2); ``` ### 試したこと ### 補足情報(言語/FW/ツール等のバージョンなど) ![拡大前の画像](https://teratail.storage.googleapis.com/uploads/contributed_images/291dbed33fb4b8add7d6d479c45e14f9.png) ![8倍に拡大](https://teratail.storage.googleapis.com/uploads/contributed_images/4a96d5de828f8fca7b59e68b37bf5f25.png) ![32倍に拡大](https://teratail.storage.googleapis.com/uploads/contributed_images/831a0f1360f12edccd46d7c9ca2449ee.png)
回答: 自分もやってみましたがうまくいきませんでした。 SceneはデフォルトでSceneAntialiasing.DISABLEDになっているはずですのでこれに影響されているわけではないはずです。(一応明示的に指定してみましたが、結果はかわらずでした) GraphicsContextのリファレンスで関連しそうなものを見てみましたがペンの境界を表現するようなものは見当たりません。Strokeならば線分の属性が指定できますがfillRectなどの場合は境界について制御するようなものはない気がします。 推測ですがこれはJavaFXの座標系がintではなくdoubleを基本としているという事実に関係しているのではないかと思えました。つまりシーン上に描画した内容がデバイスピクセル上にどのように反映させるかについては「少なくともNodeのスケールプロパティーを用いた拡大縮小についてはJavaFXが適当にスムーズにレンダリングするのでプログラマーは気にしないでほしい」ということではないかと。 この推測を肯定 or 否定できる情報を見つけることはできませんでした。間違っている可能性もあるかと思います。 代案: それはさておき、もしスケールプロパティーでくっきりとした描画ができのなら代案がほしいところですね。それは次のようにすると一応できました。 * NodeのscaneX, scaleYプロパティーは用いない * GraphicsContextのtransformのscaleを用いる 拡大縮小の度にcanvasへの描画しなおしが必要な点が若干面倒ですね。ただ、描画の際にはGraphicsContext#save/restoreを用いてやると割合単純に書けます。 ``` void redraw(Canvas canvas, double scale) { GraphicsContext gc = canvas.getGraphicsContext2D(); gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); gc.save(); // 変換座標他を内部スタックへ退避 gc.scale(scale, scale); try { //ここでgcへ描画する。もちろんスケールの違いは意識せずに描画する。 gc.setColor(Color.BLUE); gc.fillRect(0, 0, 20, 20); ... } finally { gc.restore(); // 変換座標他を内部スタックから回復 } } ```