HTML, CSS, JS, Canvas rectangle not deleting - javascript

I would like the rectangle to move on the canvas and not copy every time.
It draws it but then the rectangle stays there.
I am a beginner with the canvas so if it is an epic fail then be prepared.
The codepen is at LINK.
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var boxWidth = 50;
var boxHeight = 50;
var bX = WIDTH / 2 - boxWidth / 2;
var bY = HEIGHT / 2 - boxHeight / 2;
function render() {
ctx.fillStyle = "white";
ctx.rect(bX, bY, boxWidth, boxHeight);
ctx.fill();
}
function control() {
bX++;
}
function main() {
control();
render();
}
main();
var run = setInterval(main, 10)
canvas {
width: 400px;
height: 400px;
background-color: black;
}
div {
text-align: center;
}
<div>
<canvas width="400px" height="400px" background-color="black" id="canvas"></canvas>
</div>

Repaint your canvas before drawing the rectangle each time - think about it. Its all done in layers.
The rectangle is "staying there" because you aren't replacing the rectangle your drew last time.
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var boxWidth = 50;
var boxHeight = 50;
var bX = WIDTH / 2 - boxWidth / 2;
var bY = HEIGHT / 2 - boxHeight / 2;
function render() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); //use clear rect instead
ctx.fillStyle = "white";
ctx.fillRect(bX, bY, boxWidth, boxHeight); //use fillRect instead of fill()
}
function control() {
bX++;
}
(function main() {
control();
render();
requestAnimationFrame(()=>main());
})()
canvas {
width: 400px;
height: 400px;
background-color: black;
}
div {
text-align: center;
}
<html>
<head></head>
<body>
<div>
<canvas width="400px" height="400px" background-color="black" id="canvas"></canvas>
</div>
</body>
</html>
Also have a look at the requestAnimationFrame() method as opposed to setInterval - it syncs up with the window's javascript timer and is less likely to cause problems.

Related

Saturate image where mouse is hovering

I'm trying to have an image on my website become saturated at the same location the mouse is. When the mouse moves the saturation effect goes with it, and the area previously hovered over becomes grayscale again. I'm thinking this effect could be accomplished using saturate(), however I haven't had any success with it. Additionally, I would like the effect to be circular without hard edges similar to this.
Example of what it would look like (orange arrow indicating where the mouse is).
Any help or insight would be appreciated, thanks!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content= "width=device-width, initial-scale=1.0" />
</head>
<script>
const size = 250;
var radius = 30;
var rad = Math.PI / 180;
var canvas = document.querySelector("canvas")
var ctx = canvas.getContext("2d");
canvas.width = size;
canvas.height = size;
var image = new Image();
image.onload = demo
image.src = "https://picsum.photos/250"
function draw_circle(x, y, radius) {
ctx.clearRect(0, 0, size, size);
ctx.drawImage(image, 0, 0); // image to change
ctx.globalCompositeOperation = "saturation";
ctx.beginPath();
ctx.fillStyle = "hsl(0,100%,50%)"; // saturation at 100%
ctx.arc(x, y, radius, 0, 360 * rad, false);
ctx.fill()
ctx.closePath();
ctx.globalCompositeOperation = "source-over"; // restore default comp
}
function demo() {
ctx.drawImage(image, 0, 0); // image to change
canvas.addEventListener('mousemove', function(ev) {
var cx = ev.offsetX
var cy = ev.offsetY
draw_circle(cx, cy, radius)
})
}
</script>
<canvas></canvas>
</html>
Using a canvas we can try. Here's a start inspired by How can I adjust the huse, saturation, and lightness of in image in HTML5 Canvas?.
const size = 250;
var radius = 30;
var rad = Math.PI / 180;
var canvas = document.querySelector("canvas")
var ctx = canvas.getContext("2d");
canvas.width = size;
canvas.height = size;
var image = new Image();
image.onload = demo
image.src = "https://picsum.photos/250"
function draw_circle(x, y, radius) {
ctx.clearRect(0, 0, size, size);
ctx.drawImage(image, 0, 0); // image to change
ctx.globalCompositeOperation = "saturation";
ctx.beginPath();
ctx.fillStyle = "hsl(0,100%,50%)"; // saturation at 100%
ctx.arc(x, y, radius, 0, 360 * rad, false);
ctx.fill()
ctx.closePath();
ctx.globalCompositeOperation = "source-over"; // restore default comp
}
function demo() {
ctx.drawImage(image, 0, 0); // image to change
canvas.addEventListener('mousemove', function(ev) {
var cx = ev.offsetX
var cy = ev.offsetY
draw_circle(cx, cy, radius)
})
}
<canvas></canvas>
This is a simple answer (change the logic of the program as you want):
<!DOCTYPE html>
<html>
<head>
<style>
div.relative {
position: relative;
width: 200px;
height: 150px;
}
.image {
width: 100%;
height: 100%;
}
</style>
<script>
const width = 50;
const height = 50;
function create() {
const element = document.createElement("div");
element.id = "filtered";
element.style.width = `${width}px`;
element.style.height = `${height}px`;
element.style.borderRadius = "50%";
element.style.position = "absolute";
element.style.backgroundColor = "red";
element.style.opacity = "0.2";
element.style.zIndex = "2";
return element;
}
function changePos(e) {
x = e.clientX;
y = e.clientY;
let element = document.getElementById("filtered");
if (!element) {
element = create();
document.getElementById("focusArea").appendChild(element);
}
element.style.left = `${x - width / 2}px`;
element.style.top = `${y - height / 2}px`;
}
function removeElement() {
if (document.getElementById("filtered")) {
document.getElementById("filtered").remove();
}
}
</script>
</head>
<body>
<div
id="focusArea"
onmouseleave="removeElement()"
onmousemove="changePos(event)"
class="relative"
>
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/800px-Image_created_with_a_mobile_phone.png"
class="image"
/>
</div>
</body>
</html>

