Reputation: 331
So, I'm making a relatively trivial HTML5 Canvas drawing web app. Basically, you can select your color, and then draw on a 500x500 canvas. It's going to be themed as a "graffiti" wall, so I am attempting to create a graffiti effect to the drawing, much like the Spray tool in MS Paint of yore.
Feel free to take a look at it here.
In order to facilitate this effect, I'm making use of web workers to callback on mouse events and asynchronously draw to the canvas. The naive implementation I have now is that on any mouse event, 5 pixels are randomly drawn around the coords of the event.
What I would like to do though, is to have those pixels drawn continuously from the mousedown event until the mouseup event, while updating the coords on mousemove events. From my limited knowledge of JavaScript, I imagine that this could involve a setTimeout(), but I'm not sure how to manipulate this to achieve what I want.
DISCLAIMER: This is part of a school project, and as such I am trying to avoid JQuery, Ajax, and other such frameworks; my goal here is to make an as-pure-as-possible JavaScript/HTML5 web app.
Thanks in advance.
Upvotes: 2
Views: 3478
Reputation: 2069
Drawing an SVG in a web worker to pass it to its parent and append the SVG to the DOM is possible.
/**
* Web Worker
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
var workerURL = URL.createObjectURL(new Blob(['(',
function() {
onmessage = function( event ) {
if (event.data === 'generateSVG') {
// Generate the SVG content
const svgContent = '<svg width="200" height="200"><circle cx="100" cy="100" r="50" fill="red" /></svg>';
// Send the SVG content back to the parent page
postMessage(svgContent);
}
};
}.toString(), ')()' ], { type: 'application/javascript' }));
/**
* Main Script
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
// Init Worker
worker = new Worker( workerURL );
// Listen for Worker
worker.addEventListener('message', function(event) {
if(event.data !== undefined) {
console.log( 'Worker Response: ', event.data );
}
}, false);
// Listen for messages from the web worker
worker.onmessage = function (event) {
const svgData = event.data;
// Display the SVG in the HTML page
document.getElementById('svg-container').innerHTML = svgData;
};
// Start the web worker
worker.postMessage('generateSVG');
<html>
<body>
<div id="svg-container"></div>
</body>
</html>
Upvotes: 0
Reputation: 665574
If you want to use a WebWorker (for example for more complex drawing algorithms), I could think of the following setup:
In the worker
Yet I think that a Worker is too much overhead for a simple graffiti tool. Use the simple solution without a Worker like @Esailija demonstrated.
If you had a more complex application which could make good use of Workers, you wouldn't really spawn them onmousedown and terminate them. Instead, you maybe instantiated single Workers for single kinds of tools, and fired start-processing and end-processing events to them.
Upvotes: 2
Reputation: 140244
Using a timer (no worker required):
var mouseX = 0,
mouseY = 0,
mouseDown = false;
function ev_canvas( ev ) {
if (ev.offsetX || ev.offsetX == 0) { //opera
mouseX = ev.offsetX;
mouxeY = ev.offsetY;
} else if (ev.layerX || ev.layerX == 0) { //firefox
var canvasOffset = document.getElementById("graffiti_wall").getBoundingClientRect();
mouseX = ev.layerX - canvasOffset.left;
mouseY = ev.layerY - canvasOffset.top;
}
if ( ev.type == 'mousedown' ) {
mouseDown = true;
}
else if ( ev.type == 'mouseup' ) {
mouseDown = false;
}
}
function draw_spray() {
if( !mouseDown ) {
//Don't do anything since the mouse is not pressed down
return;
}
//Draw something at the last known location
context.strokeRect( mouseX, mouseY, 1, 1 );
}
//Call draw_spray function continuously every 16 milliseconds
window.setInterval( draw_spray, 16 );
Upvotes: 3