Canvas size issue when html attribute and css style width & height differs.
Hi, I'm trying to use pts.js with canvas-sketch, which provides its own canvas and context.
When I use it with the CanvasForm object only, there is no problem.
But when I add CanvasSpace supplying the existing canvas, there is a canvas sizing issue.
I think this happens when <canvas> width & height html attribute is different from width & height css style value. canvas-sketch automatically resizes the canvas css w&h according to the current browser window size.
I haven't found a way to update pts.js code accordingly. If anyone has a suggestion, I'd appreciate it.
Here is my sample code to reproduce the problem:
const canvasSketch = require("canvas-sketch");
const { CanvasSpace, CanvasForm, Pt } = require("pts");
const sketch = ({ canvas, context: ctx }) => {
const space = new CanvasSpace(canvas); // adding space object causes the issue
const form = new CanvasForm(ctx);
return {
render({ width, height, playhead }) {
ctx.fillStyle = "#aaa";
ctx.fillRect(0, 0, width, height);
const center = new Pt([width / 2, height / 2]);
const diam = Math.sin(playhead * Math.PI * 2) * 100 + 200;
form.strokeOnly("#ff0", 12).point(center, diam, "circle");
},
};
};
const settings = {
dimensions: [1400, 1400], // try a big value to reproduce the problem
animate: true,
duration: 4,
};
canvasSketch(sketch, settings);
Hi @cdaein - yes, the css styles and width/height attributes differ to support different pixel density screens automatically. Eg, if you're using a 2x retina screen, the canvas' actual size will be double of the width & height.
I'm not familiar with canvas-sketch, but here are a couple suggestions --
-
If you already have the
<canvas>set up via canvas-sketch, you may not need to create another CanvasSpace. You can pass the rendering context directly to CanvasForm, egnew CanvasForm( ctx ) -
If you are looking for a way to generate high-quality prints, you can try node-pts-canvas. Note that this is experimental and may not work 100%.
Hope this helps!
Thank you for the response, @williamngan !
As you suggested, I am just using CanvasForm although I wish I can use convenience methods and properties that come with CanvasSpace. If only there is a way to modify my canvas to do that...
Also when using new CanvasForm(ctx), it seems that the gradient is not supported?
I was recreating one of your demos - CanvasForm.gradient, and the gradient does not work properly.
I get an error:
Uncaught TypeError: Cannot read properties of undefined (reading 'ctx')
at get ctx [as ctx] (dist.js:3146:26)
at dist.js:3209:33
at dist.js:5283:13
at dist.js:5288:3
Sample code below. This time, I am using pts-starter-kit and do not have any other dependency.
import { CanvasForm, Pt, Bound, Create, Circle } from "pts";
// prepare canvas
const canvas = document.createElement("canvas");
canvas.width = 600;
canvas.height = 600;
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
const form = new CanvasForm(ctx);
// recreate CanvasSpace properties for demonstration
const center = new Pt(canvas.width / 2, canvas.height / 2);
const size = new Pt(canvas.width, canvas.height);
const innerBound = new Bound(new Pt(), size);
// simulate mouse pointer
const pointer = new Pt(100, 100);
let scale = center.$subtract(pointer).divide(center).abs();
let bound = new Bound(new Pt(), size.$add(0, size.y * scale.y));
let cells = Create.gridCells(bound, 21, 30);
let offy = (bound.height - innerBound.height) / 2;
let cy = 1 - Math.abs(center.y - pointer.y) / center.y;
let radial = form.gradient([
[0.2, `rgba(${70 * cy}, 0, ${255 * cy})`],
[0.6, `rgba(${205 * cy}, 0, ${30 * cy})`],
[0.95, `rgba(${255 * cy}, ${220 * cy}, 0)`],
]);
// radial gradient seems to have an issue with 'ctx'
form
.fill(
radial(
Circle.fromCenter(pointer, center.y / 2),
Circle.fromCenter(pointer, size.y * 1.5)
)
)
.rect(innerBound);
for (let i = 0, len = cells.length; i < len; i++) {
let grad = form.gradient(["rgba(255,255,255,1)", "rgba(255,255,255,0)"]);
form
.fillOnly(i % 2 === 0 ? grad(cells[i]) : "rgba(0,0,0,0)")
.rect(cells[i].subtract(0, offy));
}
Thanks for the report! I will take a look soon.
This is a common enough use case, so maybe we should create a CustomCanvasSpace or something similar for this type of use case.
Thank you for looking into this.
the gradient issue is now fixed with 0.10.12 as mentioned in the other issue.