I am currently trying to create a canvas that has a background and a crosshair like object that follows around your mouse, everything works besides the crosshair still showing where it was previously drawn. I'm not sure where to clear the canvas without everything on the canvas being cleared and not showing up here is my code.
canvas = document.querySelector("canvas");
ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
class Background {
constructor(x, y, width, height, color) {
this.x = x,
this.y = y,
this.width = width,
this.height = height,
this.color = color
}
drawBackground() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
const backgroundSky = new Background(0, 0, canvas.width, canvas.height, "#89CFF0");
const backgroundGrass = new Background(0, canvas.height/1.2,canvas.width, canvas.height, "green");
backgroundSky.drawBackground();
backgroundGrass.drawBackground();
class Lens {
constructor(x, y, radius, color) {
this.x = x,
this.y = y,
this.radius = radius,
this.color = color
}
drawLens() {
ctx.lineWidth = 10;
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.fillStyle = this.color;
ctx.fill();
}
}
class Cross {
constructor(x, y, width, height, color) {
this.x = x,
this.y = y,
this.width = width,
this.height = height,
this.color = color
}
drawCross() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
addEventListener("mousemove", function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
const crossX = new Cross(mouseX, 0, 10, canvas.height, "black");
const crossY = new Cross(0, mouseY, canvas.width, 10, "black");
const lens = new Lens(mouseX, mouseY, 250, "transparent");
crossX.drawCross();
crossY.drawCross();
lens.drawLens();
});
* {
margin: 0;
overflow:hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas></canvas>
<script src="index.js" async defer></script>
</body>
</html>
Clear the entire screen and redraw it per frame:
ctx.clearRect(0, 0, canvas.width, canvas.height);
backgroundSky.drawBackground();
backgroundGrass.drawBackground();
crossX.drawCross();
crossY.drawCross();
lens.drawLens();
Full code:
canvas = document.querySelector("canvas");
ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
class Background {
constructor(x, y, width, height, color) {
this.x = x,
this.y = y,
this.width = width,
this.height = height,
this.color = color
}
drawBackground() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
const backgroundSky = new Background(0, 0, canvas.width, canvas.height, "#89CFF0");
const backgroundGrass = new Background(0, canvas.height/1.2,canvas.width, canvas.height, "green");
class Lens {
constructor(x, y, radius, color) {
this.x = x,
this.y = y,
this.radius = radius,
this.color = color
}
drawLens() {
ctx.lineWidth = 10;
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.fillStyle = this.color;
ctx.fill();
}
}
class Cross {
constructor(x, y, width, height, color) {
this.x = x,
this.y = y,
this.width = width,
this.height = height,
this.color = color
}
drawCross() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
addEventListener("mousemove", function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
const crossX = new Cross(mouseX, 0, 10, canvas.height, "black");
const crossY = new Cross(0, mouseY, canvas.width, 10, "black");
const lens = new Lens(mouseX, mouseY, 250, "transparent");
ctx.clearRect(0, 0, canvas.width, canvas.height);
backgroundSky.drawBackground();
backgroundGrass.drawBackground();
crossX.drawCross();
crossY.drawCross();
lens.drawLens();
});
* {
margin: 0;
overflow:hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas></canvas>
<script src="index.js" async defer></script>
</body>
</html>
You could redraw the background just before drawing the crosshair.
Your mousemove event listener function would become:
addEventListener("mousemove", function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
const crossX = new Cross(mouseX, 0, 10, canvas.height, "black");
const crossY = new Cross(0, mouseY, canvas.width, 10, "black");
const lens = new Lens(mouseX, mouseY, 250, "transparent");
backgroundSky.drawBackground(); // ⚠️
backgroundGrass.drawBackground(); // ⚠️
crossX.drawCross();
crossY.drawCross();
lens.drawLens();
});
canvas = document.querySelector("canvas");
ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
class Background {
constructor(x, y, width, height, color) {
this.x = x,
this.y = y,
this.width = width,
this.height = height,
this.color = color
}
drawBackground() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
const backgroundSky = new Background(0, 0, canvas.width, canvas.height, "#89CFF0");
const backgroundGrass = new Background(0, canvas.height/1.2,canvas.width, canvas.height, "green");
backgroundSky.drawBackground();
backgroundGrass.drawBackground();
class Lens {
constructor(x, y, radius, color) {
this.x = x,
this.y = y,
this.radius = radius,
this.color = color
}
drawLens() {
ctx.lineWidth = 10;
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.fillStyle = this.color;
ctx.fill();
}
}
class Cross {
constructor(x, y, width, height, color) {
this.x = x,
this.y = y,
this.width = width,
this.height = height,
this.color = color
}
drawCross() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
addEventListener("mousemove", function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
const crossX = new Cross(mouseX, 0, 10, canvas.height, "black");
const crossY = new Cross(0, mouseY, canvas.width, 10, "black");
const lens = new Lens(mouseX, mouseY, 250, "transparent");
backgroundSky.drawBackground(); // ⚠️
backgroundGrass.drawBackground(); // ⚠️
crossX.drawCross();
crossY.drawCross();
lens.drawLens();
});
* {
margin: 0;
overflow:hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas></canvas>
<script src="index.js" async defer></script>
</body>
</html>
Related
I am drawing a canvas.
I simplified my code.
There is a transparent circle.
The background is rgba 0,0,0,0.5.
I'd like to add "shadowblur" for the transparent circle. However, it's fail.
Is it possible?
I have another logic:
Create one circle with linear-gradient (rgba 0,0,0,0.5, transparent)
However, it seems no good.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
<style>
.Preloader {
background-color: #7bf;
}
</style>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.fill();
ctx.closePath();
ctx.save();
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
ctx.clip();
ctx.clearRect(0, 0, c.width, c.height);
ctx.shadowBlur = 0;
ctx.closePath();
ctx.restore();
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
</script>
</body>
</html>
If you mean that you want the edges of the clipping-area to be smoother, then you can use compositing to use any bitmap as a mask:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
// fillRect doesn't need beginPath(), and it does fill()
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
// closePath encloses the current subpath
// it doesn't "end" the path declaration
// beginPath does that
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
// we use compositing to create our hole, with shadow:
ctx.globalCompositeOperation = "destination-out";
ctx.shadowBlur = 30;
ctx.shadowColor = "black";
ctx.fillStyle = 'black';
ctx.fill();
// restore
ctx.shadowBlur = 0;
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
This would also work with CanvasGradient instead of shadowBlur:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = ctx.createRadialGradient(this.position.x, this.position.y, this.r, this.position.x, this.position.y, 0);
ctx.fillStyle.addColorStop(0, "transparent");
ctx.fillStyle.addColorStop(.25, "black");
ctx.fillRect(0, 0, c.width, c.height);
// restore
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
Or even in Chrome and Firefox by using CSS blur filters:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
// we use compositing to create our hole, with shadow:
ctx.globalCompositeOperation = "destination-out";
ctx.filter = "blur(15px)";
ctx.fill();
// restore
ctx.filter = "none";
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x++
this.position.y++
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div class="Preloader">
<canvas id="myCanvas"></canvas>
</div>
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>
//Selectors
canvas = document.querySelector('.canvas');
canvas.setAttribute("tabindex", 0);
canvas.focus();
pointerImg = document.querySelector('.pointer');
//Variables
const pi = Math.PI;
const c = canvas.getContext('2d');
var grid = {
'x':60,
'y':20,
'size':20,
}
var pointerValues = {
37: {'x':-1, 'y':0},
38: {'x':0, 'y':-1},
39: {'x':1, 'y':0},
40: {'x':0, 'y':1},
}
//Event Listeners
window.addEventListener('resize', function() {
//init();
})
var cells = [];
for(let i=0;i<grid.x;i++) {
cells[i] = new Array(grid.y);
}
//Functions
function init() {
resizeGrid();
initCells();
}
init();
function update(){
requestAnimationFrame(update)
}
update();
function Cell(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = 'white';
this.update = function() {
this.draw();
}
this.draw = function() {
c.beginPath();
c.rect(this.x*this.size, this.y*this.size, this.size, this.size);
c.strokeStyle = 'black';
c.stroke();
c.fillStyle=this.color; c.fill();
c.closePath();
}
this.resetCell = function() {
c.clearRect(this.x, this.y, this.size, this.size);
this.update();
}
}
function resizeGrid() {
let windowX = window.innerWidth;
windowX -= windowX*0.1;
grid.size = windowX/grid.x;
let canvasX = windowX, canvasY = grid.y * grid.size;
canvas.width = canvasX;
canvas.height = canvasY;
}
function initCells() {
cells = [];
for(let i=0;i<grid.x;i++) {
cells[i] = new Array(grid.y);
}
for(let i=0;i<grid.x;i++) {
for(let j=0;j<grid.y;j++) {
cells[i][j] = new Cell(i, j, grid.size);
cells[i][j].update();
}
}
}
<html>
<head>
<link rel="stylesheet" href="assets/css/main.css">
<div style="display:none;">
<img class='pointer' src="assets/img/pointer.svg">
</div>
<div class='nav'>
</div>
</head>
<body>
<div class="content">
<canvas class='canvas'></canvas>
</div>
<script src='assets/js/canvas.js'></script>
</body>
</html>
function Cell(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = 'white';
this.update = function () {
this.draw();
}
this.draw = function () {
c.beginPath();
c.rect(this.x * this.size, this.y * this.size, this.size, this.size);
c.strokeStyle = 'black';
c.stroke();
c.fillStyle = this.color;
c.fill();
c.closePath();
}
this.resetCell = function () {
c.clearRect(this.x, this.y, this.size, this.size);
this.update();
}
This is my code for a single cell in a grid. After I draw it a single time, when I call resetCell(), it draws the cell just a little bit bigger.
In this picture, I call Update for the very first cell and it becomes a tiny bit bigger than the rest.
I've tried pretty much everything but nothing seems to work.
Also can someone recommend better way to draw and control grid.
I need it to demonstrate BFS algorithm.
You were tricked by the thickness of the border
The border has a thickness, which is easy to forget. If you draw a box which is X wide, its left and right border are in addition to the width of X.
So if you do NOT fill the interior, you get this nice appearance (left), but if you FILL, you get this ugly appearance (right).
When you draw a grid of these squares, each one covers over the right-hand and bottom sides of previous squares, so that it is not obvious what is happening.
Unless you redraw one that is not the last of the list, as I have done here (bottom-middle). Then it becomes obvious that something is wrong.
Here is the code to reproduce the above figures, and below I recommend a solution.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// With NO fill, it looks fine
ctx.beginPath();
ctx.rect(40, 40, 40, 40);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.rect(80, 80, 40, 40);
ctx.stroke();
ctx.closePath();
// With white fill, the inner half of each box gets covered up by the white fill.
ctx.beginPath();
ctx.rect(140, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(180, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
// Make Grid. This part looks OK initially.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(240, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(240, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(280, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(280, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(320, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(320, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
// Redraw one: this will look messed up.
ctx.beginPath();
ctx.rect(280, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="400" height="150" ></canvas>
</body>
</html>
Solution 1. Don't fill the interiors
This is the neatest solution, if you can get away with it, and it works regardless of any (non-zero) border thickness.
Solution 2. Shrink the width to allow for border thickness
This is complicated because you need to manually set the border thickness, and realise that it is in addition to the numerical values you specify for the rectangle's size.
Look at this messy business at CSS-tricks, even when they are trying to make borders interesting! https://css-tricks.com/almanac/properties/b/border/
I have two circles that same color, and I am trying to figure out find a way to have different color circles on the canvas. I am wondering if I can use the CanvasRenderingContext2D.save() and CanvasRenderingContext2D.restore()
method to create a different color. If the methods work, how can I attempt this?
Edit: I was able to color the circles in different colors after I tried
beginPath, 2. draw 3. closePath 4. set color 5. stroke/fill. Do that for both circles:
that Chris G suggested.
enter code here
var canvas = document.getElementById("canvasGame");
var ctx = canvas.getContext("2d");
var model = {
circle1: { x: 300, y: 200},
circle2: { x: 200, y: 200 }
};
var radius = 50;
function view(ctx, model) {
function circle(c) {
ctx.beginPath();
ctx.save();
ctx.arc(c.x, c.y, radius, 0, 2 * Math.PI, true);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.arc(c.x, c.y, radius, 0, 2 * Math.PI, true);
ctx.fill();
ctx.stroke();
}
// clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
circle(model.circle1);
circle(model.circle2);
}
function redraw() {
view(ctx, model);
}
redraw();
function getCircleForPosition(x, y) {
function intersect(a, b) {
var d2 = Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2);
r2 = Math.pow(radius, 2);
return d2 < r2;
}
return [model.circle1, model.circle2].find(circle => intersect(circle, { x, y }));
}
canvas.addEventListener('mousedown', function(e) {
model.dragging = getCircleForPosition(e.pageX, e.pageY);
}, 0);
canvas.addEventListener('mouseup', function() {
model.dragging = undefined;
}, 0);
canvas.addEventListener('mousemove', function(e) {
if (model.dragging) {
model.dragging.x = e.pageX;
model.dragging.y = e.pageY;
redraw();
}
}, 0);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Canvas</title>
</head>
<body>
<canvas id="canvasGame" style='background-color:#EEE;' width='600px' height='500px'>
</canvas>
<div>
<script src="JS/object.js"></script>
</body>
</html>
i have following code with newest craftyjs:
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin:0;
}
</style>
<script type="text/javascript" src="crafty.js"></script>
<script>
Crafty.c("Planet", {
Planet: function(radius, map) {
this.radius = radius;
this.map = map;
return this;
},
draw: function() {
var ctx = Crafty.canvas.context;
var x = 100;
var y = 100;
var offsetX = 0;
var map = this.map;
ctx.save();
ctx.beginPath();
ctx.arc(x, y, this.radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.clip();
var scale = (this.radius * 2) / map.height;
ctx.drawImage(map, 0, 0, map.width, map.height, x - this.radius - offsetX * scale, y - this.radius, map.width * scale, map.height * scale);
ctx.beginPath();
ctx.arc(x, y, this.radius * 1.04, Math.PI * 0.70, Math.PI * 1.30, false);
ctx.shadowColor = "black";
ctx.shadowBlur = 5;
ctx.shadowOffsetX = 5;
ctx.stroke();
ctx.beginPath();
ctx.arc(x, y, this.radius * 1.04, -Math.PI * 0.30, Math.PI * 0.30, false);
ctx.shadowColor = "black";
ctx.shadowBlur = 5;
ctx.shadowOffsetX = -5;
ctx.stroke();
ctx.restore();
console.log('drawing');
}
});
Game = {
// Initialize and start our game
start: function() {
// Start crafty and set a background color so that we can see it's working
Crafty.init(500,500);
Crafty.scene('Game', function() {
Crafty.load(["1.jpg", "ship.png"],
function() {
Crafty.sprite("ship.png", {player_spr:[0,0, 48,48]});
Crafty.background("url('space.jpg')");
Crafty.e("2D, Canvas, Planet")
.Planet(40, Crafty.asset('1.jpg'));
var b2d = Crafty.e("2D, Canvas, player_spr, Actor, Fourway")
.multiway({W: -90, S: 90, D: 0, A: 180})
.attr({z: 4});
Crafty.viewport.clampToEntities = false;
Crafty.viewport.follow(b2d,0,0);
});
});
Crafty.scene('Game');
}
}
window.onload = Game.start;
</script>
</head>
<body>
</body>
</html>
Textures is:
File: 1.jpg
File: ship.png
The result canvas rendered image:
This is a strange bug! What i can to do with it?
Crafty sprite conflict with custom drawings... (it shows sprite transparency)
CraftyJS Github version fix this issue!
Just compile that with grunt.
Thank you for your answers!