Canvas fill viewport and keep image ratio

I am trying to make the canvas area and image fill the viewport without the image stretching and retain its aspect ratio when you resize the page. Below is my current code.
var ctx = $("#demo")[0].getContext("2d"),
img = new Image(),
radius = 35,
blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";
img.src = blurryImageSrc;
$(img).on("load", function() {
resizeCanvas();
$("#demo").on("mousemove", function(e) {
erase(getXY(e));
});
$("#reset").on("click", function() {
ctx.globalCompositeOperation = "source-over";
ctx.drawImage(img, 0, 0);
ctx.globalCompositeOperation = "destination-out";
});
ctx.drawImage(img, 0, 0, window.innerWidth, window.innerHeight);
ctx.globalCompositeOperation = "destination-out";
});
function getXY(e) {
var r = $("#demo")[0].getBoundingClientRect();
return { x: e.clientX - r.left, y: e.clientY - r.top };
}
function erase(pos) {
ctx.beginPath();
ctx.arc(pos.x, pos.y, radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
}
var can = document.getElementById('demo');
function resizeCanvas() {
can.style.width = window.innerWidth + 'px';
setTimeout(function() {
can.style.height = window.innerHeight + 'px';
}, 0);
}
window.onresize = resizeCanvas;
resizeCanvas();
https://jsfiddle.net/65fph0mn/8/
To retain the image's correct proportions, you need to query it's 'natural' width and height. The image object itself has two properties for this purpose: naturalWidth and naturalHeight.
As the image finished loading you must decide by which factor to scale the image based on the dimensions of the browser window and the longer side of your image.
Let's have a look at a simple example. Say your browser window's width is 1200 pixel and the image 250. If we now divide 1200 by 250 we get 4.8 - that's the factor we need to multiply the image's width and height to fill the current browser window in one direction while maintaining it's correct aspect ratio.
Here's an example:
var ctx = $("#demo")[0].getContext("2d"),
img = new Image(),
radius = 35,
blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";
/// setup logic
img.src = blurryImageSrc;
$(img).on("load", function() {
resizeCanvas();
});
var can = document.getElementById('demo');
function resizeCanvas() {
can.width = window.innerWidth;
can.height = window.innerHeight;
if (img.width > 0) {
let factor = can.width / img.naturalWidth * img.naturalHeight > window.innerHeight ? can.height / img.naturalHeight : can.width / img.naturalWidth;
ctx.drawImage(img, 0, 0, img.naturalWidth * factor, img.naturalHeight * factor);
}
}
window.onresize = resizeCanvas;
resizeCanvas();
body {
background: lightgrey;
margin: 0;
}
.container {
position: relative;
background: blue;
width: 100vw;
height: 100vh;
}
#demo {
cursor: crosshair;
width: 100vw;
height: 100vh;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div class="container">
<canvas id="demo" width=640 height=640></canvas>
</div>
Here I'm waiting for the image to load. Then I can add the eventlistener for window resize and call the function resizeCanvas. This function will then resize the canvas and paint the image in the canvas.
The image must be repainted every time the window is resized.
To keep the aspect ratio the height of the image is calculated from the scaled width.
const canvas = document.getElementById('demo');
var ctx = canvas.getContext("2d"),
img = new Image(),
blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";
img.src = blurryImageSrc;
img.addEventListener("load", e => {
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
});
function paint() {
var newHeight = Math.round(img.width/canvas.width*img.height);
ctx.drawImage(img, 0, 0, img.width, newHeight, 0, 0, canvas.width, canvas.height);
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
paint();
}
body {
background: lightgrey;
margin: 0;
}
.container {
position: relative;
background: blue;
width: 100vw;
height: 100vh;
}
#demo {
cursor: crosshair;
width: 100vw;
height: 100vh;
}
<div class="container">
<canvas id="demo" width="640" height="640"></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.

