I want change the middle point of canvas quadratic curve which is far away from the line while dragging middle point. On dragging i want to stick with the link as now its increasing the distance of the middle point.http://jsfiddle.net/ashishbhatt/yqgak7eq/1/
http://s25.postimg.org/hegxhlgrj/123123.jpg
Please check the above reference image for the same.
Code :
(function() {
var canvas, ctx, code, point, style, drag = null, dPoint;
// define initial points
function Init(quadratic) {
point = {
p1: { x:0, y:100 },
p2: { x:200, y:100 }
};
if (quadratic) {
point.cp1 = { x: 100, y: 50 };
}
else {
point.cp1 = { x: 100, y: 100 };
point.cp2 = { x: 100, y: 100 };
}
// default styles
style = {
curve: { width: 2, color: "#333" },
cpline: { width: 1, color: "#C00" },
point: { radius: 6, width: 1, color: "#900", fill: "rgba(200,200,200,0.5)", arc1: 0, arc2: 2 * Math.PI }
}
// line style defaults
ctx.lineCap = "round";
ctx.lineJoin = "round";
// event handlers
canvas.onmousedown = DragStart;
canvas.onmousemove = Dragging;
canvas.onmouseup = canvas.onmouseout = DragEnd;
DrawCanvas();
}
// draw canvas
function DrawCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// control lines
ctx.lineWidth = style.cpline.width;
ctx.strokeStyle = style.cpline.color;
ctx.beginPath();
//ctx.moveTo(point.p1.x, point.p1.y);
//ctx.lineTo(point.cp1.x, point.cp1.y);
if (point.cp2) {
//ctx.moveTo(point.p2.x, point.p2.y);
//ctx.lineTo(point.cp2.x, point.cp2.y);
}
else {
//ctx.lineTo(point.p2.x, point.p2.y);
}
ctx.stroke();
// curve
ctx.lineWidth = style.curve.width;
ctx.strokeStyle = style.curve.color;
ctx.beginPath();
ctx.moveTo(point.p1.x, point.p1.y);
if (point.cp2) {
//ctx.bezierCurveTo(point.cp1.x, point.cp1.y, point.cp2.x, point.cp2.y, point.p2.x, point.p2.y);
}
else {
ctx.quadraticCurveTo(point.cp1.x, point.cp1.y, point.p2.x, point.p2.y);
}
ctx.stroke();
// control points
for (var p in point) {
ctx.lineWidth = style.point.width;
ctx.strokeStyle = style.point.color;
ctx.fillStyle = style.point.fill;
ctx.beginPath();
ctx.arc(point[p].x, point[p].y, style.point.radius, style.point.arc1, style.point.arc2, true);
ctx.fill();
ctx.stroke();
}
ShowCode();
}
// show canvas code
function ShowCode() {
var myCounter = 0;
if(point.cp1.y < 100){
myCounter = point.cp1.y-100;
}else if(point.cp1.y > 100){
myCounter = point.cp1.y-100;
}
if (code) {
code.firstChild.nodeValue = myCounter
}
}
// start dragging
function DragStart(e) {
e = MousePos(e);
var dx, dy;
for (var p in point) {
//console.log(p)
//dx = point[p].x - e.x;
if(p == 'cp1'){
dy = point[p].y - e.y;
if ((dy * dy) < style.point.radius * style.point.radius) {
drag = p;
dPoint = e;
canvas.style.cursor = "move";
return;
}
}
}
}
// dragging
function Dragging(e) {
if (drag) {
e = MousePos(e);
//point[drag].x += e.x - dPoint.x;
point[drag].y += e.y - dPoint.y;
dPoint = e;
DrawCanvas();
}
}
// end dragging
function DragEnd(e) {
drag = null;
canvas.style.cursor = "default";
DrawCanvas();
}
// event parser
function MousePos(event) {
event = (event ? event : window.event);
return {
//x: event.pageX - canvas.offsetLeft,
y: event.pageY - canvas.offsetTop
}
}
// start
canvas = document.getElementById("canvasSettings");
code = document.getElementById("code");
if (canvas.getContext) {
ctx = canvas.getContext("2d");
Init(canvas.className == "quadratic");
}
})();
Related
I am trying to code a game about snowboarding but so far, when I try to make trees (green rectangles), they aren't showing up.
Code:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 1000;
canvas.height = 800;
var x = canvas.width / 2,
speed = 0.1,
size = 5,
alive = 1,
keys = [];
function player() {
if (alive === 1) {
if (keys[37] || keys[65]) {
x -= 3;
}
if (keys[39] || keys[68]) {
x += 3;
}
if (x > canvas.width) {
x = canvas.width;
}
if (x < 0) {
x = 0;
}
ctx.beginPath();
ctx.fillStyle = "black"
ctx.arc(x, 100, size, 0, Math.PI * 2);
ctx.fill();
}
}
function tree() {
var treeX = Math.floor(Math.random() * (canvas.width + 1)) + 25;
var treeY;
if (treeY < 1) {
treeY = canvas.height;
} else {
treeY -= speed;
}
ctx.fillStyle = "green";
ctx.fillRect(treeX, treeY, 5, 8);
}
function update() {
requestAnimationFrame(update);
ctx.clearRect(0, 0, canvas.width, canvas.height);
player();
tree();
}
update();
document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
<canvas id="canvas"></canvas>
I tried switching the order of things and using console to see where the trees are but none worked.
For player, you are tracking state outside of the function in some different variables.
For a tree to be able to update, you also have to track its state.
Here's a way you can do that:
Instead of always initializing treeX and treeY fresh in the function, pass values as arguments
After updating the tree state, return its x and y coordinates
Outside of your tree function, keep track of a list of trees.
In update, replace your list of trees with updated trees.
Here's a running example:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 200;
var x = canvas.width / 2,
speed = 1,
size = 5,
alive = 1,
keys = [],
trees = [ tree(), tree(), tree() ];
function player() {
if (alive === 1) {
if (keys[37] || keys[65]) {
x -= 3;
}
if (keys[39] || keys[68]) {
x += 3;
}
if (x > canvas.width) {
x = canvas.width;
}
if (x < 0) {
x = 0;
}
ctx.beginPath();
ctx.fillStyle = "black"
ctx.arc(x, 100, size, 0, Math.PI * 2);
ctx.fill();
}
}
function tree(
treeX = Math.floor(Math.random() * (canvas.width + 1)),
treeY = Math.floor(Math.random() * (canvas.height + 1))
) {
if (treeY < 1) {
treeY = canvas.height;
} else {
treeY -= speed;
}
ctx.fillStyle = "green";
ctx.fillRect(treeX, treeY, 5, 8);
return [ treeX, treeY ];
}
function update() {
requestAnimationFrame(update);
ctx.clearRect(0, 0, canvas.width, canvas.height);
player();
trees = trees.map(([x, y]) => tree(x, y));
}
update();
document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
* { margin: 0; }
canvas { border: 1px solid red; }
<canvas id="canvas"></canvas>
I'm creating a simple paint app in html5 canvas and JavaScript which creates triangles of variable size. I have just figured out how to do this and am now trying to drag and move the triangles that have been created. For this, I'm using a "triangles" array to store all the triangle objects.
When I try to push one object of one triangle into the array, too many objects get created. How do I fix this? I just want one object per triangle.
My code:
HTML:
<body>
<h1>Simple Paint App</h1>
<div id="canvs">
<canvas id="paint-canvas" width="800" height="400"></canvas>
<button id="buttn" >Clear/Reset</button>
</div>
<noscript>This site requires JavaScript to be activated.</noscript>
</body>
JavaScript:
let canvas = document.querySelector("#paint-canvas");
let context = canvas.getContext("2d");
let triangles = []
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX, startY;
let dragOk = false;
let imageData;
function getCoordinates(e){
const X = parseInt(e.clientX - offsetX);
const Y = parseInt(e.clientY - offsetY);
return {x: X, y: Y};
}
function getRandomColor(){
const colors =
["#DFFF00", "#FFBF00", "#FF7F50", "#DE3163", "#9FE2BF", "#40E0D0", "#6495ED", "#CCCCFF"];
return colors[Math.floor(Math.random() * colors.length)];
}
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
canvas.onmousemove = mouseMove;
document.querySelector("#buttn").addEventListener("click", () => resetCanvas());
function mouseDown(e){
dragOk = true;
const start = getCoordinates(e);
startX = start.x;
startY = start.y;
storeImageData();
}
function mouseUp(e){
dragOk = false;
restoreImageData();
let position = getCoordinates(e);
drawTriangle(position);
console.log(triangles);
}
function mouseMove(e){
if (!dragOk) {
return;
}
let position;
restoreImageData()
position = getCoordinates(e);
drawTriangle(position);
}
function storeImageData() {
imageData = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(imageData, 0, 0);
}
function drawTriangle(position) {
let tri = { x:startX, y:startY, points: [{x:0,y:0},{x:0,y:0},{x:0,y:0}], outline: "#000000", fill:"#000000", dragOk: false };
const radius = Math.sqrt(Math.pow((startX - position.x), 2) + Math.pow((startY - position.y), 2));
let i = 0;
let angle = 100;
// 3 because triangle has 3 sides
for (i = 0; i < 3; i++) {
tri.points[i].x = startX + radius * Math.cos(angle);
tri.points[i].y = startY - radius * Math.sin(angle);
angle += (2 * Math.PI) / 3;
}
context.beginPath();
context.moveTo(tri.points[0].x, tri.points[0].y);
for (i = 1; i < 3; i++) {
context.lineTo(tri.points[i].x, tri.points[i].y);
}
context.closePath();
// the outline
context.lineWidth = 5;
tri.outline = "#000000"
context.strokeStyle = tri.outline;
context.stroke();
// the fill color
tri.fill = getRandomColor();
context.fillStyle = tri.fill;
context.fill();
triangles.push(tri)
}
function resetCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
Edit:
I am pushing the newly created triangles in the drawTriangle function.
JSFiddle: Code
The problem is that your drawTriangle function is chained to the onMouseMove event. Of course this event is required to size the triangles but you shouldn't use it to stuff objects inside the triangles array, as this means as long as the mouse is moving, your creating new objects which are pushed into the array.
Better do it like this:
create a global variable tempTriangle
inside the drawTriangle function assign tri to tempTriangle
if the mouse button is released push tempTriangle into the triangles array
Here's an example based on your code:
let canvas = document.querySelector("#paint-canvas");
let context = canvas.getContext("2d");
let triangles = []
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX, startY;
let dragOk = false;
let imageData;
let tempTriangle;
function getCoordinates(e) {
const X = parseInt(e.clientX - offsetX);
const Y = parseInt(e.clientY - offsetY);
return {
x: X,
y: Y
};
}
function getRandomColor() {
const colors = ["#DFFF00", "#FFBF00", "#FF7F50", "#DE3163", "#9FE2BF", "#40E0D0", "#6495ED", "#CCCCFF"];
return colors[Math.floor(Math.random() * colors.length)];
}
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
canvas.onmousemove = mouseMove;
function mouseDown(e) {
dragOk = true;
const start = getCoordinates(e);
startX = start.x;
startY = start.y;
storeImageData();
}
function mouseUp(e) {
dragOk = false;
restoreImageData();
let position = getCoordinates(e);
drawTriangle(position);
triangles.push(tempTriangle)
console.log(triangles, triangles.length);
}
function mouseMove(e) {
if (!dragOk) {
return;
}
let position;
restoreImageData()
position = getCoordinates(e);
drawTriangle(position);
}
function storeImageData() {
imageData = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(imageData, 0, 0);
}
function drawTriangle(position) {
let tri = {
x: startX,
y: startY,
points: [{
x: 0,
y: 0
}, {
x: 0,
y: 0
}, {
x: 0,
y: 0
}],
outline: "#000000",
fill: "#000000",
dragOk: false
};
const radius = Math.sqrt(Math.pow((startX - position.x), 2) + Math.pow((startY - position.y), 2));
let i = 0;
let angle = 100;
// 3 because triangle has 3 sides
for (i = 0; i < 3; i++) {
tri.points[i].x = startX + radius * Math.cos(angle);
tri.points[i].y = startY - radius * Math.sin(angle);
angle += (2 * Math.PI) / 3;
}
context.beginPath();
context.moveTo(tri.points[0].x, tri.points[0].y);
for (i = 1; i < 3; i++) {
context.lineTo(tri.points[i].x, tri.points[i].y);
}
context.closePath();
// the outline
context.lineWidth = 5;
tri.outline = "#000000"
context.strokeStyle = tri.outline;
context.stroke();
// the fill color
tri.fill = getRandomColor();
context.fillStyle = tri.fill;
context.fill();
tempTriangle = tri;
}
function resetCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
#import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
h1 {
display: flex;
justify-content: center;
font-family: 'Roboto', sans-serif;
}
#paint-canvas {
border: 1vh solid black;
}
#canvs {
display: flex;
flex-flow: column;
align-items: center;
}
#buttn {
margin: 5vh 0 0 0;
}
<div id="canvs">
<canvas id="paint-canvas" width="800" height="400"></canvas>
<button id="buttn" onclick="resetCanvas()">Clear/Reset</button>
</div>
This question already has answers here:
How do I rotate a single object on an html 5 canvas?
(8 answers)
Closed 2 years ago.
I want to simulate car rotation and movement in the new direction in a game I am designing.
According to the following answer, within the HTML5 canvas element you cannot rotate individual elements.
The movement itself is happening in this function, I expect the vehicle to move but the entire canvas moves (try pressing left and right). I couldn't figure out how to rotate the car.
Game._rotate = function(dirx, direction) {
this.ctx.translate(200,200);
}
According to this tutorial, I can only rotate the car itself by rotating the canvas. I'd like the rotation and movement to emulate the following: https://oseiskar.github.io/js-car/.
The code itself here: https://plnkr.co/edit/K5X8fMhUlRLhdeki.
You need to render the car relative to ITS position. Also, you can do the rotation inside its RENDER.
The changes below will handle rotation for the car, but you have bigger problems. I would take time and invest in learning how vectors work. The position, speed and acceleration should all be 2D vectors that provide vector math like adding and multiplication.
Also, provide an initial angle to your car so it is initially rendered the right way. It also appears that your acceleration and deceleration are mixed up.
function Car(map, x, y) {
this.map = map;
this.x = x;
this.y = y;
this.angle = 0; // IMPORTANT
this.width = map.tsize;
this.height = map.tsize;
this.image = Loader.getImage('car');
}
Car.speed = 0;
Car.acceleration = 0;
Car.friction = 5;
Car.moveAngle = 0;
Car.maxSpeed = 500;
Car.forward = 'FORWARD';
Car.backward = 'BACKWARD';
Car.left = 'LEFT';
Car.right = 'RIGHT';
// Render relative to car...
Car.prototype.render = function(ctx) {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
ctx.restore();
};
Game.update = function (delta) {
var dirx = 0;
var diry = 0;
if (Keyboard.isDown(Keyboard.LEFT)) {
this._rotate(dirx, Car.left)
}
else if (Keyboard.isDown(Keyboard.RIGHT)) {
this._rotate(dirx, Car.right)
}
else if (Keyboard.isDown(Keyboard.UP)) {
this._rotate(dirx, Car.up)
diry = accelerate(diry, Car.forward);
}
else if (Keyboard.isDown(Keyboard.DOWN)) {
this._rotate(dirx, Car.down)
diry = accelerate(diry, Car.backward);
}
else {
decelerate();
}
this.car.move(delta, dirx, diry);
this.camera.update();
};
Game._rotate = function(dirx, direction) {
let angleInDegrees = 0;
switch (direction) {
case 'UP':
angleInDegrees = 0;
break;
case 'RIGHT':
angleInDegrees = 90;
break;
case 'DOWN':
angleInDegrees = 180;
break;
case 'LEFT':
angleInDegrees = 270;
break;
}
this.car.angle = angleInDegrees * (Math.PI / 180);
}
Game.render = function () {
// draw map background layer
this._drawLayer(0);
this.car.render(this.ctx);
// draw map top layer
this._drawLayer(1);
};
Vectors
Here is an example using vectors.
loadImage('https://i.stack.imgur.com/JY7ai.png')
.then(function(img) {
main(img);
})
function main(img) {
let game = new Game({
canvas: document.querySelector('#viewport')
});
let car = new Car({
img: img,
imgRadiansOffset : -Math.PI / 2,
position: new Victor(game.canvas.width, game.canvas.height).divide(new Victor(2, 2)),
velocity: new Victor(0, -1),
showBorder: true
});
game.addLayer(car);
game.start();
}
class Game {
constructor(options) {
Object.assign(this, Game.defaultOptions, options);
if (this.canvas != null) {
Object.assign(this, {
width: this.canvas.width,
height: this.canvas.height
});
this.addListeners();
}
}
addLayer(layer) {
this.layers.push(layer);
layer.parent = this;
}
start() {
this.id = setInterval(() => {
this.render();
}, 1000 / this.rate); // frames per second
}
render() {
let ctx = this.canvas.getContext('2d');
ctx.clearRect(0, 0, this.width, this.height);
this.layers.forEach(layer => layer.render(ctx));
}
addListeners() {
if (this.canvas != null) {
window.addEventListener('keydown', (e) => {
this.handleKeyDown(e.keyCode);
});
window.addEventListener('keyup', (e) => {
this.handleKeyUp(e.keyCode);
});
}
}
handleKeyDown(keyCode) {
this.layers.forEach(layer => {
layer.update(keyCode !== this.lastKeyCode ? keyCode : null);
});
this.lastKeyCode = keyCode;
}
handleKeyUp(keyCode) {
this.layers.forEach(layer => {
layer.update(this.lastKeyCode); // calls reset...
});
}
}
Game.defaultOptions = {
id: null,
rate: 30,
layers: [],
canvas: null,
width: 0,
height: 0
};
class Car {
constructor(options) {
Object.assign(this, Car.defaultOptions, options);
if (this.img != null) {
Object.assign(this, {
width: this.img.width,
height: this.img.height
});
}
}
render(ctx) {
ctx.save();
ctx.translate(this.position.x, this.position.y);
ctx.rotate(this.velocity.angle() - this.imgRadiansOffset);
ctx.drawImage(this.img, -this.width / 2, -this.height / 2, this.width, this.height);
if (this.showBorder) {
ctx.strokeStyle = '#C00';
ctx.setLineDash([4, 8]);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.rect(-this.width / 2, -this.height / 2, this.width, this.height);
ctx.stroke();
}
ctx.restore();
}
update(keyCode) {
if (keyCode != null) this.changeDirection(keyCode);
this.position.add(this.velocity.add(this.acceleration));
this.detectCollision();
}
detectCollision() {
let xMin = this.width / 2, xMax = this.parent.width - xMin;
let yMin = this.height / 2, yMax = this.parent.height - yMin;
if (this.position.x < xMin) this.position.x = xMin;
if (this.position.x > xMax) this.position.x = xMax;
if (this.position.y < yMin) this.position.y = yMin;
if (this.position.y > yMax) this.position.y = yMax;
}
changeDirection(keyCode) {
switch (keyCode) {
case 37:
this.reset(new Victor(-1, 0)); // LEFT
break;
case 38:
this.reset(new Victor(0, -1)); // UP
break;
case 39:
this.reset(new Victor(1, 0)); // RIGHT
break;
case 40:
this.reset(new Victor(0, 1)); // DOWN
break;
}
}
reset(dirVect) {
this.velocity = new Victor(this.speedFactor, this.speedFactor).multiply(dirVect);
this.acceleration = new Victor(this.accelFactor, this.accelFactor).multiply(dirVect);
}
}
Car.defaultOptions = {
position: new Victor(0, 0),
width: 0,
height: 0,
img: null,
imgRadiansOffset: 0,
velocity: new Victor(0, 0),
acceleration: new Victor(0, 0),
showBorder: false,
speedFactor: 3, // Velocity scalar
accelFactor: 1 // Acceleration scalar
};
function loadImage(url) {
return new Promise(function(resolve, reject) {
var img = new Image;
img.onload = function() {
resolve(this)
};
img.onerror = img.onabort = function() {
reject("Error loading image")
};
img.src = url;
})
}
#viewport {
border: thin solid grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/victor/1.1.0/victor.min.js"></script>
<canvas id="viewport" width="400" height="160"></canvas>
I'm having a canvas on which i have created dynamically some rectangles and when you hover over them i need to show an username that's stored, i tried to do it like this but i didn't got the result that i desired. The rectangles are not html elements so i can't use classes or ids.
This is the code that i tried:
canvas.addEventListener('mouseover', (evt)=>{
mousePos = onMousePos(canvas,evt);
for(let i=0;i<rectArray.length;i++)
if(ctx.isPointInPath(mousePos.x,mousePos.y))
console.log(rectArray[i].username);
});
The onMousePos function checks the that the mouse is inside of an hexagon and i use the same function for mouseup, mousedown and mousemove and it works.
EDIT the onMousePos is this:
function onMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
if (history && timeline) {
return {
x: Math.round(evt.clientX - rect.left) * 1.18,
y: Math.round(evt.clientY - rect.top) * 1.05
};
}
if (timeline && history === false) {
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top) * 1.05
};
}
if (history && timeline === false) {
return {
x: Math.round(evt.clientX - rect.left) * 1.18,
y: Math.round(evt.clientY - rect.top)
};
}
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top)
};
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
// Classes
/*
Constructor function
when called with new, everything attached to the 'this' keyword
becomes a new member of the new object
*/
function ToolTip(text) {
this.text = text;
}
/*
Constructor prototype, a collection
of values & functions that are shared across all instances,
use for constant values and member functions
*/
ToolTip.prototype = {
TEXT_SIZE: 15,
TEXT_FONT: "15px Arial",
TEXT_COLOUR: "#FFFFFFFF",
BOX_BORDER_COLOUR: "#000000FF",
BOX_BACKGROUND_COLOUR: "#990000FF",
render: function(ctx,x,y) {
ctx.fillStyle = this.BOX_BACKGROUND_COLOUR;
ctx.strokeStyle = this.BOX_BORDER_COLOUR;
ctx.font = this.TEXT_FONT;
ctx.beginPath();
ctx.rect(
x,
y - this.TEXT_SIZE,
ctx.measureText(this.text).width,
this.TEXT_SIZE
);
ctx.fill();
ctx.stroke();
ctx.fillStyle = this.TEXT_COLOUR;
ctx.fillText(this.text,x,y - 2);
}
};
function Rectangle(x,y,width,height,name) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.tooltip = new ToolTip(name);
}
Rectangle.prototype = {
BORDER_COLOUR: "#000000FF",
BACKGROUND_COLOR: "#0000AAFF",
contains: function(x,y) {
return x > this.x && x < this.x + this.width
&& y > this.y && y < this.y + this.height;
},
render: function(ctx) {
ctx.strokeStyle = this.BORDER_COLOUR;
ctx.fillStyle = this.BACKGROUND_COLOR;
ctx.beginPath();
ctx.rect(this.x,this.y,this.width,this.height);
ctx.fill();
ctx.stroke();
}
};
// Variables
var canvasWidth = 150;
var canvasHeight = 150;
var canvas = null;
var ctx = null;
var rectangles = null;
// Functions
function onMouseMove(e) {
var bounds = canvas.getBoundingClientRect();
var x = e.clientX - bounds.left;
var y = e.clientY - bounds.top;
draw();
for (var i = 0; i < rectangles.length; ++i) {
var rectangle = rectangles[i];
if (rectangle.contains(x,y)) {
rectangle.tooltip.render(ctx,x,y);
return;
}
}
}
function draw() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
for (var i = 0; i < rectangles.length; ++i) {
rectangles[i].render(ctx);
}
}
// Entry Point
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.onmousemove = onMouseMove;
ctx = canvas.getContext("2d");
rectangles = [
new Rectangle(10,10,25,25,"User 1"),
new Rectangle(45,10,25,25,"User 2"),
new Rectangle(80,10,25,25,"User 3"),
new Rectangle(115,10,25,25,"User 4"),
new Rectangle(10,45,25,25,"User 5"),
new Rectangle(45,45,25,25,"User 6"),
new Rectangle(80,45,25,25,"User 7"),
new Rectangle(115,45,25,25,"User 8"),
new Rectangle(10,80,25,25,"User 9"),
new Rectangle(45,80,25,25,"User 10"),
new Rectangle(80,80,25,25,"User 11"),
new Rectangle(115,80,25,25,"User 12"),
new Rectangle(10,115,25,25,"User 13"),
new Rectangle(45,115,25,25,"User 14"),
new Rectangle(80,115,25,25,"User 15"),
new Rectangle(115,115,25,25,"User 16")
];
draw();
}
}();
</script>
</body>
</html>
This question already has an answer here:
Drawing a rectangle on Canvas
(1 answer)
Closed 5 years ago.
I want to draw a square with a function like following.
How can I modify following function to create a square.
function square() {
var tool = this;
this.started = false;
this.mousedown = function (ev) {
context.beginPath();
context.moveTo(ev._x, ev._y);
tool.started = true;
};
this.mousemove = function (ev) {
if (tool.started && checkboxSquare.checked) {
context.lineTo(ev._x, ev._y);
context.stroke();
}
};
this.mouseup = function (ev) {
if (tool.started && checkboxSquare.checked) {
tool.mousemove(ev);
tool.started = false;
}
};
}
Here is a rework:
var Square;
(function(Square) {
var canvas = document.body.appendChild(document.createElement("canvas"));
canvas.style.border = "1px solid";
canvas.width = 800;
canvas.height = 800;
var context = canvas.getContext("2d");
var drawing = false;
var square = {
x: 0,
y: 0,
w: 0,
h: 0,
color: getColor()
};
var persistentSquares = [];
function getColor() {
return "rgb(" +
Math.round(Math.random() * 255) + ", " +
Math.round(Math.random() * 255) + ", " +
Math.round(Math.random() * 255) + ")";
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
for (var pSquareIndex = 0; pSquareIndex < persistentSquares.length; pSquareIndex++) {
var pSquare = persistentSquares[pSquareIndex];
context.fillStyle = pSquare.color;
context.fillRect(pSquare.x, pSquare.y, pSquare.w - pSquare.x, pSquare.h - pSquare.y);
context.strokeRect(pSquare.x, pSquare.y, pSquare.w - pSquare.x, pSquare.h - pSquare.y);
}
context.strokeRect(square.x, square.y, square.w - square.x, square.h - square.y);
}
canvas.onmousedown = function(evt) {
square.x = evt.offsetX;
square.y = evt.offsetY;
square.w = evt.offsetX;
square.h = evt.offsetY;
drawing = true;
requestAnimationFrame(draw);
};
canvas.onmousemove = function(evt) {
if (drawing) {
square.w = evt.offsetX;
square.h = evt.offsetY;
requestAnimationFrame(draw);
}
};
function leave(evt) {
if (!drawing) {
return;
}
square.w = evt.offsetX;
square.h = evt.offsetY;
drawing = false;
persistentSquares.push(square);
square = {
x: 0,
y: 0,
w: 0,
h: 0,
color: getColor()
};
requestAnimationFrame(draw);
};
canvas.onmouseup = leave;
canvas.onmouseleave = leave;
})(Square || (Square = {}));
It's your lucky day! I was just working on something like this. If you use it for anything, be sure to credit me! ;)
Note that circle and oval are still a Work in Progress.
Link to JSFiddle that will be updated when I update the program: JSFiddle
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var mx=300;
var my=300;
var currentObject = {};
document.onmousemove = function(e){
mx=e.pageX-8;
my=e.pageY-8;
}
document.onmousedown = function(e){
var obj = document.getElementById("objSel").value;
currentObject.type=obj;
if(obj=="Rectangle"||currentObject.type=="Square"){
currentObject.x=e.pageX-8;
currentObject.y=e.pageY-8;
}
}
document.onmouseup = function(e){
mx=e.pageX-8;
my=e.pageY-8;
objects.push(complete(currentObject));
currentObject={};
}
var objects = [];
function render(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.moveTo(mx-5,my);
ctx.lineTo(mx+5,my);
ctx.moveTo(mx,my-5);
ctx.lineTo(mx,my+5);
ctx.strokeStyle="black";
ctx.lineWidth=2;
ctx.stroke();
ctx.closePath();
if(currentObject.type=="Rectangle"){
ctx.beginPath();
ctx.rect(currentObject.x,currentObject.y,mx-currentObject.x,my-currentObject.y);
ctx.stroke();
}
draw(complete(currentObject));
for(var i=0;i<objects.length;i++){
draw(objects[i]);
}
}
setInterval(render,5);
render();
function complete(o){
if(o.type=="Square"){
var sidelength = Math.max(Math.abs(mx-o.x),Math.abs(my-o.y));
var fix = function(input){
if(input==0){
return 1;
} else {
return input;
}
};
o.length=fix(Math.sign(mx-o.x))*sidelength;
o.height=fix(Math.sign(my-o.y))*sidelength;
} else if(o.type=="Rectangle"){
o.length=mx-o.x;
o.height=my-o.y;
}
return o;
}
function draw(o){
if(o.type=="Square"||o.type=="Rectangle"){
ctx.beginPath();
ctx.rect(o.x,o.y,o.length,o.height);
ctx.stroke();
}
}
<canvas id="canvas" style="border:1px solid black;" width="500" height="500">Please use a browser that supports the canvas element and make sure your Javascript is working properly.</canvas>
<br>
<span id="testing"></span>
<select id="objSel">
<option>Square</option>
<option>Rectangle</option>
<option>Circle</option>
<option>Oval</option>
</select>