infinite-canvas
infinite-canvas copied to clipboard
Problems with Objects stored in array
Hi,
in my project I create filled rectagles with the mouse and store them into an objectArray. If I create a new rec I clear the screen while onmousemove and recreate the objects by looping through my array.
But in combination with your script I have the problem, that each time, when I move the canvas and then draw a new rect, everthing jumps back to it's origninal position. Any idea how to handle that?
thanks in advance Frannk
const canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
setCanvasSize();
// Initialization
var inf_ctx = infiniteCanvas.initialize(ctx);
inf_ctx.updateChunks();
window.addEventListener('resize', () => {
setCanvasSize();
drawUpdate();
})
let color = '#e28743'
ctx.strokeStyle = color;
ctx.lineWidth=1;
// calculate where the canvas is on the window
// (used to help calculate mouseX/mouseY)
var offsetX=canvas.offsetLeft;
var offsetY=canvas.offsetTop;
var scrollX=canvas.scrollLeft;
var scrollY=canvas.scrollTop;
// this flage is true when the user is dragging the mouse
var isDown=false;
// these vars will hold the starting mouse position
var startX;
var startY;
let objectArray = [];
let startDrawing = false;
var width = 0;
var height = 0;
var dx = 0;
var dy = 0;
function setCanvasSize()
{
canvas.width= window.innerWidth;
canvas.height = window.innerHeight;
}
function createNotepaper(x,y,width,height, color) {
this.color = color;
this.startX = x;
this.startY = y;
this.width = width;
this.height = height;
this.draw = () => {
ctx.fillStyle = '#00000020';
ctx.beginPath();
ctx.filter = 'blur(3px)';
ctx.fillRect(this.startX+4,this.startY+4,this.width,this.height);
ctx.filter = 'blur(0px)';
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.fillRect(this.startX,this.startY,this.width,this.height);
// Text
ctx.font = "12px Verdana";
ctx.fillStyle = '#fff';
ctx.textAlign = "left";
ctx.fillText("GovBoard Demo", this.startX+5, this.startY+17, this.width-10);
ctx.save();
}
}
function changeColor(e)
{
color = window.getComputedStyle(e).getPropertyValue('background-color');
ctx.strokeStyle = color;
isDown=false;
startDrawing= false;
}
function handleMouseDown(e){
e.preventDefault();
e.stopPropagation();
// save the starting x/y of the rectangle
startX=parseInt(e.clientX-canvas.offsetLeft);
startY=parseInt(e.clientY-canvas.offsetTop);
// set a flag indicating the drag has begun
isDown=true;
}
function handleMouseUp(e){
e.preventDefault();
e.stopPropagation();
// the drag is over, clear the dragging flag
isDown=false;
if(startDrawing)
{
newPaperNote();
}
inf_ctx.updateChunks();
}
function handleMouseOut(e){
e.preventDefault();
e.stopPropagation();
// the drag is over, clear the dragging flag
isDown=false;
}
function drawUpdate()
{
for(var i=0; i < objectArray.length; i++)
{
objectArray[i].draw();
}
}
function moveTo(x,y)
{
ctx.clearRect(0,0,canvas.width,canvas.height);
dx = x;
dy = y;
inf_ctx.moveBy(x, y);
}
function newPaperNote()
{
const notepaper = new createNotepaper(startX,startY,width,height,color);
ctx.clearRect(0,0,canvas.width,canvas.height);
objectArray.push(notepaper);
drawUpdate();
startDrawing = false;
}
function handleMouseMove(e){
e.preventDefault();
e.stopPropagation();
// if we're not dragging, just return
if(isDown)
{
startDrawing = true;
// get the current mouse position
mouseX=parseInt(e.offsetX);
mouseY=parseInt(e.offsetY);
// calculate the rectangle width/height based
// on starting vs current mouse position
width=mouseX-startX;
height=mouseY-startY;
ctx.clearRect(0,0,canvas.width,canvas.height);
// inf_ctx.updateChunks();
drawUpdate();
ctx.beginPath()
ctx.fillStyle = '#ff0000';
ctx.rect(startX,startY,width,height);
ctx.stroke()
}
if(!isDown && startDrawing)
{
newPaperNote();
}
}
canvas.addEventListener("mousedown",handleMouseDown);
canvas.addEventListener("mouseup",handleMouseUp);
canvas.addEventListener("mousemove",handleMouseMove);
canvas.addEventListener("mouseout", handleMouseOut);
The problem is that you're storing the rectangle co-ordinates and redrawing them every time.
The moveTo
and moveBy
methods handle the drawing for you.
It works like this:
- You draw to your regular canvas
- When you call
inf_ctx.updateChunks()
, this gets synchronised to the infinite canvas behind - You can now call
inf_ctx.moveBy
andinf_ctx.moveTo
to move around the canvas. Whatever was drawn to the canvas originally will be automatically drawn in the new, correct position.
This interaction model only really makes sense for painting-like applications, like an infinitely-expanding whiteboard or MS Paint with an automatically expanding canvas.
Can you tell me a little bit more about your goal? This library might fit, but if it involves more than a little bit of interaction I highly recommend going for something with an interaction-model built-in like paper.js, pixi.js or phaser.js (it's a game engine, but game engines are perfectly fine for interactive canvas applications!) or if you prefer a well-filled low-level toolbox you could use p5.js.
thanks for your quick answer.
I redraw the objects all the time because I need to do that for drawing the rectangles by dragging the mouse. My goal is to build a collaboration board like Miro (Miro.com) or Lucidchart.
I will have a look into the libraries you mentioned and will check if they suit to my idea.
Best Frank