Canvas responsive text - javascript

I'm attempting to make a responsive canvas game(using some code found here to keep width height 100%). In order to get the text responsive I'm using VW for the size. The problem is that even though I am calling the draw function on a resize, JavaScript still seems to be taking the VW dimension from the original size.(Although reloading the page does correctly size it).
<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">
<title>Game</title>
<style>
html body{
margin:0;
padding:0;
border:0;
}
#canvas{
display:block;
background-color: rgb(102,0,102);
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//change canvas size
function canvasSize(){
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
canvas.width = window.innerWidth * window.devicePixelRatio;
canvas.height = window.innerHeight * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
}
//draw function
function mainDraw(){
//changing coordinate x,y to centre of canvas
ctx.translate(canvas.width/2,canvas.height/2);
//drawing text;
ctx.font = "2vw Arial";
ctx.textAlign="center";
ctx.fillText("RoundCloud Christmas adventure",0,0);
// draw circle
ctx.beginPath();
ctx.arc(0,0,canvas.width / 100,0,Math.PI*2);
ctx.closePath();
ctx.fill();
}
window.onload = function(){
canvasSize();
mainDraw();
window.addEventListener('resize', canvasSize);
window.addEventListener('resize', mainDraw);
}
</script>
</body>
</html>

Canvas doesn't support css vw unit.
SO, you should use ...
ctx.font = 2 * window.innerWidth + "px Arial";
instead of ...
ctx.font = "2vw Arial";
Here is the working demo on jsFiddle

Related

Connect two HTML elements with smooth edges

I want to draw a figure like this.
I have used the Canvas to draw the line but failed to draw custom lines.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Line Joining</title>
</head>
<body>
<canvas id="DemoCanvas" width="400" height="400"></canvas>
<script>
var canvas = document.getElementById('DemoCanvas');
if (canvas.getContext)
{
var ctx = canvas.getContext("2d");
var lStart = 50;
var lEnd = 200;
var yStart = 20;
ctx.beginPath();
ctx.lineWidth = 25;
// Use a round corner.
ctx.beginPath();
ctx.lineJoin = "round";
ctx.moveTo(50, 140);
ctx.lineTo(150, 140);
ctx.lineTo(150, 260);
ctx.stroke();
}
</script>
</body>
</html>
I have also tried jQuery draggable and achieved results as figure below.
Kindly suggest me how these type of figures can be drawn using HTML and jQuery/JavaScript

How to make a line follow mouse event arctanget with class javascript

