Canvas items not rendering properly - html

I have defined the two functions to render a circle and a triangle. Very straight forward stuff.
function circle(offset, size){
var color = $("#color option:selected").val();
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
radius = size * 1;
context.beginPath();
context.arc(offset, 2, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
}
function triangle(offset, size){
var color = $("#color option:selected").val();
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = size * 6;
var height = size * 5;
var padding = 0;
// Draw a path
context.beginPath();
context.moveTo(offset + width/2, padding);
context.lineTo(offset + width, height + padding);
context.lineTo(offset, height + padding);
context.closePath();
// Fill the path
context.fillStyle = color;
context.fill();
}
I am have added the canvas to my page with:
<canvas id="canvas"></canvas>
For some reason I can see the circle and square a not rendering correctly. See attached screen shots.

I can almost guarantee that it is because you are setting the width and height of the Canvas using CSS width and height and not the <canvas> html attributes.
You need to define the width/height either in the canvas tag:<canvas width="500" height="500">
or in code:
var canvas = document.getElementById("canvas");
canvas.width = 500;
canvas.height = 500;
And not by CSS. If you did this:
<canvas style="width: 500px; height: 500px;">
Then you would have a 300x150 canvas (the default size) that was scaled/warped to be 500x500, which is almost certainly what you're getting.
(I wrote the above freehand so there might be a typo, but you get the idea)

Related

HTML5 Canvas: How to create multiple shapes in one canvas and position/style them independently

I'm new to using HTML canvas and am hoping to be able to create a button that can be transformed and interacted with using the canvas. But I'm struggling to draw the multiple component parts and style/adjust them independently.
For basics, I'm looking for a grey circle with a heart outline in the centre, almost filling the grey circle. The circle will be drawn using .arc and the heart outline is an svg path.
1) How do I have multiple shapes on the canvas that I can manipulate independently from one another? I started by creating multiple contexts of the same canvas, is this right? E.g circleContext and heartContext so that I could set different fill colours and such only to specific contexts. Is this the correct approach?
2) How do I position these shapes on the canvas? I have set up canvasCentreX and canvasCentreY with the hope of using these co-ordinates to set shapes where I want them but I cannot seem to position the path2D correctly using .moveTo or any of the other available methods.
Here is what I have:
https://codepen.io/anon/pen/xMZxvq
// Canvas setup
const canvas = document.getElementById('saveButtonCanvas');
const ctx = canvas.getContext('2d');
const canvasCentreX = canvas.width / 2;
const canvasCentreY = canvas.height / 2;
// Draw grey background circle
const circleContext = canvas.getContext('2d');
const backgroundCircleRadius = canvas.width / 2;
circleContext.beginPath();
circleContext.arc(canvasCentreX, canvasCentreY, backgroundCircleRadius, 0, 2 * Math.PI);
circleContext.fillStyle = '#eee';
circleContext.fill();
// Draw outline of heart
const heartContext = canvas.getContext('2d');
heartContext.lineWidth = 2;
const heartOutline = new Path2D("M12.7047547,3.56374623e-06 C11.2594659,0.00100271425 9.94933816,0.599893524 8.99600456,1.56687138 C8.04033388,0.603290635 6.72923238,0.00779693764 5.28238554,0.00959540854 C2.36181543,0.0127926901 -0.00252980442,2.44652348 2.03149576e-06,5.44317565 C0.00837656568,12.3289212 9.01294838,16 9.01294838,16 C9.01294838,16 18.0097299,12.3067401 17.9999921,5.41919604 C17.9962917,2.42234403 15.6261038,-0.00339354795 12.7047547,3.56374623e-06 L12.7047547,3.56374623e-06 Z");
heartOutline.moveTo(canvasCentreX, canvasCentreY);
heartContext.stroke(heartOutline);
#saveButtonCanvas {
height: 80px;
width: 80px;
margin:30px;
cursor: pointer;
}
<canvas id="saveButtonCanvas" width="80" height="80"></canvas>
This is wow I would do it: first I need the size of the svg path. In order to get the size you can draw the svg path inside an svg element and use the getBBox() method. This method is returning an object with the size and the coords of the bounding box. I use the width and the height.
You need to get the context only once.
To move the heart in the center of your canvas I would use translate
// Canvas setup
const canvas = document.getElementById('saveButtonCanvas');
const ctx = canvas.getContext('2d');
const canvasCentreX = canvas.width / 2;
const canvasCentreY = canvas.height / 2;
// Draw grey background circle
//const circleContext = canvas.getContext('2d');
const backgroundCircleRadius = canvas.width / 2;
ctx.beginPath();
ctx.arc(canvasCentreX, canvasCentreY, backgroundCircleRadius, 0, 2 * Math.PI);
ctx.fillStyle = '#eee';
ctx.fill();
// Draw outline of heart
//const heartContext = canvas.getContext('2d');
ctx.lineWidth = 2;
const hw = 18;// width of the heart
const hh = 16;// height of the heart
ctx.save();
// translate the heart in the center of the canvas
ctx.translate(-hw/2, -hh/2);
ctx.translate(canvasCentreX,canvasCentreY);
const heartOutline = new Path2D("M12.7047547,3.56374623e-06 C11.2594659,0.00100271425 9.94933816,0.599893524 8.99600456,1.56687138 C8.04033388,0.603290635 6.72923238,0.00779693764 5.28238554,0.00959540854 C2.36181543,0.0127926901 -0.00252980442,2.44652348 2.03149576e-06,5.44317565 C0.00837656568,12.3289212 9.01294838,16 9.01294838,16 C9.01294838,16 18.0097299,12.3067401 17.9999921,5.41919604 C17.9962917,2.42234403 15.6261038,-0.00339354795 12.7047547,3.56374623e-06 L12.7047547,3.56374623e-06 Z");
ctx.stroke(heartOutline);
ctx.restore();
#saveButtonCanvas {
height: 80px;
width: 80px;
margin:30px;
cursor: pointer;
}
canvas{border:1px solid}
<canvas id="saveButtonCanvas" width="80" height="80"></canvas>
In the case you need to draw a bigger heart I would use scale:
// Canvas setup
const canvas = document.getElementById('saveButtonCanvas');
const ctx = canvas.getContext('2d');
const canvasCentreX = canvas.width / 2;
const canvasCentreY = canvas.height / 2;
// Draw grey background circle
//const circleContext = canvas.getContext('2d');
const backgroundCircleRadius = canvas.width / 2;
ctx.beginPath();
ctx.arc(canvasCentreX, canvasCentreY, backgroundCircleRadius, 0, 2 * Math.PI);
ctx.fillStyle = '#eee';
ctx.fill();
// Draw outline of heart
//const heartContext = canvas.getContext('2d');
ctx.lineWidth = 1;
const hw = 18;// the width of the heart
const hh = 16;// the height of the heart
let scale = 3;// the scale for the heart
ctx.save();
ctx.translate(-scale*hw/2, -scale*hh/2);
ctx.translate(canvasCentreX,canvasCentreY);
ctx.scale(scale,scale)
const heartOutline = new Path2D("M12.7047547,3.56374623e-06 C11.2594659,0.00100271425 9.94933816,0.599893524 8.99600456,1.56687138 C8.04033388,0.603290635 6.72923238,0.00779693764 5.28238554,0.00959540854 C2.36181543,0.0127926901 -0.00252980442,2.44652348 2.03149576e-06,5.44317565 C0.00837656568,12.3289212 9.01294838,16 9.01294838,16 C9.01294838,16 18.0097299,12.3067401 17.9999921,5.41919604 C17.9962917,2.42234403 15.6261038,-0.00339354795 12.7047547,3.56374623e-06 L12.7047547,3.56374623e-06 Z");
ctx.stroke(heartOutline);
ctx.restore();
#saveButtonCanvas {
height: 80px;
width: 80px;
margin:30px;
cursor: pointer;
}
canvas{border:1px solid}
<canvas id="saveButtonCanvas" width="80" height="80"></canvas>
I hope this helps.