JS Canvas: How to make rectangle go back and forth once it reaches the boundary

So I have this rectangle that animates across to the right. How can I get the rectangle to reverse it when it hits the boundaries. I'm trying to make it go back and forth.
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>
window.onload=function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
var y = 50;
var width = 10;
var height = 10;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, y, width, height);
x++;
if(x <= 490) {
setTimeout(animate, 33);
}
}
animate();
}
</script>
</head>
<body>
<canvas id="canvas" width="500" height="400"
style="border: 1px solid #000000;"></canvas>
</body>
</html>
https://codepen.io/forTheLoveOfCode/pen/wqdpeg
Is that what you need? (link to codepen above).
var canvas = document.getElementById("canvas_id");
var context = canvas.getContext('2d');
var x=5;
var y=5;
var velocity = 10;
function move(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
x =x + velocity
if ((x+50)>canvas.width || x<0){
velocity *=-1;
}
draw()
}
function draw(){
context.fillStyle = "#E80C7A";
context.strokeStyle = "#000000";
context.lineWidth = '3';
context.fillRect(x, y, 50, 100);
context.strokeRect(x, y, 50, 100);
}
setInterval(move, 100);
<html>
<body>
<canvas id = "canvas_id">
</canvas>
</body>
</html>
here's a solution with boundaries detection
window.onload=function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
var y = 50;
var width = 10;
var height = 10;
var speed = 10; // speed
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, y, width, height);
if(
(x >= 500 - width && speed > 0) || // going to the right and bound reached
(x <= 0 && speed < 0) // going to the left and bound reached
) {
speed *= -1; // inverting the direction
}
x += speed;
setTimeout(animate, 33);
}
animate();
}
<canvas id="canvas" width="500" height="400"
style="border: 1px solid #000000;"></canvas>
consider using requestAnimationFrame instead of setTimeout to do this kind of work.

How to zoom to center of canvas, not to center of context

