How to rotate rectangle in HTML canvas using Anime.js - javascript

I have created a rectangle on HTML canvas. I want to have a 45 degree rotation animation on this rectangle using Anime.js. I have seen number of posts on rectangle rotation but can't figure out how to rotate it using Anime.js. Following is my <body> tag:
<body class="container">
<canvas></canvas>
<script src="anime.min.js" type="text/javascript"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var canvas = document.querySelector('canvas');
canvas.width = 1280;
canvas.height = 720;
var c = canvas.getContext('2d');
//Create box
function Box(size) {
var box = {};
box.size = size;
box.x = 640 - (box.size/2);
box.y = 250 - (box.size/2);
box.translateX = 0;
box.translateY = 0;
box.degree = 0;
box.color = "#ffffff";
box.draw = function () {
c.save();
c.fillStyle = box.color;
c.translate(box.translateX, box.translateY);
c.rotate(box.degree * Math.PI/180);
c.fillRect(box.x, box.y, box.size, box.size);
c.restore();
};
return box;
}
var box = new Box(300);
box.draw();
anime.timeline().add({
targets: box,
x: -100,
y: -125,
translateX: 640,
translateY: 250,
degree: 45,
duration: 1000
})
});
</script>
</body>
Can anyone please help?

You mix up two different topics. Anime.js is good to animate dom elements. So in your case you can animate only complete canvas. Is not possible to animate rectangle inside. This is because animate.js is using DOM selectors and CSS technique.
So to animate complete canvas you can assign id
canvas id="myCanvas"></canvas>
In java-script code change only target
anime.timeline().add({
targets: '#myCanvas',
Other way is to paint rotated rectangle by your own on canvas.

Related

Resize Canvas html to fit the inner content

I am trying to record audio and draw the bars on canvas. But I am stuck on resizing the canvas according to the length of bars that are there. Following is the JS for all the work that is being done. I tried adding function to resize canvas, and override the canvas width but none is working.
css width:auto; is also not working. Following is the function That I have used to resize canvas according the to BARS length that are drawn.
I tried to override the canvas width inside stop function [Current Visual of Bars inside canvas][1]
Following code can be tested in this codepen https://codepen.io/smashingmag/pen/qBVzRaj
function resizeCanvas() {
CANVAS.width = BARS.length;
console.log(CANVAS.width);
}
resizeCanvas();
//Getting and initializing canvas from html to create bars
const CANVAS = document.querySelector('canvas')
const DRAWING_CONTEXT = CANVAS.getContext('2d')
//setting canvas height and width and bars configuration
CANVAS.width = CANVAS.offsetWidth
CANVAS.height = CANVAS.offsetHeight
const CONFIG = {
fft: 2048,
show: true,
duration: 0.8,
fps: 100,
barWidth: 0.1,
barMinHeight: 0.01,
barMaxHeight: 0.3,
barGap: 0.01,
}
//here I am creating bars
const addBar = (volume = 100) => {
const BAR = {
x: CANVAS.width + CONFIG.barWidth / 2,
// Note the volume is 0
size: gsap.utils.mapRange(
50,
150,
CANVAS.height * CONFIG.barMinHeight/3,
CANVAS.height * CONFIG.barMaxHeight*3
)(volume),
}
const drawBars = () => {
DRAWING_CONTEXT.clearRect(0, 0, CANVAS.width, CANVAS.height)
for (const BAR of BARS) {
drawBar(BAR)
}
}
STOP.addEventListener('click', () => {
if (recorder) recorder.stop()
AUDIO.setAttribute('controls', true)
AUDIO_CONTEXT.close()
timeline.pause()
SCRUB(START_POINT)
var delayInMilliseconds = 1000; //1 second
setTimeout(function() {
//Here i am getting the canvas image on console
const img = CANVAS.toDataURL("image/png");
console.log(img);
}, delayInMilliseconds);
})
drawBars()
[1]: https://i.stack.imgur.com/JBBjT.png
I looked at your codepen and I think yours has a simple solution
function resizeCanvas() {
CANVAS.style.width = BARS.length + "px";
CANVAS.width = BARS.length;
}
This is just setting the CSS width property using javascript.
Doing CANVAS.width = 500 does not overwrite the CSS which tells it to be 300px. So it was still a CSS problem.

How to properly Down-sampling HTML Canvas for good looking images?

Introduction
I'm trying to deal with blurry visuals on my canvas animation. The blurriness is especially prevalent on mobile-devices, retina and high-dpi (dots-per-inch) screens.
I'm looking for a way to ensure the pixels that are drawn using the canvas look their best on low-dpi screens and high-dpi screens. As a solution to this problem I red multiple articles about canvas-down-scaling and followed this tutorial:
https://www.kirupa.com/canvas/canvas_high_dpi_retina.htm
Integrating down-scaling in the project
The project in which I want to implement down-scaling can be found below and consists of a few important features:
There is a (big) main canvas. (Performance optimization)
There are multiple (pre-rendered) smaller canvasses that are used to draw and load a image into. (Performance optimization)
The canvas is animated. (In the code snippet, there is no visible animation but the animation function is intergrated.)
Question
What im trying to achieve: The problem I'm facing seems quite simple. When the website (with the canvas) is opened on a mobile device (eg. an Iphone, with more pixels per inch then a regular desktop). The images appear more blurry. What I'm actually trying to achieve is to remove this blurriness from the images. I red this and it stated that blurriness can be removed by downsampling. I tried to incorporate this technique in the code provided, but it did not work completely. The images just became larger and I was unable to scale the images back to the original size. snippet it is not implemented correctly, the output is still blurry. What did I do wrong and how am I able to fix this issue?
Explanation of the code snippet
The variable devicePixelRatio is set to 2 to simulate a high-dpi phone screen, low-dpi screens have a devicePixelRatio of 1.
Multiple pre-rendered canvasses generated is the function spawn is the snippet there are 5 different canvasses, but on the production environment there are 10's.
If there are any pieces of information missing or questions about this post, please let me know. Thanks a lot!
Code Snippet
var canvas = document.querySelector('canvas');
var c = canvas.getContext('2d' );
var circles = [];
//Simulate Retina screen = 2, Normal screen = 1
let devicePixelRatio = 2
function mainCanvasPixelRatio() {
// get current size of the canvas
let rect = canvas.getBoundingClientRect();
// increase the actual size of our canvas
canvas.width = rect.width * devicePixelRatio;
canvas.height = rect.height * devicePixelRatio;
// ensure all drawing operations are scaled
c.scale(devicePixelRatio, devicePixelRatio);
// scale everything down using CSS
canvas.style.width = rect.width + 'px';
canvas.style.height = rect.height + 'px';
}
// Initial Spawn
function spawn() {
for (let i = 0; i < 2; i++) {
//Set Radius
let radius = parseInt(i*30);
//Give position
let x = Math.round((canvas.width/devicePixelRatio) / 2);
let y = Math.round((canvas.height /devicePixelRatio) / 2);
//Begin Prerender canvas
let PreRenderCanvas = document.createElement('canvas');
const tmp = PreRenderCanvas.getContext("2d");
//Set PreRenderCanvas width and height
let PreRenderCanvasWidth = ((radius*2)*1.5)+1;
let PreRenderCanvasHeight = ((radius*2)*1.5)+1;
//Increase the actual size of PreRenderCanvas
PreRenderCanvas.width = PreRenderCanvasWidth * devicePixelRatio;
PreRenderCanvas.height = PreRenderCanvasHeight * devicePixelRatio;
//Scale PreRenderCanvas down using CSS
PreRenderCanvas.style.width = PreRenderCanvasWidth + 'px';
PreRenderCanvas.style.height = PreRenderCanvasHeight + 'px';
//Ensure PreRenderCanvas drawing operations are scaled
tmp.scale(devicePixelRatio, devicePixelRatio);
//Init image
const image= new Image();
//Get center of PreRenderCanvas
let m_canvasCenterX = (PreRenderCanvas.width/devicePixelRatio) * .5;
let m_canvasCenterY = (PreRenderCanvas.height/devicePixelRatio) * .5;
//Draw red circle on PreRenderCanvas
tmp.strokeStyle = "red";
tmp.beginPath();
tmp.arc((m_canvasCenterX), (m_canvasCenterY), ((PreRenderCanvas.width/devicePixelRatio)/3) , 0, 2 * Math.PI);
tmp.lineWidth = 2;
tmp.stroke();
tmp.restore();
tmp.closePath()
//Set Image
image .src= "https://play-lh.googleusercontent.com/IeNJWoKYx1waOhfWF6TiuSiWBLfqLb18lmZYXSgsH1fvb8v1IYiZr5aYWe0Gxu-pVZX3"
//Get padding
let paddingX = (PreRenderCanvas.width/devicePixelRatio)/5;
let paddingY = (PreRenderCanvas.height/devicePixelRatio)/5;
//Load image
image.onload = function () {
tmp.beginPath()
tmp.drawImage(image, paddingX,paddingY, (PreRenderCanvas.width/devicePixelRatio)-(paddingX*2),(PreRenderCanvas.height/devicePixelRatio)-(paddingY*2));
tmp.closePath()
}
let circle = new Circle(x, y, c ,PreRenderCanvas);
circles.push(circle)
}
}
// Circle parameters
function Circle(x, y, c ,m_canvas) {
this.x = x;
this.y = y;
this.c = c;
this.m_canvas = m_canvas;
}
//Draw circle on canvas
Circle.prototype = {
//Draw circle on canvas
draw: function () {
this.c.drawImage( this.m_canvas, (this.x - (this.m_canvas.width)/2), (this.y - this.m_canvas.height/2));
}
};
// Animate
function animate() {
//Clear canvas each time
c.clearRect(0, 0, (canvas.width /devicePixelRatio), (canvas.height /devicePixelRatio));
//Draw in reverse for info overlap
circles.slice().reverse().forEach(function( circle ) {
circle.draw();
});
requestAnimationFrame(animate);
}
mainCanvasPixelRatio()
spawn()
animate()
#mainCanvas {
background:blue;
}
<canvas id="mainCanvas"></canvas>
<br>
<!DOCTYPE html>
<html>
<body>
<p>Image to use:</p>
<img id="scream" width="220" height="277"
src="pic_the_scream.jpg" alt="The Scream">
<p>Canvas:</p>
<canvas id="myCanvas" width="240" height="297"
style="border:1px solid #d3d3d3;">
</canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var img = document.getElementById("scream");
ctx.drawImage(img, 10, 10);
};
</script>
</body>

Javascript ES6 HTML5 canvas images not drawing to background canvas or background canvas not showing

Images are not drawing to bg_canvas with a z-index of 0, only my main game canvas overlay is showing, i have only included the start of the code.
// HTML
<canvas id="bg-canvas" width="768" height="600"></canvas>
<canvas id="canvas" width="768" height="600"></canvas>
// CSS
canvas {
position: absolute;
top: 0;
left: 0;
}
#canvas {
z-index: 1
}
#bg-canvas {
z-index: 0
}
// Javascript
const bg_canvas = document.getElementById('bg-canvas');
const bg_ctx = bg_canvas.getContext("2d");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const map = {
object: {
brickwall: new Image(),
woodenbox: new Image()
}
};
map.object.brickwall.src = "objects/brickwall.jpeg";
map.object.woodenbox.src = "objects/boximage.jpg";
ctx.clearRect(0,0,canvas.width,canvas.height);
bg_ctx.clearRect(0,0,bg_canvas.width,bg_canvas.height);
// var currentItemEquipped;
// drawImage(imgsrc, xcoord, ycoord, sizex, sizey) // drawImage parameters
map.object.brickwall.onload = () => bg_ctx.drawImage(map.object.brickwall, 100, 100, 100, 100);
map.object.woodenbox.onload = () => bg_ctx.drawImage(map.object.woodenbox, 200, 200, 100, 100);
The player is drawing and the rest of the code is working completely fine however, i am not able to draw these images to the canvas, it may be a problem with z-indexes or that the overlaying canvas is not transparent.
Have you tried "window.addEventListener" ?
Because sometimes i got the same issue in some browsers...
try this:
function LoadImages(){
bg_ctx.drawImage(map.object.brickwall, 100, 100, 100, 100);
bg_ctx.drawImage(map.object.woodenbox, 200, 200, 100, 100);
}
window.addEventListener("load", LoadImages);
Had to call the function inside the draw method, not sure why though since the background canvas is never cleared.