Variable linewidth in HTML5 canvas line

I was trying to contribute to this post, HTML5 Canvas and Line Width
but it was deleted because it's not an official answer, because technically I'm also asking a question using the following code I get the same problem.
"I'm drawing line graphs on a canvas. The lines draw fine. The graph is scaled, every segment is drawn, color are ok, etc. My only problem is visually the line width varies. It's almost like the nib of a caligraphy pen. If the stroke is upward the line is thin, if the stroke is horizontal, the line is thicker.
My line thickness is constant, and my strokeStyle is set to black. I don't see any other properties of the canvas that affect such a varying line width but there must be.
"
<html>
<head>
<style>html{font-family:Verdana;}</style>
<script type="text/javascript">
var canvas ;
var context ;
var Val_max;
var Val_min;
var sections;
var xScale;
var yScale;
var Samsung = [21000,21000,23000,22000,22000,23000,23000];
function init() {
// set these values for your data
sections = 7;
Val_max = 25000;
Val_min = 10000;
var stepSize = 1500;
var columnSize = 75;
var rowSize = 75;
var margin = 10;
var xAxis = [""," Monday "," Tuesday"," Wednesday"," Thursday"," Friday"," Saturday"," Sunday"]//;
//
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.fillStyle = "#4d4d4d"
context.font = "10 pt Arial"
yScale = (canvas.height - columnSize - margin) / (Val_max - Val_min);
xScale = (canvas.width - rowSize) / sections;
context.strokeStyle="#4d4d4d"; // color of grid lines
context.beginPath();
// print Parameters on X axis, and grid lines on the graph
for (i=1;i<=sections;i++) {
var x = i * xScale;
context.fillText(xAxis[i], x,columnSize - margin);
context.moveTo(x, columnSize);
context.lineTo(x, canvas.height - margin);
}
// print row header and draw horizontal grid lines
var count = 0;
for (scale=Val_max;scale>=Val_min;scale = scale - stepSize) {
var y = columnSize + (yScale * count * stepSize);
context.fillText(scale, margin,y + margin);
context.moveTo(rowSize,y)
context.lineTo(canvas.width,y)
count++;
}
context.stroke();
context.lineWidth=20;
context.translate(rowSize,canvas.height + Val_min * yScale);
context.scale(1,-1 * yScale);
// Color of each dataplot items
context.strokeStyle="#2FBC3A";
plotData(Samsung);
}
function plotData(dataSet) {
// context.beginPath();
// context.moveTo(0, dataSet[0]);
// for (i=1;i<sections;i++) {
// context.lineTo(i * xScale, dataSet[i]);
// }
// context.stroke();
var love=0;
for (i=1;i<sections;i++) {
context.beginPath();
context.moveTo(love, dataSet[i-1]);
context.lineTo(i * xScale, dataSet[i]);
love=i*xScale;
context.stroke();
}
}
</script>
</head>
<body onLoad="init()">
<div align="center">
<canvas id="canvas" height="400" width="650">
</canvas>
<br>
<!--Legends for Dataplot -->
<span style="color:#4d4d4d"> Graph </span>
</div>
</body>
</html>
You are changing your context's scaleY in a non-uniform way.
So all the drawings after this operation will get shrunk on the Y axis.
To avoid that, apply this scaling only on your coordinates, at the time of drawing i.e
context.scale(1, -1 * yScale);
...
context.lineTo(x, y);
becomes
context.lineTo(x, y * -1 * yScale);
This way, your coordinate gets correctly scaled, but your stroke keeps its correct scale.
Also, you were drawing each segment separately, which would produce some holes in between of every segments, so I took the liberty of merging them in a single sub-path.
var canvas;
var context;
var Val_max;
var Val_min;
var sections;
var xScale;
var yScale;
var Samsung = [21000, 21000, 23000, 22000, 22000, 23000, 23000];
function init() {
// set these values for your data
sections = 7;
Val_max = 25000;
Val_min = 10000;
var columnSize = 75;
var rowSize = 75;
var margin = 10;
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.fillStyle = "#4d4d4d";
yScale = (canvas.height - columnSize - margin) / (Val_max - Val_min);
xScale = (canvas.width - rowSize) / sections;
context.lineWidth = 20;
context.translate(rowSize, canvas.height + Val_min * yScale);
//context.scale(1,-1 * yScale);
// ^-- Don't do that.
context.strokeStyle = "#2FBC3A";
plotData(Samsung);
}
function plotData(dataSet) {
var love = 0;
// make a single path from all the segments
context.beginPath();
for (var i = 0; i < sections; i++) {
// Here we scale the coordinate, not the drawings
context.lineTo(i * xScale, dataSet[i] * -1 * yScale);
love = i * xScale;
}
context.stroke();
}
init();
<canvas id="canvas" height="400" width="650">
</canvas>

