How to make mousemove event working for touchscreen with touchmove? - javascript

I'm working on a canvas javascript where with the mousemove event you can erase the background...
Now i'm trying to get the same experience for touchscreens (mobile).
How can I give my code the mousemove and touchmove event at the same time?
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
/*this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();*/
var radgrad = ctx.createRadialGradient(x, y, 0, x, y, radius);
radgrad.addColorStop(0, 'rgba(255,0,0,1)');
radgrad.addColorStop(0.8, 'rgba(255,0,0,.9)');
radgrad.addColorStop(1, 'rgba(255,0,0,0)');
// draw shape
ctx.fillStyle = radgrad;
ctx.fillRect(x - radius, y - radius, x + radius, y + radius);
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 1, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 100; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmouseenter = function(e) {
canvas.isDrawing = true;
};
}
var container = document.getElementById('canvas');
init(container, 5000, 3000, '#f8fa58');
})();
body {
margin-left: -10vw;
margin-top: -30vh;
background: url(https://i-d-images.vice.com/images/articles/meta/2014/10/21/untitled-article-1413860640.jpg?crop=1xw:0.44513137557959814xh;0xw,0.14219474497681608xh&resize=2000:*&output-format=image/jpeg&output-quality=75) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
#canvas {
z-index: -1;
top: 2vh;
left: -10vw;
width: 110vw;
height: 130vh;
overflow: hidden;
}
<div id="back"></div>
<div id="canvas"></div>

You can use the same event handler, but inside, you'll have to process the event differently, because there is no clientX nor clientY property on touch[XXX] events.
Touch events can be multi-touch, so they do hold an array of touches, which have these coordinate properties.
IMO a cleaner way would be to split your event handler in two different phases :
one to extract the event's coordinates, and one to do something with these coords.
(function() {
// a little verbose but...
function handleMousemove(event){
var x = event.clientX;
var y = event.clientY;
draw(x, y);
}
function handleTouchmove(event){
event.preventDefault(); // we don't want to scroll
var touch = event.touches[0];
var x = touch.clientX;
var y = touch.clientY;
draw(x, y);
}
// this one can be shared by both touch and move events
function activateDrawing(event){
event.preventDefault();
canvas.isDrawing = true;
}
function draw(eventX, eventY){
var x = eventX - canvas.node.offsetLeft;
var y = eventY - canvas.node.offsetTop;
if (!canvas.isDrawing) {
return;
}
var radius = 100; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
}
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
var canvas, ctx; // got it out to avoid nesting too deeply my handlers;
function init(container, width, height, fillColor) {
canvas = createCanvas(container, width, height);
ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
var radgrad = ctx.createRadialGradient(x, y, 0, x, y, radius);
radgrad.addColorStop(0, 'rgba(255,0,0,1)');
radgrad.addColorStop(0.8, 'rgba(255,0,0,.9)');
radgrad.addColorStop(1, 'rgba(255,0,0,0)');
// draw shape
ctx.fillStyle = radgrad;
ctx.fillRect(x - radius, y - radius, x + radius, y + radius);
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 1, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = throttle(handleMousemove);
canvas.node.ontouchmove = throttle(handleTouchmove);
canvas.node.onmouseenter =
canvas.node.ontouchstart = throttle(activateDrawing);
}
var container = document.getElementById('canvas');
init(container, 5000, 3000, '#f8fa58');
/* Bonus : throttle these events so they don't fire too often */
function throttle(callback) {
var active = false; // a simple flag
var evt; // to keep track of the last event
var handler = function(){ // fired only when screen has refreshed
active = false; // release our flag
callback(evt);
}
return function handleEvent(e) { // the actual event handler
evt = e; // save our event at each call
if (!active) { // only if we weren't already doing it
active = true; // raise the flag
requestAnimationFrame(handler); // wait for next screen refresh
};
}
}
})();
body {
margin-left: -10vw;
margin-top: -30vh;
background: url(https://i-d-images.vice.com/images/articles/meta/2014/10/21/untitled-article-1413860640.jpg?crop=1xw:0.44513137557959814xh;0xw,0.14219474497681608xh&resize=2000:*&output-format=image/jpeg&output-quality=75) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
#canvas {
z-index: -1;
top: 2vh;
left: -10vw;
width: 110vw;
height: 130vh;
overflow: hidden;
}
<div id="back"></div>
<div id="canvas"></div>

Related

Make erase work for thoughscreen (TouchEvent)

i made a simple game where you have to erase a colored layer to reveal a image. But it only works on my desktop, not on something with a thoughscreen (iphone or ipad). I know i have to replace the MouseEvent to TouchEvent but i don't know how since i am a beginner at coding. I hope someone can help me with this!
#canvas {
background-image: url("img/image.jpg");
background-repeat: no-repeat;
width: 800px;
height: 800px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Ellen Langendam</title>
<link href="style.css" rel="stylesheet">
</head>
<body>
<div id="canvas"></div>
<script>
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 10, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 40; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
};
}
var container = document.getElementById('canvas');
init(container, 800, 800, '#99ff99');
})();
</script>
</body>
</html>
Register touch movements with ontouchmove and then interate through the touch points event.touches and use the properties from each of those items to draw your circle, the same way you do it in onmousemove.
I would also suggest turning to using let or const type of variables rather than var as var's can result in unfortunate issues, see: What's the difference between using "let" and "var"?
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 10, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 40; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
};
canvas.node.ontouchmove = function(event) {
for(let index = 0; index < event.touches.length; index++) {
const touch = event.touches[index];
const x = touch.pageX - this.offsetLeft;
const y = touch.pageY - this.offsetTop;
const radius = 40; // or whatever
const fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
}
};
}
var container = document.getElementById('canvas');
init(container, 800, 800, '#99ff99');
#canvas {
background-image: url("img/image.jpg");
background-repeat: no-repeat;
width: 800px;
height: 800px;
}
<div id="canvas"></div>

