HTML:
<canvas id="cnvs" width=1 height=250 style="border:1px solid #000000;"></canvas>
JS:
// Square size
var squareSize = 50;
// Trail size (smaller number means more trail)
var globalAlpha = 0.0025;
// Text
var text = "Lorem Ipsum";
console.clear();
var cnvs = document.getElementById("canvas");
var ctx = cnvs.getContext("2d");
var windW = window.innerWidth;
cnvs.width = windW - 20;
var cnvsH = cnvs.height;
function MouseMove(XMouse, YMouse) {
console.clear();
ctx.fillStyle = "#000000";
ctx.globalAlpha = 1;
ctx.fillRect(
XMouse - 10 - squareSize / 2,
YMouse - 10 - squareSize / 2,
squareSize,
squareSize
);
}
function handler(e) {
e = e || window.event;
var pageX = e.pageX;
var pageY = e.pageY;
if (pageX === undefined) {
pageX =
e.clientX +
document.body.scrollLeft +
document.documentElement.scrollLeft;
pageY =
e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
console.log(pageX, pageY);
MouseMove(pageX, pageY);
}
if (document.attachEvent) document.attachEvent("onmousemove", handler);
else document.addEventListener("mousemove", handler);
var loop = setInterval(function() {
ctx.fillStyle = "#FFFFFF";
ctx.globalAlpha = globalAlpha;
ctx.fillRect(0, 0, windW, CnvsH);
ctx.font = "100px Arial";
ctx.globalAlpha = 1;
ctx.fillStyle = "#000000";
ctx.textAlign = "center";
ctx.fillText(text, windW / 2, cnvsH / 2);
}, 10);
What's Expected is a Square That Fades Away, With Text In The Center
The square is drawn correctly, but the fade doesn't happen, and the text doesn't appear.
I use codepen for my coding.
It was working, but I think I tried adding comments, and something I did while doing that broke it. I haven't graduated high school so I don't have any college experience and all my coding is self-taught and tutorials (Thanks w3schools.com)
in your code are 2 mistakes.
First:
"var cnvs = document.getElementById("canvas");"
Your ID is - "var cnvs = document.getElementById("cnvs");"
And secound:
In your "var loop" there is a typo mistake for
"ctx.fillRect(0, 0, windW, CnvsH);" it should be "cnvsH" and not "CnvsH".
right -> ctx.fillRect(0, 0, windW, cnvsH);
Gl and try to use a Debugger.
Related
I am trying to draw multiple rectangles on canvas. I am able to do it except its not clearing rectangles as the mouse moves.
And when i try to clear rectangle using clearRect then the back image on canvas is also gets cleared. So I have commented out //ctx.clearRect(0, 0, canvas.width, canvas.height); in the code below
I have gone through several SO posts with similar questions but doesn't seems work
$(function(){
var canvas = document.getElementById('myCanvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.fillText("Sample String", 20, 50);
}
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function (e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function (e) {
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
//ctx.clearRect(0, 0, canvas.width, canvas.height);
var width = mousex - last_mousex;
var height = mousey - last_mousey;
ctx.beginPath();
ctx.rect(last_mousex, last_mousey, width, height);
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.stroke();
}
//Output
$('#results').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
});
})
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
Use mouse to draw multiple rectangles with in the canvas
</h3>
<canvas id="myCanvas"></canvas>
<div id="results">
</div>
your mistake was you cleared all the canvas:
ctx.clearRect(0, 0, canvas.width, canvas.height);
instead of clearing just the area you drew before:
ctx.clearRect(prev_x-1, prev_y-1, prev_w+2, prev_h+2);
I wrote the basic idea here, but you need to add some code to clear the area depends on the direction the mouse was, and moving to (try to move your mouse to each of the corners and see what happens).
$("#clear").click(function(){
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillText("Sample String", 20, 50);
});
$(function(){
var canvas = document.getElementById('myCanvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.fillText("Sample String", 20, 50);
}
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = w = h = 0;
var prev_x = prev_y = prev_w = prev_h = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function (e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function (e) {
w = h = 0;
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
prev_x = last_mousex;
prev_y = last_mousey;
prev_w = w;
prev_h = h;
ctx.clearRect(prev_x-1, prev_y-1, prev_w+2, prev_h+2);
w = mousex - last_mousex;
h = mousey - last_mousey;
ctx.beginPath();
ctx.rect(last_mousex, last_mousey, w, h);
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.stroke();
}
//Output
$('#results').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
});
})
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
Use mouse to draw multiple rectangles with in the canvas
</h3>
<button id="clear">clear</button>
<br />
<canvas id="myCanvas"></canvas>
<div id="results">
</div>
I think you can come to another approach
By using mousedown event only then save all rectangle to an array variable
Then you can clear and redraw the whole canvas with the saved variable
var shapes = [];
canva.addEventListener('mousedown', mouseDownListener);
class Rectangle() {
public ctx, x, y, w, h;
public Rectangle(ctx, x, y, w, h) {
this.ctx = ctx;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
public draw() {
// draw using ctx here
}
}
function mouseDownListener() {
// create rectable
var rectangle = new Rectangle(ctx, x, y, width, height);
// save rectangle to an array
shapes.push(rectangle);
// redraw canvas
redraw();
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw all rectangle
shapes.forEach(function(shape) {
// draw shape
shape.draw();
})
}
Only want shadows to animate and keep the fillText from animating due to letters pixelating from getting ran over and over.
var canvas = document.getElementById('canvas')
var ctx = this.canvas.getContext('2d')
var width = canvas.width = canvas.scrollWidth
var height = canvas.height = canvas.scrollHeight
var start;
var j=0;
var makeText = function(){
j+=1
ctx.shadowColor= 'red';
ctx.shadowOffsetX = j; //animate
ctx.shadowOffsetY = j; //animate
ctx.globalAlpha=0.5;
ctx.font = "48px serif";
ctx.fillStyle = "black";
ctx.fillText('hey you', width/2, height / 2); //Only ran once so letters
//don't pixelate!
}
function animateText(timestamp){
var runtime = timestamp - start;
var progress = Math.min(runtime / 1400, 1);
makeText(progress)
if(progress < 1){
requestAnimationFrame(animateText)
}else {
return;
}
}
requestAnimationFrame(function(timestamp){
start = timestamp;
animateText(timestamp)
})
<canvas id="canvas" width=500px height=500px></canvas>
My outcome of the process would only have shadows animate and keeping letters where they are
Just draw your own shadows, here is an example:
var canvas = document.getElementById('canvas')
var ctx = this.canvas.getContext('2d')
ctx.font = "68px serif";
var base = {text: 'hey you', x: 10, y: 60 }
var inc = 2;
var j = 30;
var makeText = function() {
ctx.globalAlpha = 1;
ctx.fillStyle = "black";
ctx.fillText(base.text, base.x, base.y);
}
var makeshadow = function(offset) {
ctx.fillStyle = "red";
for (var i = 0; i < offset; i++) {
ctx.globalAlpha = 1/i;
ctx.fillText(base.text, base.x + i, base.y + i);
}
}
function animateText() {
ctx.clearRect(0, 0, 999, 999)
makeshadow(j);
makeText();
j += inc;
if (j > 35 || j < 3) inc *= -1
}
setInterval(animateText, 50)
<canvas id="canvas" width=300px height=170px></canvas>
And if you add some math in the mix you can get some cool effects:
var canvas = document.getElementById('canvas')
var ctx = this.canvas.getContext('2d')
ctx.font = "68px serif";
var base = {text: '123456', x: 30, y: 80 }
var inc = 5;
var j = 0;
var makeText = function() {
ctx.globalAlpha = 1;
ctx.fillStyle = "black";
ctx.fillText(base.text, base.x, base.y);
}
var makeshadow = function(offset) {
ctx.globalAlpha = 0.05;
ctx.fillStyle = "red";
for (var i = 0; i < offset; i++)
ctx.fillText(base.text, base.x + Math.sin(i/5)*10, base.y + Math.cos(i/5)*15);
}
function animateText() {
ctx.clearRect(0, 0, 999, 999)
makeshadow(j);
makeText();
j += inc;
if (j > 120 || j < 0) inc *= -1
}
setInterval(animateText, 50)
<canvas id="canvas" width=300px height=170px></canvas>
Your main issue (the text pixelisation) is due to you not clearing the canvas between every frames, and drawing again and again over the same position. semi-transparent pixels created by antialiasing mix up to more and more opaque pixels.
But in your situation, it seems that you actually want at-least the shadow to mix up like this.
To do it, one way would be to draw only once your normal text, and to be able to draw only the shadow, behind the current drawing.
Drawing only the shadow of a shape.
One trick to draw only the shadows of your shape is to draw your shape out of the visible viewPort, with shadowOffsets set to the inverse of this position.
var text = 'foo bar';
var ctx = canvas.getContext('2d');
var original_x = 20; // the position it would have been
ctx.font = '30px sans-serif';
var targetPosition = ctx.measureText(text).width + original_x + 2;
// default shadow settings
ctx.shadowColor = 'red';
ctx.shadowBlur = 3;
// just to show what happens
var x = 0;
anim();
function anim() {
if(++x >= targetPosition) {
x=0;
return;
}
// if we weren't to show the anim, we would use 'targetPosition'
// instead of 'x'
ctx.shadowOffsetX = x;
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillText(text, -x + original_x, 30);
requestAnimationFrame(anim);
}
// restart the anim on click
onclick = function() {
if(x===0)anim();
};
<canvas id="canvas"></canvas>
Once we have this clear shadow, without our shape drawn on it, we can redraw it as we wish.
Drawing behind the current pixels
The "destination-over" compositing option does just that.
So if we put these together, we can draw behind the normal text, and only draw our shadow behind it at each frame, avoiding antialiasing mix-up.
(Note that we can also keep the clean shadow on an offscreen canvas for performances, since shadow is a really slow operation.)
var text = 'foo bar';
var ctx = canvas.getContext('2d');
ctx.font = '48px sans-serif';
var x = 20;
var y = 40;
var shadow = generateTextShadow(ctx, text, x, y, 'red', 5);
ctx.globalAlpha = 0.5;
ctx.fillText(text, x, y);
// from now on we'll draw behind current content
ctx.globalCompositeOperation = 'destination-over';
var shadow_pos = 0;
anim();
// in the anim, we just draw the shadow at a different offset every frame
function anim() {
if(shadow_pos++ > 65) return;
ctx.drawImage(shadow, shadow_pos, shadow_pos);
requestAnimationFrame(anim);
}
// returns a canvas where only the shadow of the text provided is drawn
function generateTextShadow(original_ctx, text, x, y, color, blur, offsetX, offsetY) {
var canvas = original_ctx.canvas.cloneNode();
var ctx = canvas.getContext('2d');
ctx.font = original_ctx.font;
var targetPosition = ctx.measureText(text).width + 2;
// default shadow settings
ctx.shadowColor = color || 'black';
ctx.shadowBlur = blur || 0;
ctx.shadowOffsetX = targetPosition + x +(offsetX ||0);
ctx.shadowOffsetY = (offsetY || 0);
ctx.fillText(text, -targetPosition, y);
return canvas;
}
<canvas id="canvas"></canvas>
I have drawn an arc on a canvas, this arc has 3 parts. If user clicks on any one of the part then my code will show an alert with the x and y position. Now I want to highlight this clicked region. How do I do that?
This code draws the arc:
var canvas = document.getElementById('zone');
if(!canvas.getContext){
alert("canvas not supported");
}
else {
var canvasContent = canvas.getContext('2d');
var zoneX = canvas.width / 2;
var zoneY = canvas.height / 2;
var radius = 100;
canvasContent.beginPath();
canvasContent.arc(zoneX,zoneY, radius, 0, 2 * Math.PI, false);
canvasContent.fillStyle = 'white';
canvasContent.fill();
canvasContent.lineWidth = 1;
canvasContent.strokeStyle = '#333';
canvasContent.stroke();
drawLine(canvasContent);
$('#zone').on('click',function(e){
var clickX = e.clientX;
var clickY = e.clientY;
alert(clickX + " : "+clickY);
});
}
function drawLine(canvasContentDrawLine) {
canvasContentDrawLine.beginPath();
canvasContentDrawLine.moveTo(canvas.width / 2, canvas.width / 2);
canvasContentDrawLine.lineTo(canvas.width / 2.5, canvas.height / 4.7);
canvasContentDrawLine.moveTo(338, 200 );
canvasContentDrawLine.lineTo(canvas.width / 2.5, canvas.height / 4.7);
canvasContentDrawLine.stroke();
}
Fiddle
This code will show an alert with the position:
$('#zone').on('click',function(e){
var clickX = e.clientX;
var clickY = e.clientY;
alert(clickX + " : "+clickY);
});
I want to move one canvas on top of another. when top canvas moves the base canvas displays its x and y. The event initially starts at mouse down. so press mouse and start moving the canvas moves smoothly from right to left but not left to right.
http://jsfiddle.net/happyomi/23PL3/3/
<head>
<style type="text/css">
body, html {
margin: 0;
}
canvas {
position: absolute;
/* top: 0;
left: 0;*/
}
#temp {
background-color: pink;
}
</style>
</head>
<body style="margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden;">
<canvas id="myCanvas" style="display: block;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas id="temp" style="position: relative">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var hgap = 0;
var vgap = 0;
var rows, cols;
var annotation_x = 1;
var row = 0; var col = 0;
//ctx.font = "14px Arial";
c.width = $(document).width();
c.height = $(document).height();
var t = document.getElementById("temp");
tctx = t.getContext("2d");
// tctx.lineWidth = 10;
tctx.lineJoin = 'round';
tctx.lineCap = 'round';
tctx.strokStyle = 'red';
var mouse = { x: 0, y: 0 };
c.addEventListener('mousemove', function (evt) {
mouse.x = evt.pageX;
mouse.y = evt.pageY;
}, false);
c.addEventListener('mousedown', function (evt) {
// tctx.clearRect(0, 0, c.width, c.height);
evt.preventDefault();
ctx.clearRect(0, 0, c.width, c.height);
tctx.clearRect(0, 0, c.width, c.height);
mouse.x = evt.pageX;
mouse.y = evt.pageY;
t.style.left = mouse.x + "px";
t.style.top = mouse.y + "px";
t.style.position = "absolute";
str = "x=" + mouse.x + " y=" + mouse.y;
ctx.fillText(str, 10, 10);
c.addEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function () {
ctx.clearRect(0, 0, c.width, c.height);
tctx.clearRect(0, 0, t.width, t.height);
t.style.left = mouse.x + "px";
t.style.top = mouse.y + "px";
t.style.position = "absolute";
str = "x=" + mouse.x + " y=" + mouse.y;
ctx.fillText(str, 10, 10);
}
c.addEventListener('mouseup', function () {
c.removeEventListener('mousemove', onPaint, false);
}, false);
</script>
</body>
Heres A good Starting point for ya :) it does what your looking for. jsFiddle
/* Main Canvas */
var main = document.getElementById('main');
main.width = window.innerWidth;
main.height = window.innerHeight;
var mainCtx = main.getContext('2d');
var mainFill = '#000';
mainCtx.fillStyle = mainFill;
mainCtx.rect(0,0,main.width,main.height);
mainCtx.fill();
/* secondary canvas */
var cv = document.createElement('canvas');
cv.style.position = 'absolute';
cv.width = '200';
cv.height = '100';
cv.style.left = '0px';
cv.style.top = '0px';
var ctx = cv.getContext('2d');
var fillRect = '#ccc';
var fillText = '#000';
ctx.fillStyle = fillRect;
ctx.rect(0,0,cv.width,cv.height);
ctx.fill();
//draw this canvas to main canvas
mainCtx.drawImage(cv,parseInt(cv.style.left),parseInt(cv.style.top));
var isHolding = false;
var mDown = function(e)
{
isHolding = true;
main.addEventListener('mousemove',mMove);
}
var mMove = function(e)
{
console.log('moving');
if(isHolding)
{
var xPos = e.pageX;
var yPos = e.pageY;
cv.style.left = (xPos-(cv.width/2))+'px';
cv.style.top = (yPos-(cv.height/2))+'px';
cv.width = cv.width; //clears canvas
ctx.fillStyle = fillRect;
ctx.rect(0,0,cv.width,cv.height);
ctx.fill();
ctx.fillStyle = fillText;
ctx.fillText('x: '+e.pageX,10,10);
ctx.fillText('y: '+e.pageY,50,10);
//draw temp canvas to main canvas
this.width = this.width;
mainCtx.fillStyle = mainFill;
mainCtx.rect(0,0,main.width,main.height);
mainCtx.fill();
mainCtx.drawImage(cv,parseInt(cv.style.left),parseInt(cv.style.top));
}
}
var mUp = function(e)
{
isHolding = false;
main.removeEventListener('mousemove',mMove);
}
main.addEventListener('mousedown',mDown);
main.addEventListener('mouseup',mUp);
also it gets rid of the move event when not being used which will help have less event dispatches in memory and help with performance.
I have a rectangle (which should appear) on a canvas, that I want to move from side to side of the canvas. The code I have atm however isn't working, as nothing is showing up at all! Any help would be appreciated, cheers!
<!DOCTYPE html>
<html>
<head>
<title>Simple animations in HTML5</title>
<!--<script>
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect (20, 50, 200, 100);
</script> -->
<script>
function drawMessage()
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect(x, y, WIDTH, HEIGHT);
context.fillStyle = "white";
context.font = "30px Arial";
context.fillText ("Hello World", MESSAGE_WIDTH, MESSAGE_HEIGHT);
x += dx;
y += dy;
if(x <= 0 || x >= 500)
{
dx = -dx;
}
if(y <= 0 || y >= 200)
{
dy = -dy
}
function animate()
{
return setInterval(drawMessage, 10);
}
</script>
</head>
<body>
<h2> Optical Illusion </h2>
<video id="illusion" width="640" height="480" controls>
<source src="Illusion_movie.ogg">
</video>
<div id="buttonbar">
<button onclick="changeSize()">Big/Small</button>
</div>
<p>
Watch the animation for 1 minute, staring at the centre of the image. Then look at something else near you.
For a few seconds everything will appear to distort.
Source: Wikipedia:Illusion movie
</p>
<script type="text/javascript">
var myVideo=document.getElementById("illusion");
var littleSize = false;
function changeSize()
{
myVideo.width = littleSize ? 800 : 400;
littleSize = !littleSize;//toggle boolean
}
</script>
<canvas id="myCanvas" width="500" height="500">
</canvas>
<!--<script type="text/javascript">
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect(20, 50, 200, 100);
context.fillStyle = "white";
context.font = "30px Arial";
context.fillText ("Hello World", 35, 110);
</script> -->
<script>
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var x = 20; // x coordinate of box position
var y = 50; // y coordinate of box position
var dx = 2; // amount to move box to the right
var dy = 4; // amount to move box down
var WIDTH = 500; // width of canvas
var HEIGHT = 200; // height of canvas
var MESSAGE_WIDTH = 200; // width of message
var MESSAGE_HEIGHT = 100; // height of message
animate(); // run the animation
</script>
</body>
</html>
It seems to me like the first script portion of your code might be missing curly braces.
Specifically, the portion:
function drawMessage()
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect(x, y, WIDTH, HEIGHT);
context.fillStyle = "white";
context.font = "30px Arial";
context.fillText ("Hello World", MESSAGE_WIDTH, MESSAGE_HEIGHT);
x += dx;
y += dy;
if(x <= 0 || x >= 500)
{
dx = -dx;
}
if(y <= 0 || y >= 200)
{
dy = -dy
}
Might work better as:
function drawMessage()
{
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect(x, y, WIDTH, HEIGHT);
context.fillStyle = "white";
context.font = "30px Arial";
context.fillText ("Hello World", MESSAGE_WIDTH, MESSAGE_HEIGHT);
x += dx;
y += dy;
if(x <= 0 || x >= 500)
{
dx = -dx;
}
if(y <= 0 || y >= 200)
{
dy = -dy
}
}