How can I fill in the outside of a path?

I am able to draw these letters using a path. But what I want to do is use that path and fill in what the red image shows instead of filling in the letters.
Here is the code I am using:
function mattes_draw_letter(x, y, width, height, letter, position)
{
var canvas = document.createElement('canvas');
canvas.style.position = "absolute";
canvas.style.top = y + "px";
canvas.id = "canvas_opening_" + position;
canvas.style.zIndex = 5;
canvas.width = width;
canvas.height = height;
canvas.style.left = x + "px";
var ctx = canvas.getContext("2d");
ctx.lineWidth = 1;
ctx.fillStyle = '#bfbfbf';
ctx.strokeStyle = '#000000';
ctx.beginPath();
ctx.moveTo(letter[0] * width, letter[1] * height);
for (i = 0; i < letter.length; i+=2)
{
if (typeof letter[i+3] !== 'undefined')
{
ctx.lineTo(letter[i+2] * width, letter[i+3] * height);
}
}
ctx.fill();
ctx.stroke();
ctx.closePath();
$("#mattes").append(canvas);
canvas.addEventListener("drop", function(event) {drop(event, this);}, false);
canvas.addEventListener("dragover", function(event) {allowDrop(event);}, false);
canvas.addEventListener("click", function() {photos_add_selected_fid(this);}, false);
}
This is what I currently have:
This is what I would like:
Just fill the boxes with red color before drawing the letters in gray.
I was able to do this by adding two lines of code in your code.
ctx.fillStyle = "#F00";
ctx.fillRect(0, 0, width, height);
Put these two lines between the lines:
ctx.lineWidth = 1;
and
ctx.fillStyle = '#bfbfbf';
I assume you're starting the existing letters otherwise (as #Chirag64 says), you can just draw the red rectangles first and then draw the letters on top).
You can use canvas compositing to "draw behind" existing content.
A Demo: http://jsfiddle.net/m1erickson/695dY/
In particular the destination-over compositing mode will draw new content behind existing content (new content is only drawn where the existing content is transparent).
context.globalCompositeOperation="destination-over";
Assuming the HOPE characters are drawn over a transparent background you can add red rectangles behind the HOPE characters like this:
// draw red rectangles **behind** the letters using compositing
ctx.fillStyle="red";
ctx.globalCompositeOperation="destination-over";
for(var i=0;i<4;i++){
ctx.fillRect(i*62+16,13,50,88); // your x,y,width,height depend on your artwork
}

