I've got a simple resize script as such:
$(`#game`).css('width', '100%');
$(window).resize(function(){
$(`#game`).height($(`#game`).width() / 2.031);
})
(from https://stackoverflow.com/a/10750346/12359120)
The problem though, as cyberwombat said,
"This will cause the content to be blurred."
The other answers on that post don't really work for my situation, as they often make the contents go offscreen.
Right now this is how blurry it is:
With the other answers:
Is there any way to make it less blurry?
Edit: The element's width and height always say 300 and 150 even though the styles say otherwise. Here is some HTML + CSS + JS that can mostly reproduce this.
const canvas = document.getElementById('game')
const ctx = canvas.getContext("2d");
$(`#game`).css('width', '100%');
$(window).resize(function() {
$(`#game`).height($(`#game`).width() / 2.031);
})
const imageAt = ((href, x, y, sizex, sizey) => {
var img = new Image();
img.addEventListener('load', function() {
ctx.drawImage(img, x, y, sizex, sizey);
}, false);
img.src = href
})
imageAt('https://b.thumbs.redditmedia.com/bZedgr0gq7RQBBnVYVc-Nmzdr-5vEUg4Dj8nTrMb7yA.png',0,0,25,25)
#game {
padding-left: 0;
padding-right: 0;
display: block;
padding: 0;
}
#vertical-center {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
body {
background-color: black;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div id="vertical-center">
<canvas id="game"></canvas>
</div>
Related
I have simple animation created using create js and ffmpegserver.js.
ffmpegserver.js.
This is a simple node server and library that sends canvas frames to the server and uses FFmpeg to compress the video. It can be used standalone or with CCapture.js.
Here is repo: video rendering demo.
on folder public, I have demos eg test3.html and test3.js
Test3.html
<!DOCTYPE html>
<html>
<head>
<title>TweenJS: Simple Tween Demo</title>
<style>
canvas {
border: 1px solid #08bf31;
justify-content: center;
display: flex;
align-items: center;
margin: 0px auto;
margin-bottom: 40px;
}
a {
width: 150px;
height: 45px;
background: red;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
border-radius: 300px;
color: white;
}
#container{
flex-direction: column;
justify-content: center;
display: flex;
align-items: center;
margin: 0px auto;
}
#progress{
margin: 30px;
}
#preview{
margin: 40px;
width: 150px;
height: 45px;
background: deepskyblue;
color: white;
border: none;
border-radius: 300px;
}
</style>
</head>
<body onload="init();">
<div>
<div id="container">
<h1>Simple Tween Demo</h1>
<canvas id="testCanvas" width="500" height="400"></canvas>
<div id="progress"></div>
</div>
</div>
<script src="http://localhost:8081/ffmpegserver/CCapture.js"></script>
<script src="http://localhost:8081/ffmpegserver/ffmpegserver.js"></script>
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>
<script src="test3.js"></script>
</body>
</html>
Test3.js
/* eslint-disable eol-last */
/* eslint-disable no-undef */
/* eslint-disable quotes */
var canvas, stage;
function init() {
var framesPerSecond = 60;
var numFrames = framesPerSecond * 5; // a 5 second 60fps video
var frameNum = 0;
var progressElem = document.getElementById("progress");
var progressNode = document.createTextNode("");
progressElem.appendChild(progressNode);
function onProgress(progress) {
progressNode.nodeValue = (progress * 100).toFixed(1) + "%";
}
function showVideoLink(url, size) {
size = size ? (" [size: " + (size / 1024 / 1024).toFixed(1) + "meg]") : " [unknown size]";
var a = document.createElement("a");
a.href = url;
var filename = url;
var slashNdx = filename.lastIndexOf("/");
if (slashNdx >= 0) {
filename = filename.substr(slashNdx + 1);
}
a.download = filename;
a.appendChild(document.createTextNode("Download"));
var container = document.getElementById("container").insertBefore(a, progressElem);
}
var capturer = new CCapture( {
format: 'ffmpegserver',
//workersPath: "3rdparty/",
//format: 'gif',
//verbose: true,
framerate: framesPerSecond,
onProgress: onProgress,
//extension: ".mp4",
//codec: "libx264",
} );
capturer.start();
canvas = document.getElementById("testCanvas");
stage = new createjs.Stage(canvas);
var ball = new createjs.Shape();
ball.graphics.setStrokeStyle(5, 'round', 'round');
// eslint-disable-next-line quotes
ball.graphics.beginStroke('#000000');
ball.graphics.beginFill("#FF0000").drawCircle(0, 0, 50);
ball.graphics.setStrokeStyle(1, 'round', 'round');
ball.graphics.beginStroke('#000000');
ball.graphics.moveTo(0, 0);
ball.graphics.lineTo(0, 50);
ball.graphics.endStroke();
ball.x = 200;
ball.y = -50;
createjs.Tween.get(ball, {loop: -1})
.to({x: ball.x, y: canvas.height - 55, rotation: -360}, 1500, createjs.Ease.bounceOut)
.wait(1000)
.to({x: canvas.width - 55, rotation: 360}, 2500, createjs.Ease.bounceOut)
.wait(1000)
.to({scaleX: 2, scaleY: 2}, 2500, createjs.Ease.quadOut)
.wait(1000)
stage.addChild(ball);
createjs.Ticker.addEventListener("tick", stage);
function render() {
requestAnimationFrame(render);
capturer.capture( canvas );
++frameNum;
if (frameNum < numFrames) {
progressNode.nodeValue = "rendered frame# " + frameNum + " of " + numFrames;
} else if (frameNum === numFrames) {
capturer.stop();
capturer.save(showVideoLink);
}
}
render();
}
Everything works fine, you can test it yourself if you want by cloning the repo.
Right now animation rendering happens in client side, I would like this animation rendering to happen in the backend side
What do I need to change to make this animation rendering in backend server side using Nodejs? any help or suggestions will be appreciated.
Since you do all your animations in the canvas, you can use node-canvas to do the same in Node.js. (You have to double check that create.js also work in Node.js, though. If not, find another library or write those routines yourself).
Spawn ffmpeg into it's own process accepting input through a pipe (ffmpeg -i - -f rawvideo -pix_fmt rgba etc. The pipe will probably be different according to which server environment you use). After each frame is drawn, extract the image array using canvas.getContext('2d').getImageData(0, 0, width, height).data and pipe the result to to ffmpeg.
I am having difficulty getting my image to rotate when I click on it.
I've attached a link to fiddle with my HTML, CSS and JS
http://jsfiddle.net/5x9tgo07/32/
Here is my HTML
<html>
<header>
<h1 id='heading'>SELF</h1>
</header>
<hr>
<body>
<div class='introCard'>
<img id='self' src="https://image.ibb.co/djffuz/self_eye_centered.jpg"/>
</div>
</body>
</html>
Here is my CSS
header {
width: 100%;
height: 75px;
display: flex;
flex-direction:column;
align-items: center;
}
.introCard {
width: 100%;
margin-top: 35px;
margin-bottom: 25px;
border-radius: 5px;
display: flex;
flex-direction: column;
align-items: center
}
div img {
width: 35%;
}
hr {
width: 50%
}
Here is my JS
let imageToSpin = document.getElementById('self');
function spinImage() {
imageToSpin.rotate(20 * Math.PI/180);
}
imageToSpin.onclick = spinImage;
rotate is not a method of the Element object.
A proper way to rotate the image would be adding (or toggling) a CSS class and rotate it using a rotate().
Using your example:
JS File
let imageToSpin = document.getElementById('self');
imageToSpin.onclick = function () {
imageToSpin.classList.toggle('rotated')
};
CSS File
.rotated {
transform: rotate(90deg)
}
And of course the image with self id in the HTML somewhere.
Here is your JSFiddle updated.
If you need to calculate the deg in JS, then you can set the CSS property by hand in the onclick function directly.
create a closure around the stuff you want to use, and then use the style.transform like so:
let imageToSpin = document.getElementById('self');
function spinImage(imageToSpin) {
var count = 0
return function() {
count += 10;
imageToSpin.style.transform = `rotate(${count}deg)`;
}
}
imageToSpin.onclick = spinImage(imageToSpin);
Here's how you could set it up in a quick and short way:
var rotate_angle = 0;
<img src='blue_down_arrow.png' onclick='rotate_angle = (rotate_angle + 180) % 360; $(this).rotate(rotate_angle);' /></a>
An HTML canvas element can be automatically resized by the dynamics of a HTML page: Maybe because its style properties are set to a percentage value, or maybe because it is inside a flex container.
Thereby the content of the canvas gets resized as well: Because of the interpolation the canvas content looks blurred (loss of resolution).
In order to keep the resolution to the maximum, one must render the canvas content based on the current pixel size of the element.
This fiddle shows how this can be done with the help of the function getComputedStyle: https://jsfiddle.net/fx98gmu2/1/
setInterval(function() {
var computed = getComputedStyle(canvas);
var w = parseInt(computed.getPropertyValue("width"), 10);
var h = parseInt(computed.getPropertyValue("height"), 10);
canvas.width = w;
canvas.height = h;
// re-rendering of canvas content...
}, 2000); // intentionally long to see the effect
With a setTimeout function I'm updating the width and height of the canvas to the computed values of these properties.
As the fiddle shows, this works only when increasing the size of the window. Whenever the window size gets decreased, the canvas (item of the flexbox) stays fixed.
Set its flex-basis to 0, allow it to shrink with flex-shrink, and don't force any minimum width:
#canvas {
flex: 1 1 0;
min-width: 0;
}
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
setInterval(function() {
var computed = getComputedStyle(canvas),
w = parseInt(computed.width, 10),
h = parseInt(computed.height, 10);
canvas.width = w;
canvas.height = h;
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.arc(w/2, h/2, h/2, 0, Math.PI*2, true);
ctx.stroke();
}, 2000); // intentionally long to see the effect
#container {
border: 1px solid blue;
width: 100%;
display: flex;
}
#canvas {
border: 1px solid red;
flex: 1 1 0;
min-width: 0;
height: 150px;
}
<div id="container">
<canvas id="canvas"></canvas>
<div>something else...</div>
</div>
You need to place the canvas into a container with overflow:hidden and set canvas dimensions to dimensions of that container:
window.setTimeout( function() {
var div = $("div");
div.find("canvas").attr( { width:div.width(), height:div.height()} );
})
canvas { background:gold; display:block; }
div { width:50%; height:50%; border:1px solid; overflow:hidden; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<canvas width="200" height="100" />
</div>
I'm trying to draw into a canvas, but the more I go right, the more offset my drawing become.
Anyone have an idea why?
I have included the relevant code below:
CSS
html,body {
width:100%;
height:100%;
background:rgba(0,0,0,.2);
}
#container {
position:relative;
width:700px;
height:450px;
background:#fff;
overflow:hidden;
}
* {
-webkit-user-select: none;
}
canvas {
position: absolute;
top: 0;
left: 0;
background: #ccc;
width: 500px;
height: 200px;
}
HTML
<div id='adContainer'>
<canvas></canvas>
</div>
Javascript
var ctx;
var can = $('canvas');
$(document).ready(function() {
ctx = can[0].getContext('2d');
ctx.strokeStyle = "rgba(255,0,0,1)";
ctx.lineWidth = 5;
ctx.lineCap = 'round';
can.on("touchstart", function(event) {
event.preventDefault();
var e = event.originalEvent;
if(e.touches.length == 1) {
var posX = e.touches[0].pageX;
var posY = e.touches[0].pageY;
ctx.moveTo(posX, posY);
}
});
can.on("touchmove", function(event) {
event.preventDefault();
var e = event.originalEvent;
if(e.touches.length == 1) {
var posX = e.touches[0].pageX;
var posY = e.touches[0].pageY;
ctx.lineTo(posX, posY);
ctx.stroke();
}
});
});
Demo: http://jsfiddle.net/8Wtf8/
That is because you define the size of the canvas using CSS.
What happens is that when you don't explicitly define the size of the canvas using its width and height attributes the canvas defaults to size 300 x 150.
In your CSS you are then stretching the canvas element (look at it as an image) to 500px etc. - the content of the canvas is still 300 x 150.
You need to set the width and height on the canvas element itself:
<canvas width=500 height=200 id="myCanvas"></canvas>
and remove the definition from the CSS:
canvas {
position: absolute;
top: 0;
left: 0;
background: #ccc;
/*width: 500px;
height: 200px;*/
}
Also notice that background set by CSS will not be part of the canvas content.
My code is below. I also have it at http://jsfiddle.net/S2JHa/
I do not understand why cursor changes to I-beam when I click and drag the mouse over my picture.
If I remove "some text" then it does not change. This happens in Chrome. FF is fine.
Please if you can tell how to fix that I would appreciate it.
Thanks!
<div id="window">
<div>some text</div>
<div id="sketch" class="box">
<div class="contents">
<canvas id="image-layer"></canvas>
</div>
</div>
</div>
CSS:
#window #sketch
{
padding: 1cm 0;
}
#window #sketch canvas
{
left: 0;
position: absolute;
top: 0;
}
#window #sketch .contents
{
cursor: crosshair;
position: relative;
}
div.box
{
background-color: #fff;
border: 1px solid black;
border-radius: 0.3cm;
cursor: move;
left: 0;
position: fixed;
top: 0;
}
JavaScript:
function image_onload(e) {
var image = e.target;
$("div.box").draggable({
cancel: "div.box div.contents",
containment: "document"
});
var x = $("#window #sketch");
// size to fit image
x.css("width", image.width);
x.css("height", image.height);
// center sketch inside parent window
x.css("left", ($(window).width() - x.width()) / 2);
var canvas = document.getElementById("image-layer");
canvas.height = image.height;
canvas.width = image.width;
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
}
function open(url) {
var image = new Image();
image.src = url;
image.onload = image_onload;
}
open("http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png");
If you don't want interactivity with the canvas you can cancel the onmousedown event like so:
canvas.onmousedown = function () {
return false;
}
Fr IE you will need:
canvas.onselectstart = function () {
return false;
}
See updated jsfiddle here: http://jsfiddle.net/S2JHa/11/