How do I make the JavaScript canvas cover the whole screen?

(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "black");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 40; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = false;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = true;
};
}
var container = document.getElementById('canvas');
init(container, 531, 438, 'black');
})();
#canvas {
/* background:url(); */
width: 100vw;
height: 100vh;
background-color: rgb(224, 255, 226);
}
<div id="canvas"></div>
I'm starting out quite new to coding, I'm trying to get the JavaScript to cover the whole of the rgb(224, 255, 226) - that mint looking color. So basically I want to whole thing back. Please help and thank you in advance for the help :)
This is code I found on the internet, I tried to find the person that made it to ask them but they did not reply
When you call init(), instead of passing static values for width and height, pass the size of the window.
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "black");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 40; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = false;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = true;
};
}
var container = document.getElementById('canvas');
// Instead of passing static values for width and height,
// pass the size of the window.
init(container, window.innerWidth, window.innerHeight, 'black');
})();
#canvas {
/* background:url(); */
width: 100vw;
height: 100vh;
background-color: rgb(224, 255, 226);
}
<div id="canvas" height="50" width="50"></div>
You need to pass window.innerWidth and window.innerHeight as parameters to init function.
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "black");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 40; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = false;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = true;
};
}
var container = document.getElementById('canvas');
init(container, window.innerWidth, window.innerHeight, 'black');
})();
<div id="canvas"></div>

How to scale an image for a canvas pattern?