canvas in HTML5 and creating multiple circles

following the w3c school explanation of canvas, I understand creating shapes...
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 20;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
</script>
This will make a green circle where my canvas is.
<canvas id="myCanvas"></canvas>
However - I want to apply that "circle" to multiple places on the page, and doing this by ID would be ridiculous.
How does one apply a context (as defined above) to multiple canvas'?? I' assume using class, this seems the logical way.
<canvas class="redDot"></canvas>
<canvas class="redDot"></canvas>
<canvas class="redDot"></canvas>
<canvas class="greenDot"></canvas>
<canvas class="greenDot"></canvas>
<canvas class="blueDot"></canvas>
<canvas class="blueDot"></canvas>
<canvas class="blueDot"></canvas>
You would have to iterate through each Element to apply the changes. I.E:
var dots = document.getElementsByClassName('dots');
for (var i=0;i<dots.length;i++){
var canvas = dots[i];
var context = canvas.getContext('2d');
// Draw circles here
}
Ideally, you would only have one canvas element which you can draw multiple circles
var canvas = document.getElementById('myOneAndOnlyCanvas');
// Using CSS and layering can make background
var context = canvas.getContext('2d');
dot('red',50,50);
dot('blue',100,50);
//etc..
function dot(color,x,y){
context.beginPath();
context.arc(y, y, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
But if that doesn't fit your use case what about using an SVG object?
Since you mentioned w3 schools: http://www.w3schools.com/svg/
But ideally check out: http://www.w3.org/Graphics/SVG/
Mind, Dom Heavy pages can seriously hurt load times. Depending on what you want to do it might be wiser just to use an image (eg. a large cluster of dots).

Canvas drawings, like lines, are blurry

I have a <div style="border:1px solid border;" /> and canvas, which is drawn using:
context.lineWidth = 1;
context.strokeStyle = "gray";
The drawing looks quite blurry (lineWidth less than one creates even worse picture), and nothing near to the div's border. Is it possible to get the same quality of drawing as HTML using canvas?
var ctx = document.getElementById("canvas").getContext("2d");
ctx.lineWidth = 1;
ctx.moveTo(2, 2);
ctx.lineTo(98, 2);
ctx.lineTo(98, 98);
ctx.lineTo(2, 98);
ctx.lineTo(2, 2);
ctx.stroke();
div {
border: 1px solid black;
width: 100px;
height: 100px;
}
canvas, div {background-color: #F5F5F5;}
canvas {border: 1px solid white;display: block;}
<table>
<tr><td>Line on canvas:</td><td>1px border:</td></tr>
<tr><td><canvas id="canvas" width="100" height="100"/></td><td><div> </div></td></tr>
</table>
I found that setting the canvas size in CSS caused my images to be displayed in a blurry manner.
Try this:
<canvas id="preview" width="640" height="260"></canvas>
as per my post: HTML Blurry Canvas Images
When drawing lines in canvas, you actually need to straddle the pixels. It was a bizarre choice in the API in my opinion, but easy to work with:
Instead of this:
context.moveTo(10, 0);
context.lineTo(10, 30);
Do this:
context.moveTo(10.5, 0);
context.lineTo(10.5, 30);
Dive into HTML5's canvas chapter talks about this nicely
Even easier fix is to just use this:
context = canvas.context2d;
context.translate(0.5, 0.5);
From here on out your coordinates should be adjusted by that 0.5 pixel.
I use a retina display and I found a solution that worked for me here.
Small recap :
First you need to set the size of your canvas twice as large as you want it, for example :
canvas = document.getElementById('myCanvas');
canvas.width = 200;
canvas.height = 200;
Then using CSS you set it to the desired size :
canvas.style.width = "100px";
canvas.style.height = "100px";
And finally you scale the drawing context by 2 :
const dpi = window.devicePixelRatio;
canvas.getContext('2d').scale(dpi, dpi);
The Mozilla website has example code for how to apply the correct resolution in a canvas:
https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Set display size (css pixels).
var size = 200;
canvas.style.width = size + "px";
canvas.style.height = size + "px";
// Set actual size in memory (scaled to account for extra pixel density).
var scale = window.devicePixelRatio; // Change to 1 on retina screens to see blurry canvas.
canvas.width = size * scale;
canvas.height = size * scale;
// Normalize coordinate system to use css pixels.
ctx.scale(scale, scale);
ctx.fillStyle = "#bada55";
ctx.fillRect(10, 10, 300, 300);
ctx.fillStyle = "#ffffff";
ctx.font = '18px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var x = size / 2;
var y = size / 2;
var textString = "I love MDN";
ctx.fillText(textString, x, y);
<canvas id="canvas"></canvas>
Lines are blurred because the canvas virtual size is zoomed to its HTML element actual size. To overcome this issue you need to adjust canvas virtual size before drawing:
function Draw () {
var e, surface;
e = document.getElementById ("surface");
/* Begin size adjusting. */
e.width = e.offsetWidth;
e.height = e.offsetHeight;
/* End size adjusting. */
surface = e.getContext ("2d");
surface.strokeRect (10, 10, 20, 20);
}
window.onload = Draw ()
<!DOCTYPE html>
<html>
<head>
<title>Canvas size adjusting demo</title>
</head>
<body>
<canvas id="surface"></canvas>
</body>
</html>
HTML:
Ok, I've figured this out once and for all. You need to do two things:
place any lines on 0.5 px. Refer to this, which provides a great explanation:
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors#A_lineWidth_example
There are essentially two heights and two widths associated with the canvas. There is the canvas height and width and then there is the css style height and width of the element. These need to be in sync.
To do this, you need to calculate the css height and width as:
var myCanvasEl = document.getElementById('myCanvas');
var ctx = myCanvasEl.getContext('2d');
myCanvasEl.style.height = myCanvasEl.height / window.devicePixelRatio + "px";
myCanvasEl.style.width = myCanvasEl.width / window.devicePixelRatio + "px";
where myCanvasEl.style.height and myCanvasEl.style.widthis the css styling height and width of the element, while myCanvasEl.height and myCanvasEl.width is the height and width of the canvas.
OLD ANSWER (superseded by above):
This is the best solution I've found in 2020. Notice I've multiplied the devicePixelRatio by 2:
var size = 100;
var scale = window.devicePixelRatio*2;
context.width = size * scale;
cartesian_001El.style.height = cartesian_001El.height / window.devicePixelRatio + "px";
cartesian_001El.style.height = cartesian_001El.height / window.devicePixelRatio + "px";
context.height = size * scale;
context.scale(scale, scale);
Something else that nobody talked about here when images are scaled (which was my issue) is imageSmoothingEnabled.
The imageSmoothingEnabled property of the CanvasRenderingContext2D interface, part of the Canvas API, determines whether scaled images are smoothed (true, default) or not (false). On getting the imageSmoothingEnabled property, the last value it was set to is returned.
This property is useful for games and other apps that use pixel art. When enlarging images, the default resizing algorithm will blur the pixels. Set this property to false to retain the pixels' sharpness.
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled
To disable it, simply set the properity to false:
ctx.imageSmoothingEnabled = false;
canvas.width=canvas.clientWidth
canvas.height=canvas.clientHeight
To avoid this issue in animation I would like to share a small demo.
Basically I am checking increment values each time & jumping in a set of 1px by removing float values.
HTML:
<canvas id="canvas" width="600" height="600"></canvas>
CSS:
html, body{
height: 100%;
}
body{
font-family: monaco, Consolas,"Lucida Console", monospace;
background: #000;
}
canvas{
position: fixed;
top: 0;
left: 0;
transform: translateZ(0);
}
JS:
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
ctx.translate(0.5, 0.5);
var i = 0;
var iInc = 0.005;
var range = 0.5;
raf = window.requestAnimationFrame(draw);
function draw() {
var animInc = EasingFunctions.easeInQuad(i) * 250;
ctx.clearRect(0, 0, 600, 600);
ctx.save();
ctx.beginPath();
ctx.strokeStyle = '#fff';
var rectInc = 10 + animInc;
// Avoid Half Pixel
rectIncFloat = rectInc % 1; // Getting decimal value.
rectInc = rectInc - rectIncFloat; // Removing decimal.
// console.log(rectInc);
ctx.rect(rectInc, rectInc, 130, 60);
ctx.stroke();
ctx.closePath();
ctx.font = "14px arial";
ctx.fillStyle = '#fff';
ctx.textAlign = 'center';
ctx.fillText("MAIN BUTTON", 65.5 + rectInc, 35.5 + rectInc);
i += iInc;
if (i >= 1) {
iInc = -iInc;
}
if (i <= 0) {
iInc = Math.abs(iInc);
}
raf = window.requestAnimationFrame(draw);
}
// Easing
EasingFunctions = {
// no easing, no acceleration
linear: function(t) {
return t
},
// accelerating from zero velocity
easeInQuad: function(t) {
return t * t
},
// decelerating to zero velocity
easeOutQuad: function(t) {
return t * (2 - t)
},
// acceleration until halfway, then deceleration
easeInOutQuad: function(t) {
return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t
},
// accelerating from zero velocity
easeInCubic: function(t) {
return t * t * t
},
// decelerating to zero velocity
easeOutCubic: function(t) {
return (--t) * t * t + 1
},
// acceleration until halfway, then deceleration
easeInOutCubic: function(t) {
return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
},
// accelerating from zero velocity
easeInQuart: function(t) {
return t * t * t * t
},
// decelerating to zero velocity
easeOutQuart: function(t) {
return 1 - (--t) * t * t * t
},
// acceleration until halfway, then deceleration
easeInOutQuart: function(t) {
return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t
},
// accelerating from zero velocity
easeInQuint: function(t) {
return t * t * t * t * t
},
// decelerating to zero velocity
easeOutQuint: function(t) {
return 1 + (--t) * t * t * t * t
},
// acceleration until halfway, then deceleration
easeInOutQuint: function(t) {
return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t
}
}
A related issue could be that you're setting the <canvas>'s height and width from CSS or other sources. I'm guessing it scales the canvas and associated drawings. Setting the <canvas> size using the height and width property (either from the HTML tag or a JS script) resolved the error for me.
Here is my solution: set width and height for canvas
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
Also set in css, so it will not overflow from its parent
canvas {
width: 100%
height: 100%
}
Although LittleJoe's solution worked perfect on desktop it didn't work on mobile because on iphone 11 pro for example the dpi is 3 so I had to set width/height based on dpi. At the end it worked:
let width = 100, height = 100;
const dpi = window.devicePixelRatio;
canvas = document.getElementById('myCanvas');
canvas.width = width * dpi;
canvas.height = height * dpi;
canvas.style.width = width + "px";
canvas.style.height = width + "px";
canvas.getContext('2d').scale(dpi, dpi);
in order to get rid of the blurryness you need to set the size of the canvas in two manners:
first withcanvas.width = yourwidthhere;
and canvas.height = yourheighthere;
second by setting the css attribute either by js or a stylesheet
HTML:
<canvas class="canvas_hangman"></canvas>
JS:
function setUpCanvas() {
canvas = document.getElementsByClassName("canvas_hangman")[0];
ctx = canvas.getContext('2d');
ctx.translate(0.5, 0.5);
// Set display size (vw/vh).
var sizeWidth = 80 * window.innerWidth / 100,
sizeHeight = 100 * window.innerHeight / 100 || 766;
// console.log(sizeWidth, sizeHeight);
// Setting the canvas height and width to be responsive
canvas.width = sizeWidth;
canvas.height = sizeHeight;
canvas.style.width = sizeWidth;
canvas.style.height = sizeHeight;
}
window.onload = setUpCanvas();
This perfectly sets up your HTML canvas to draw on, and in a responsive manner too :)