Hi every one I'm trying to make a line follow the mouse move event. I can do this with the ctx.save and restore but i don't know how to do if i want use class and draw other object. In fact whit using save and restore It Work but if i want to have the same result whit class i dont know how to do many thanks
window.onload = function() {
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight,
arrowX = width / 2,
arrowY = height / 2,
dx, dy,
angle = 0,
a = 0;
render();
function render() {
arrowX = width / 2 + Math.cos(a) * height * .4;
arrowY = height / 2 + Math.sin(a) * height * .4;
context.clearRect(0, 0, width, height);
context.save();
context.translate(arrowX, arrowY);
context.rotate(angle);
context.beginPath();
context.moveTo(20, 0);
context.lineTo(-20, 0);
context.moveTo(20, 0);
context.lineTo(10, -10);
context.moveTo(20, 0);
context.lineTo(10, 10);
context.stroke();
context.restore();
requestAnimationFrame(render);
}
document.body.addEventListener("mousemove", function(event) {
dx = event.clientX - arrowX;
dy = event.clientY - arrowY;
angle = Math.atan2(dy, dx);
});
};
<!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 style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>
If i want use class i start like thaïs on the following code
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;
var arrowX = width / 2;
var arrowY = height -20;
var dx;
var dy;
var angle = 0;
class Player{
constructor(x,y,radius,color)
{
this.x=x;
this.y=y;
this.radius=radius;
this.color=color;
}
draw(){
c.beginPath();
c.arc(this.x,this.y,this.radius, 0, Math.PI *2,false );
c.fillStyle=this.color;
c.fill();
}
}
class Shooter{
constructor(x,y,xEnd,yEnd,color){
this.x=x;
this.y=y;
this.xEnd=xEnd;
this.yEnd=yEnd;
this.color=color;
}
draw(){
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.xEnd, this.yEnd);
c.strokeStyle=this.color;
c.stroke();
}
}
// const player= new Player(arrowX,arrowY,20,'white');
const shooter= new Shooter(arrowX,500,arrowX,arrowY,'white');
let animationId;
function animate(){
animationId=requestAnimationFrame(animate)
c.fillStyle='rgba(0, 0, 0, 0.5)';
c.fillRect(0,0,canvas.width,canvas.height);
//player.draw();
shooter.draw();
}
requestAnimationFrame(animate);
<!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 style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>
I can offer two methods for this. The first is to simply have the end of the vector the same coordinates as the mouse position. This will change the magnitude of the vector of course.
This method does not rotate or translate the context.
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = (canvas.width = window.innerWidth);
var height = (canvas.height = window.innerHeight);
let canvasBounds = canvas.getBoundingClientRect()
let mouse = {x: 0, y: 0}
class Shooter {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.xEnd = mouse.x;
this.yEnd = mouse.y;
this.color = color;
}
draw() {
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.xEnd, this.yEnd);
c.strokeStyle = this.color;
c.stroke();
}
update() {
this.xEnd = mouse.x;
this.yEnd = mouse.y;
}
}
const shooter = new Shooter(width/2, height/2, "white");
canvas.addEventListener("mousemove", e => {
mouse.x = e.x - canvasBounds.x;
mouse.y = e.y - canvasBounds.y;
});
function animate() {
animationId = requestAnimationFrame(animate);
c.fillStyle = "rgba(0, 0, 0, 0.5)";
c.fillRect(0, 0, canvas.width, canvas.height);
//player.draw();
shooter.draw();
shooter.update();
}
requestAnimationFrame(animate);
<!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 style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>
The second method draws the start point at (0, 0) but then you can use translate to position it where ever you want. This also rotates the context but allows you to keeps the magnitude the same.
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = (canvas.width = window.innerWidth);
var height = (canvas.height = window.innerHeight);
let canvasBounds = canvas.getBoundingClientRect()
let mouse = {x: 0, y: 0}
class Shooter {
constructor(x, y, color) {
this.x = 0;
this.y = 0;
this.xEnd = this.x + 50;
this.yEnd = this.y;
this.translate = {x: x, y: y}
this.color = color;
this.angle = 0;
}
draw() {
this.angle = Math.atan2(mouse.y - this.translate.y, mouse.x - this.translate.x)
c.save();
c.translate(this.translate.x, this.translate.y);
c.rotate(this.angle);
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.xEnd, this.yEnd);
c.strokeStyle = this.color;
c.stroke();
c.restore()
}
update() {
}
}
const shooter = new Shooter(width/2, height/2, "white");
canvas.addEventListener("mousemove", e => {
mouse.x = e.x - canvasBounds.x;
mouse.y = e.y - canvasBounds.y;
});
function animate() {
requestAnimationFrame(animate);
c.fillStyle = "rgba(0, 0, 0, 0.5)";
c.fillRect(0, 0, canvas.width, canvas.height);
//player.draw();
shooter.draw();
}
requestAnimationFrame(animate);
<!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 style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>

How to draw on the canvas?

I have a blue circle which is revolving around the red circle and both are moving to right combined.
I need to draw on the canvas on the path of the red circle moves, but I don't want the blue circle to draw.
at present the circle is moving along right but I want the circle to move in the direction of blue circle at the point of time of mouse press.
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100;
let positionY = 100;
let X = 50;
let Y = 50;
let angle = 0;
function circle(){
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(X, Y, 20, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}
function direction(){
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}
function animate(){
ctx.clearRect(0,0, canvas.width, canvas.height);
circle();
direction();
positionX = 35 * Math.sin(angle);
positionY = 35 * Math.cos(angle);
X+=1;
angle += 0.1;
canvas.addEventListener('onclick', function(){
});
requestAnimationFrame(animate);
}
animate();
#canvas1{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
}
<!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>Canvas basics</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<script src="script.js"></script>
</body>
</html>

How do you draw a line from the last position of the mouse to the present position of the mouse?