I want to fill a Canvas with an Image and scale it to a certain width beforehand.
I am trying to achieve an effect where an image in the foreground of the canvas can be erased with the mouse to view an image in the background. This is why I need to use a pattern to fill my canvas instead of just using drawImage(). Everything works apart from the scaling of the foreground image. Here is my code for generating the pattern:
var blueprint_background = new Image();
blueprint_background.src = "myfunurl";
blueprint_background.width = window.innerWidth;
blueprint_background.onload = function(){
var pattern = context.createPattern(this, "no-repeat");
context.fillStyle = pattern;
context.fillRect(0, 0, window.innerWidth, 768);
context.fill();
};
This does exactly what it should do, except that the image keeps its original size.
As you see, I want the image to scale to window.innerWidth (which has the value 1920 when logging it).
If needed, I can provide the rest of the code, but since the error is most likely in this snippet, I decided not to post the rest.
EDIT: Here is my full code with the suggested changes. The front ground image now displays over the full width, however the erasing does not work anymore.
JavaScript (Note that I use jQuery instead of $):
jQuery(document).ready(function() {
var cwidth = window.innerWidth;
var cheight = 768;
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(canvas, fillColor) {
var ctx = canvas.context;
canvas.isDrawing = true;
jQuery('#canvas').children().css('position:absolute; top: ' + jQuery('#Top_bar').height() + 'px');
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
// bind mouse events
canvas.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - jQuery('#Top_bar').outerHeight();
var radius = 30;
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
}
var container = document.getElementById('canvas');
jQuery('#canvas').css('position:absolute; top: ' + jQuery('#Top_bar').height() + 'px');
var canvas = createCanvas(container, cwidth, cheight);
init(canvas, '#ddd');
var fgimg = document.getElementById("fgimg");
fgimg.width = cwidth;
var context = canvas.node.getContext("2d");
let canvasP = document.getElementById("pattern");
canvasP.width = window.innerWidth;
canvasP.height = 768;
let ctxP = canvasP.getContext("2d");
ctxP.drawImage( fgimg, 0, 0,window.innerWidth,768 );
context.fillStyle = context.createPattern(canvasP,"no-repeat");
context.fillRect(0,0, canvas.width, canvas.height);
});
CSS:
#canvas {
background:url(http://ulmke-web.de/wp-content/uploads/2019/01/Header-6.jpg);
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
width: 100%;
height: 768px;
}
HTML:
<div id="canvas">
<canvas id="pattern">
</div>
<div style="display:none">
<img id="fgimg" src=" http://ulmke-web.de/wp-content/uploads/2019/01/Header-5.jpg">
</div>
I would use two canvases. On the first one you draw your image and you use this canvas as an image to create the pattern. In order to scale the image you scale the size of the first canvas #pattern in my example.
For example you can do this for a 10/10 image:
canvasP.width = 10;
canvasP.height = 10;
ctxP.drawImage( redpoint, 2.5, 2.5 );
or you can do this for a 20/20 image:
canvasP.width = 20;
canvasP.height = 20;
ctxP.drawImage( redpoint, 5, 5,10,10 );
Furthermore, in my example I'm adding a little margin around the image.
let canvasP = document.getElementById("pattern");
if (canvasP && canvasP.getContext) {
let ctxP = canvasP.getContext("2d");
/*canvasP.width = 10;
canvasP.height = 10;
ctxP.drawImage( redpoint, 2.5, 2.5 ); */
canvasP.width = 20;
canvasP.height = 20;
ctxP.drawImage( redpoint, 5, 5,10,10 );
}
let canvas1 = document.getElementById("canvas");
if (canvas1 && canvas1.getContext) {
let ctx1 = canvas1.getContext("2d");
if (ctx1) {
ctx1.fillStyle = ctx1.createPattern(canvasP,"repeat");
ctx1.fillRect(0,0, canvas1.width, canvas1.height);
}
}
canvas{border:1px solid}
<img id="redpoint" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO 9TXL0Y4OHwAAAABJRU5ErkJggg==">
<canvas id="pattern"></canvas>
<canvas id="canvas"></canvas>
I hope it helps.

How do I erase image with cursor to reveal another image?