I have a canvas, size 400 x 400. On it, i have drawn a map area, 200 x 200.
I have translated this to the center of the canvas. I can zoom in and out, all is well. But, when i pan, it zooms from the center of my map area. I want it to always zoom from the center of the canvas no matter where the map area is. I think i need to negate the pan coords somehow, but i can't figure it out.
Here is my code:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var canvas1 = document.getElementById("canvasX");
var ctxX = canvas1.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var mapW = 200;
var mapH = 200;
var panX=0;
var panY=0;
var scaleFactor=1.00;
drawTranslated();
function zoomIn(){
document.getElementById("zoomin").click();
{ scaleFactor*=1.1; drawTranslated(); };
}
function zoomOut(){
document.getElementById("zoomout").click();
{ scaleFactor/=1.1; drawTranslated(); };
}
function panUp(){
document.getElementById("panup").click();
{ panY-=25; drawTranslated(); };
}
function panDown(){
document.getElementById("pandown").click();
{ panY+=25; drawTranslated(); };
}
function panLeft(){
document.getElementById("panleft").click();
{ panX-=25; drawTranslated(); };
}
function panRight(){
document.getElementById("panright").click();
{ panX+=25; drawTranslated(); };
}
function drawTranslated(){
// canvas
ctx.clearRect(0,0,cw,ch);
ctx.save();
ctx.translate(cw/2, ch/2);
ctx.translate(panX,panY);
ctx.scale(scaleFactor, scaleFactor);
ctx.fillStyle = "Green";
ctx.fillRect(mapW/-2, mapH/-2, mapW, mapH);
ctx.restore();
// canvasX
ctxX.clearRect(0,0,cw,ch);
ctxX.save();
ctxX.translate(cw/2, ch/2);
ctxX.beginPath();
ctxX.moveTo(0, 25);
ctxX.lineTo(0, -25);
ctxX.moveTo(-25, 0);
ctxX.lineTo(25, 0);
ctxX.closePath();
ctxX.lineWidth = 1;
ctxX.strokeStyle = 'Black';
ctxX.stroke();
ctxX.restore();
}
#wrapper {position: relative;}
canvas {position: absolute; border: 1px solid Black;}
<!DOCTYPE html>
<html>
<body>
<div id="wrapper">
<button id="zoomin" class="nav" title="Zoom In" onclick="zoomIn()">+</button>
<button id="zoomout" class="nav" title="Zoom Out" onclick="zoomOut()">−</button>
<button id="panup" class="nav" title="Up" onclick="panUp()">⇧</button>
<button id="pandown" class="nav" title="Down" onclick="panDown()">⇩</button>
<button id="panleft" class="nav" title="Left" onclick="panLeft()">⇦</button>
<button id="panright" class="nav" title="Right" onclick="panRight()">⇨</button>
</div>
<div id="wrapper">
<canvas id="myCanvas" width="400" height="400"></canvas>
<canvas id="canvasX" width="400" height="400"></canvas>
</div>
</body>
</html>
After some time of trying to find some equation to solve this, i think i have found the solution.
ctx.translate(panX,panY);
ctx.scale(scaleFactor, scaleFactor);
By panning first, then scaling, it will zoom from the center of the context (In this case the green square). However, simply changing it around to:
ctx.scale(scaleFactor, scaleFactor);
ctx.translate(panX,panY);
it will zoom from the center of the canvas.
It seems to do what i want it to, so unless i am mistaken, i believe this is the answer.
I have included another snippet. The only changes are those 2 lines, but i think it would be helpful for people to able to see the difference it makes.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas1 = document.getElementById("canvasX");
var ctxX = canvas1.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var mapW = 200;
var mapH = 200;
var panX = 0;
var panY = 0;
var scaleFactor = 1.00;
drawTranslated();
function zoomIn() {
document.getElementById("zoomin").click(); {
scaleFactor *= 1.1;
drawTranslated();
};
};
function zoomOut() {
document.getElementById("zoomout").click(); {
scaleFactor /= 1.1;
drawTranslated();
};
};
function panUp() {
document.getElementById("panup").click(); {
panY -= 25;
drawTranslated();
};
};
function panDown() {
document.getElementById("pandown").click(); {
panY += 25;
drawTranslated();
};
};
function panLeft() {
document.getElementById("panleft").click(); {
panX -= 25;
drawTranslated();
};
};
function panRight() {
document.getElementById("panright").click(); {
panX += 25;
drawTranslated();
};
};
function drawTranslated() {
// canvas
ctx.clearRect(0, 0, cw, ch);
ctx.save();
ctx.translate(cw / 2, ch / 2);
ctx.scale(scaleFactor, scaleFactor);
ctx.translate(panX, panY);
ctx.fillStyle = "Green";
ctx.fillRect(mapW / -2, mapH / -2, mapW, mapH);
ctx.restore();
// canvasX
ctxX.clearRect(0, 0, cw, ch);
ctxX.save();
ctxX.translate(cw / 2, ch / 2);
ctxX.beginPath();
ctxX.moveTo(0, 25);
ctxX.lineTo(0, -25);
ctxX.moveTo(-25, 0);
ctxX.lineTo(25, 0);
ctxX.closePath();
ctxX.lineWidth = 1;
ctxX.strokeStyle = 'Black';
ctxX.stroke();
ctxX.restore();
};
#wrapper {
position: relative;
}
canvas {
position: absolute;
border: 1px solid Black;
}
<div id="wrapper">
<button id="zoomin" class="nav" title="Zoom In" onclick="zoomIn()">+</button>
<button id="zoomout" class="nav" title="Zoom Out" onclick="zoomOut()">−</button>
<button id="panup" class="nav" title="Up" onclick="panUp()">⇧</button>
<button id="pandown" class="nav" title="Down" onclick="panDown()">⇩</button>
<button id="panleft" class="nav" title="Left" onclick="panLeft()">⇦</button>
<button id="panright" class="nav" title="Right" onclick="panRight()">⇨</button>
</div>
<div id="wrapper">
<canvas id="canvas" width="400" height="400"></canvas>
<canvas id="canvasX" width="400" height="400"></canvas>
</div>
There surely is a better way but in Fabric.js you can do
canvas.zoomToPoint(new fabric.Point(canvas.width / 2, canvas.height / 2), canvas.getZoom() / ZOOM_PERCENT);
See more here Canvas
For a more pure solution, you can also try translating the context by half the canvas size using
ctx.translate()
A fiddle that might help
http://jsfiddle.net/m1erickson/QEuw4/

Categories