So, I'm creating some drawing maker thing, but when I move the mouse it doesn't draw circles in a line. I don't know how to say it well, but I want it to draw a line from point A (last position of mouse) to point B (present position of mouse).
Start drawing here and you will understand:
const c = document.getElementById('c')
const ctx = c.getContext('2d')
c.height = window.innerHeight
c.width = window.innerWidth
function pen(e, colorHEX) {
let mouseX = e.clientX
let mouseY = e.clientY
ctx.fillStyle = colorHEX
ctx.beginPath()
ctx.arc(mouseX, mouseY, 2, 0, Math.PI * 2)
ctx.fill()
ctx.closePath()
}
$('body').mousedown(function(eObj){
$('body').mousemove(function(e) {
pen(e, '#000000')
})
})
$('body').mouseup(function(eObj) {
$('body').unbind('mousemove')
})
body {
margin: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<canvas id="c"></canvas>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="script.js"></script>
</body>
</html>
I think you're trying to draw a contiguous line (you don't need to do that by painting circles). You'll need to store the last mouse position, and then draw a line from there to the current mouse position.
const c = document.getElementById('c')
const ctx = c.getContext('2d')
c.height = window.innerHeight
c.width = window.innerWidth
let lastPos // state variable
function pen(e, colorHEX) {
const pos = {x:e.clientX, y: e.clientY}
lastPos = (lastPos || pos) // Default to current pos
ctx.beginPath()
ctx.strokeStyle = colorHEX
ctx.lineWidth = 1
ctx.moveTo(lastPos.x, lastPos.y)
ctx.lineTo(pos.x, pos.y)
ctx.stroke()
ctx.closePath()
// Update the state variable
lastPos = pos
}
$('body').mousedown(function(eObj){
$('body').mousemove(function(e) {
pen(e, '#000000')
})
})
$('body').mouseup(function(eObj) {
$('body').unbind('mousemove')
lastPos = undefined
})
body {
margin: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<canvas id="c"></canvas>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="script.js"></script>
</body>
</html>
You can use the lineTo method
To make it move while you are dragging the line will take an extra script that includes angles and math.
const c = document.getElementById('c')
const ctx = c.getContext('2d')
c.height = window.innerHeight
c.width = window.innerWidth
let startX;
let startY;
function pen(e, colorHEX) {
let endX = e.clientX
let endY = e.clientY
ctx.fillStyle = colorHEX
ctx.beginPath()
ctx.moveTo(startX, startY)
ctx.lineTo(endX, endY)
ctx.fill()
ctx.closePath()
ctx.stroke()
}
$('body').mousedown(function(e){
startX = e.clientX;
startY = e.clientY;
})
$('body').mouseup(function(e) {
pen(e, "#000000");
})
body {
margin: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<canvas id="c"></canvas>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Drawing with mouse
You have two options.
Draw a line segment from A to B setting the line width to match the circles diameter and the line cap to round.
Interpolate the points from A to B drawing a circle (or any shape) at points 1px apart.
I said two but there are a zillion ways to do this type of thing, but that would put this answer in the TLDR category.
Which method you use will depend on the finer details of your needs. The two example below drawing using the most basic solid line look identical.
What I think you may be having a problem with is because you are turning the event listeners on and off, the last mouse position you have is the last mouse up.
I have added two examples. One for each of the drawing options, and the top one uses an always on mouse listeners and a second turns on and of the mouse listeners as needed.
Examples
The mouse has its state put into an object called mouse.
Each time the mouse changes position the last position is put into mouse.lastX, mouse.lastY.
If the mouse event.type is mousedown the mouse.button is set to true and to false if mouseup
Mouse up and down are also used to turn on and off things like cursor, add and remove events (second example)
At the bottom of the listener it checks if the mouse is down (mouse.button is true) and draws a line from the last position to the current position.
Using line segments
Draws by using 2D API's stroke function.
Use always on mouse listeners.
const ctx = c.getContext('2d');
const BORDER = 1; // I added a 1px border to canvas.
c.height = innerHeight - BORDER * 2;
c.width = innerWidth - BORDER * 2;
const mouse = {x: 0, y: 0, lastX: 0, lastY: 0, button: false};
function drawLine(xA, yA, xB, yB, col, width) {
ctx.strokeStyle = col;
ctx.lineCap = "round";
ctx.lineWidth = width;
ctx.beginPath()
ctx.lineTo(xA, yA);
ctx.lineTo(xB, yB);
ctx.stroke();
}
function mouseEvent(e) {
if (e.type === "mousedown") {
mouse.button = true;
c.classList.add("hideMouse");
} else if (e.type === "mouseup") {
mouse.button = false;
c.classList.remove("hideMouse");
}
mouse.lastX = mouse.x;
mouse.lastY = mouse.y;
mouse.x = e.clientX - BORDER;
mouse.y = e.clientY - BORDER;
if (mouse.button) {
drawLine(mouse.lastX, mouse.lastY, mouse.x, mouse.y, "#000", 4);
}
}
addEventListener("mousedown", mouseEvent);
addEventListener("mouseup", mouseEvent);
addEventListener("mousemove", mouseEvent);
body {
margin: 0;
overflow: hidden;
font-family: arial;
}
canvas {
border: 1px solid black;
cursor: crosshair;
}
.hideMouse {
cursor: none;
}
div {
background: #FFF8;
position: absolute;
top: 4px;
left: 4px;
}
<canvas id="c"></canvas>
<div>Click and drag mouse to draw</div>
Interpolate line
Replaces drawLine function body with interpolation algorithum.
Adds mouse listeners mousemove and mouseup, on mousedown. Note that the up listener has the option {once:true} when added so does not need to be manually removed.
const ctx = c.getContext('2d');
const BORDER = 1; // I added a 1px border to canvas.
c.height = innerHeight - BORDER * 2;
c.width = innerWidth - BORDER * 2;
const mouse = {x: 0, y: 0, lastX: 0, lastY: 0, button: false};
function drawLine(xA, yA, xB, yB, col, width) {
var i = 0;
const dx = xB - xA;
const dy = yB - yA;
const length = Math.hypot(dx, dy);
const stepX = length > 0 ? dx / length : 0;
const stepY = length > 0 ? dy / length : 0;
ctx.beginPath();
ctx.fillStyle = col;
while (i <= length) {
ctx.moveTo(xA + width / 2, yA);
ctx.arc(xA, yA, width / 2, 0, Math.PI * 2);
xA += stepX;
yA += stepY;
i ++;
}
ctx.fill();
}
function mouseEvent(e) {
if (e.type === "mousedown") {
mouse.button = true;
c.classList.add("hideMouse");
addEventListener("mouseup", mouseEvent, {once: true});
addEventListener("mousemove", mouseEvent);
// Set mouse pos so last pos is not where the last mouse up was
mouse.x = e.clientX - BORDER;
mouse.y = e.clientY - BORDER;
} else if (e.type === "mouseup") {
mouse.button = false;
c.classList.remove("hideMouse");
removeEventListener("mousemove", mouseEvent);
}
mouse.lastX = mouse.x;
mouse.lastY = mouse.y;
mouse.x = e.clientX - BORDER;
mouse.y = e.clientY - BORDER;
if (mouse.button) {
drawLine(mouse.lastX, mouse.lastY, mouse.x, mouse.y, "#000", 4);
}
}
addEventListener("mousedown", mouseEvent);
body {
margin: 0;
overflow: hidden;
font-family: arial;
}
canvas {
border: 1px solid black;
cursor: crosshair;
}
.hideMouse {
cursor: none;
}
div {
background: #FFF8;
position: absolute;
top: 4px;
left: 4px;
}
<canvas id="c"></canvas>
<div>Click and drag mouse to draw</div>
Side note...
jQuery is dead
BTW jQuery is not needed, it became irrelevant about 5 years ago.
Using it puts you many years behind modern front end development.
In the past 5 years the demand for jQuery experience coders has dropped a significant amount. A trend that will continue as jQuery has painted its self into a corner from which the only way out is via re branding and re targeting its purpose.
Every time you use jQuery you are investing your most valuable asset, time. Time spent learning and gaining experience. Be wise and direct that time learning what is applicable and growing in the future, and not into what started dying over a decade ago.
For more details Should you use or learn jQuery in 2020?

Canvas Fill Page Width and Height

http://jsbin.com/oMUtePo/1/edit
I've been having a pain trying to get canvas to fill the whole page.
I tried using...
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
It filled the width, but not the height, and the drawing board was drawing 1px lines, which is not what I want.
When using 100% for width and height in CSS the width is scaled, and the height is cut, when drawing it looks as if a raster image was scaled significantly larger in ms paint and there's a large offset on onmousedown drawing which is obviously not what I want.
Any help would be greatly appreciated.
Full Code:
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>HTML5 Canvas Drawing Board</title>
<style>
* {
margin: 0;
padding: 0;
}
body, html {
height: 100%;
}
#myCanvas {
cursor: crosshair;
position: absolute;
width: 100%;
height: 100%;
}
</style>
<script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js?ver=1.4.2"></script>
<script type="text/javascript">
window.onload = function() {
var myCanvas = document.getElementById("myCanvas");
var curColor = $('#selectColor option:selected').val();
var ctx = myCanvas.getContext("2d");
ctx.fillStyle="#000";
ctx.fillRect(0,0,500,500);
if(myCanvas){
var isDown = false;
var canvasX, canvasY;
ctx.lineWidth = 5;
$(myCanvas)
.mousedown(function(e){
isDown = true;
ctx.beginPath();
canvasX = e.pageX - myCanvas.offsetLeft;
canvasY = e.pageY - myCanvas.offsetTop;
ctx.moveTo(canvasX, canvasY);
})
.mousemove(function(e){
if(isDown !== false) {
canvasX = e.pageX - myCanvas.offsetLeft;
canvasY = e.pageY - myCanvas.offsetTop;
ctx.lineTo(canvasX, canvasY);
ctx.strokeStyle = "white";
ctx.stroke();
}
})
.mouseup(function(e){
isDown = false;
ctx.closePath();
});
}
};
</script>
</head>
<body>
<canvas id="myCanvas">
Sorry, your browser does not support HTML5 canvas technology.
</canvas>
</body>
</html>
You have to set the absolute size in pixels on the canvas element and not with CSS as you do in the demo, so first remove the following lines from the CSS rule:
#myCanvas {
cursor: crosshair;
position: absolute;
/*width: 100%; Remove these */
/*height: 100%;*/
}
Then add this to your code - you need to use clientWidth/Height of the window object.
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
var ctx = myCanvas.getContext("2d");
ctx.fillStyle="#000";
ctx.fillRect(0,0, myCanvas.width, myCanvas.height);
Your modified JSBIN.

Categories

Resources