Okay, so I know there is a similar post to this (javascript erase image with cursor) but I've seen it and the code linked in the answers and I was wondering if there was a way to edit the code so that instead of erasing a solid color to reveal an image, I could erase an image to reveal a different image.
This is the code/markup from the site.
HTML
<div id="canvas"></div>
CSS
#canvas {
background:url(http://www.topscratchcards.com/images/games/888ladies/scratchcard-winning-ticket.jpg);
width: 531px;
height: 438px;
}
JAVASCRIPT
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 20; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
};
}
var container = document.getElementById('canvas');
init(container, 531, 438, '#ddd');
})();
I don't know if there is a way to edit this code to achieve what I want - if there isn't then is there any alternative method/code I could use?
There's an alternative.
You can use .innerHTML to resolve your problem.
eg. take a div with name mydiv
< img id="myImage"
src="http://www.w3schools.com/js/pic_bulboff.gif"
onmouseover="document.getElementById('myImage').src='http://www.w3schools.com/js/pic_bulbon.gif'"
onmouseout="document.getElementById('myImage').src='http://www.w3schools.com/js/pic_bulboff.gif'"
>
Ideally this sould solve your purpose
$("svg").on("mousemove", function (e) {
var x = e.pageX - $("#mySvg").offset().left;
var y = e.pageY - $("#mySvg").offset().top;
// console.log(x);
// console.log(y);
$(".a").attr("cx", x).attr("cy", y);
});
#mySvg {
width: 531px;
height: 438px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg id="mySvg">
<clippath id="clip">
<circle cx="-20" cy="-20" r="80" class="a" />
</clippath>
<image preserveAspectRatio="xMidYMin slice"
href="https://www.gannett-cdn.com/presto/2021/03/02/USAT/a51266de-f2dc-404c-a46a-bcca17c496eb-matrix-reloaded-keanu-reeves.png?width=660&height=372&fit=crop&format=pjpg&auto=webp"
class="one" />
<image preserveAspectRatio="xMidYMin slice" href="https://static.dw.com/image/56167112_303.jpg"
clip-path="url(#clip)" />
</svg>

How to fade out an item in canvas

I have a full screen canvas in my page. There are also some dive elements over this canvas. there is an circle element in the canvas that moves with the cursor everywhere in the page. However when the cursor arrives to the div element over the canvas, the circle shape stays in the last place it was on the canvas before arriving to the div.
DEMO: JSFIDDLE
Is ther any way that I can fade-out the circle shape when the cursor is over the div element and fade it in when it backs to the canvas?
Also is there any other effect rather than fading out? like making it small and then fade-out...
Here is the bit of code related to the circle:
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.fillStyle = 'black';
context.beginPath();
context.arc(x, y, 60, 0, 2 * Math.PI);
}
Well, you can always create your own fade function that gets called on mouseout (or mouseleave) event. Here's one I quickly built for you:
function fadeOut(canvas, message, x, y, amount) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
context.beginPath();
context.arc(x, y, amount, 0, 2 * Math.PI);
if (amount > 0) {
setTimeout(function(){
fadeOut(canvas, message, x, y, --amount);
}, 2);
}
else {
context.clearRect(0, 0, canvas.width, canvas.height);
}
}
See it in action here: http://jsfiddle.net/2p9dn8ed/42/
Or in the snippet:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = window.innerWidth;
var height = window.innerHeight;
var imageObj = new Image();
console.log(window.innerWidth + "----" + window.innerHeight);
//Create another canvas to darw a resized image to.
var imageResized = document.createElement('canvas');
imageResized.width = width;
imageResized.height = height;
//Wait for the original image to low to draw the resize.
imageObj.onload = function() {
//Find hoe mauch to scale the image up to cover.
var scaleX = width / imageObj.width;
var scaleY = height / imageObj.height;
var scaleMax = Math.max(scaleX, scaleY);
var ctx = imageResized.getContext('2d');
ctx.scale(scaleMax, scaleMax);
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 60, 0, 2 * Math.PI);
//context.stroke();
//
}
function fadeOut(canvas, message, x, y, amount) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, amount, 0, 2 * Math.PI);
//context.stroke();
//
if (amount > 0) {
setTimeout(function(){
fadeOut(canvas, message, x, y, --amount);
}, 2);
}
else {
context.clearRect(0, 0, canvas.width, canvas.height);
}
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas.addEventListener('mouseout', function(evt){
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
console.log(1);
fadeOut(canvas, message, mousePos.x, mousePos.y, 60);
});
// Get the canvas element form the page
var canvas = document.getElementById("myCanvas");
/* Rresize the canvas to occupy the full page,
by getting the widow width and height and setting it to canvas*/
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
anvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('../img/spiral_galaxy-1920x1080.jpg');
background-size: cover;
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
z-index:-1;
}
div{
width:200px;
height:200px;
background:rgba(0,0,0,0.5);
position: fixed;
top: 20%;
left: 20%;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<div><h1>TEXT</h1></div>

Categories