How to drawImage behind all other content on a canvas? [duplicate]

This question already has an answer here:
HTML Canvas: Drawing grid below a plot
(1 answer)
Closed 6 years ago.
I have a canvas, and I want to use drawImage to draw an image behind the current content on the canvas.
Due to the fact that there is content already on the canvas (I'm using Literally Canvas to create a canvas containing an image, so I can't really draw the image first), I cannot use drawImage before I render the rest of my content.
Is it possible to drawImage behind all other content on a canvas?
Yes you can just use globalCompositeOperation destination-over, but note that your first image needs some transparency, otherwise, you will obviously not see anything :
var img1 = new Image();
var img2 = new Image();
var loaded = 0;
var imageLoad = function(){
if(++loaded == 2){
draw();
}
};
img1.onload = img2.onload = imageLoad;
var draw = function(){
var ctx = c.getContext('2d');
ctx.drawImage(img1, 100,100);
// wait a little bit before drawing the background image
setTimeout(function(){
ctx.globalCompositeOperation = 'destination-over';
ctx.drawImage(img2, 0,0);
}, 500);
}
img1.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png";
img2.src = "https://picsum.photos/200/200";
<canvas id="c" width="200" height="200"></canvas>
Sorry about the previous post, I didn't properly read your post
Perhaps you could save the canvas, draw your image, and then reload the old content on top of your drawn image? Here's some JS psuedocode:
var imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
ctx.drawImage('Your Image Watermark Stuff');
ctx.putImageData(imgData,0,0);
You can use KonvaJS. And then use layers for it.
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.rawgit.com/konvajs/konva/0.13.0/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Rect Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var baseImage = new Konva.Image({
x: 50,
y: 50,
width: width,
height: height,
image: image
});
// add the shape to the layer
layer.add(rect);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'url to your image'
</script>
</body>
</html>
A simple solution would be to use another canvas behind the first one.
Normally canvas pixels are initialized to transparent black and therefore are perfectly see-through.
If your first canvas is created opaque instead the only other option I can think to is
create a temporary canvas of the same size
draw your image in this temporary canvas
get the ImageData object of both the temporary canvas and of the original canvas
copy from the temporary canvas to the original canvas only where the original canvas is not set at the background color
In code:
var tmpcanvas = document.createElement("canvas");
tmpcanvas.width = canvas.width;
tmpcanvas.height = canvas.height;
var temp_ctx = tmpcanvas.getContext("2d");
// ... draw your image into temporary context ...
var temp_idata = temp_ctx.getImageData(0, 0, canvas.width, canvas.height);
var temp_data = temp_idata.data;
// Access the original canvas pixels
var ctx = canvas.getContext("2d");
var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = idata.data;
// Find the background color (here I'll use first top-left pixel)
var br_r = data[0], bg_g = data[1], bg_b = data[2];
// Replace all background pixels with pixels from temp image
for (var i=0,n=canvas.width*canvas.height*4; i<n; i+=4) {
if (data[i] == bg_r && data[i+1] == bg_g && data[i+2] == bg_b) {
data[i] = tmp_data[i];
data[i+1] = tmp_data[i+1];
data[i+2] = tmp_data[i+2];
data[i+3] = tmp_data[i+3];
}
}
// Update the canvas
ctx.putImageData(idata, 0, 0);
this approach however will have a lower quality if the original canvas graphics has been drawn with antialiasing or if pixels of the background color are also used in the image (e.g. an object on #FFF white background where object highlights are also #FFF). Another problem is if the background color is not a perfectly uniform RGB value (this will happen if the image has been compressed with a lossy algorithm like jpeg).
All these problems could be mitigated with more sophisticated algorithms like range matching, morphological adjustments and color-to-alpha conversions (basically the same machinery used for chroma-keying).

How to move canvas elements?

How to move first element with black fill to mouse cursor? Or just how to move it to my position in event handler?
Javascript:
var drawing = document.getElementById('canvas');
var ctx = drawing.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(188, 50, 200, 100);
ctx.fillStyle = 'yellow';
ctx.fillRect(0, 0, 200, 100);
document.onmousemove = function(e) {
/* How to move rectangle here? */
}
http://jsfiddle.net/9545qbo4/1/
Thanks in advance.
I think it is not possible on canvas, but your function can do it like this:
ctx.clearRect(/* Old rect position */);
ctx.fillRect(/* New rect position*/);
EDIT: The same question is here.

Categories

Resources