/** SimpleFullCanvasMouse.js begin **/
// Note set window.onResize (note capital R) to get the debounced resize call
// ie onResize = function(){ // blah blah };
// Note. mouse, canvas, ctx are set for you. Mouse is a simple mouse with
// x,y,w (wheel) alt,shift,ctrl, and buttonRaw as a bit field bits 0,1,2 for buttons left, mid, right
// ie if(mouse.buttonRaw & 1) { //is left button down (othe buttons may be down also
// ie if(mouse.buttonRaw === 1) { //is only left button down
// set debounced resize event function to put new particles on canvas
onResize = function(){ particles.length = 0; };
const pSize = 5; // particle size (radius)
var particles = []; // array of things
const mouseSize = 30; // Size of mouse (radius)
const mouseCol = "red"; // guess what this holds???
const runDist = 300; // How far a particl will move when touched
const moveSpeed = 0.01; // speed to move (will move 1 unit dist so 1 / MoveSpeed == number frames to move)
const edgeDist = 10; // distance particles will stay away from the canvas edge.
const MAX_PARTICLES = 200; // the max number oof you know whats
// ease function return unit value clamped from 0-1 based on the input value clamped 0-1
// most functions take a second argument that is a curve modifier. Usualy the power
const EASE_FUNC = {
linear : function (val) {
val = val < 0 ? 0 : val > 1 ? 1 : val;
return val;
},
easePow : function (val, pow) { // for pow > 1 this is ease out rush in
// for pow > 0 & pow < 1 this is rush out ease in
val = val < 0 ? 0 : val > 1 ? 1 : val;
return Math.pow(val, pow);
},
}
const particleMoveFunction = EASE_FUNC.easePow; // ease function to use
// creates a particle at x,y
function createParticle(x, y) {
var typesC = "#F80,#8F0,#0D0,#00F".split(",");
var curves = [0.2,0.5,1.2,2];
var sizes = [1,1.2,1.6,2.2];
var type = Math.floor(4-Math.sqrt(Math.random() * 16)); // more small fast
return {
x : x,
y : y,
lx : x,
ly : y,
dest : {
x : x,
y : y,
},
from : {
x : x,
y : y,
},
size : pSize * sizes[type],
col : typesC[type] ,
moveTime : 0,
moveSpeed : moveSpeed,
moveCurve : curves[type],
}
}
// Move particles.
// checks for mouse interaction
// checks for edge distance
// moves particles is particle moveTime > 0
function updateAllParticles() {
var i;
for (i = 0; i < particles.length; i++) {
var p = particles[i];
p.lx = p.x;
p.ly = p.y;
if (p.moveTime > 0) {
p.moveTime -= p.moveSpeed;
var pos = particleMoveFunction(1 - p.moveTime, p.moveCurve);
p.x = (p.dest.x - p.from.x) * pos + p.from.x;
p.y = (p.dest.y - p.from.y) * pos + p.from.y;
}
p.x = p.x < p.size + edgeDist ? p.size + edgeDist : (p.x >= canvas.width - p.size - edgeDist ? canvas.width - p.size - edgeDist : p.x);
p.y = p.y < p.size + edgeDist ? p.size + edgeDist : (p.y >= canvas.height - p.size - edgeDist ? canvas.height - p.size - edgeDist : p.y);
var dist = Math.sqrt(Math.pow(mouse.x - p.x, 2) + Math.pow(mouse.y - p.y, 2));
if (dist < mouseSize + p.size) {
var dx = (p.x - mouse.x) / dist;
var dy = (p.y - mouse.y) / dist;
p.x = mouse.x + dx * (mouseSize + p.size); // move to edge of mouse
p.y = mouse.y + dy * (mouseSize + p.size);
// random is to stop them grouping to much
var rd = runDist / 2 + Math.random() * runDist / 2;
p.dest.x = p.x + dx * rd + Math.random() * 5 - 2.5;
p.dest.y = p.y + dy * rd + Math.random() * 5 - 2.5;
p.from.x = p.x;
p.from.y = p.y;
p.moveTime = 1;
}
p.distMoved = Math.sqrt(Math.pow(p.lx - p.x, 2) + Math.pow(p.ly - p.y, 2));
}
}
// draw particles
function drawAllParticles() {
var i;
ctx.lineCap = "round";
for (i = 0; i < particles.length; i++) {
var p = particles[i];
ctx.strokeStyle = p.col;
ctx.lineWidth = p.size * 2;
ctx.beginPath();
ctx.moveTo(p.lx, p.ly);
ctx.lineTo(p.x, p.y);
ctx.stroke();
}
}
// draws the mouse object
function drawMouse() {
ctx.fillStyle = mouseCol;
ctx.beginPath();
ctx.moveTo(mouse.x + mouseSize, mouse.y);
ctx.arc(mouse.x, mouse.y, mouseSize, 0, Math.PI * 2);
ctx.fill();
}
// Main display function
function display() {
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.globalAlpha = 0.33; // fade background
ctx.fillStyle = "white";
ctx.fillRect(0, 0, w, h);
ctx.globalAlpha = 1; // reset alpha
if (particles.length < MAX_PARTICLES) {
particles.push(createParticle(
Math.random() * (canvas.width - pSize * 2) + pSize,
Math.random() * (canvas.height - pSize * 2) + pSize));
}
updateAllParticles();
drawAllParticles();
drawMouse();
}
//==================================================================================================
// Boilerplate code not part of answer
//
//
// The following code is support code that provides me with a standard interface to various forums.
// It provides a mouse interface, a full screen canvas, and some global often used variable
// like canvas, ctx, mouse, w, h (width and height), globalTime
// This code is not intended to be part of the answer unless specified and has been formated to reduce
// display size. It should not be used as an example of how to write a canvas interface.
// By Blindman67
if (typeof onResize === "undefined") {
window["onResize"] = undefined; // create without the JS parser knowing it exists.
// this allows for it to be declared in an outside
// modal.
}
const RESIZE_DEBOUNCE_TIME = 100;
var w, h, cw, ch, canvas, ctx, mouse, createCanvas, resizeCanvas, setGlobals, globalTime = 0, resizeCount = 0;
createCanvas = function () {
var c,
cs;
cs = (c = document.createElement("canvas")).style;
cs.position = "absolute";
cs.top = cs.left = "0px";
cs.zIndex = 1000;
document.body.appendChild(c);
return c;
}
resizeCanvas = function () {
if (canvas === undefined) {
canvas = createCanvas();
}
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx = canvas.getContext("2d");
if (typeof setGlobals === "function") {
setGlobals();
}
if (typeof onResize === "function") {
resizeCount += 1;
setTimeout(debounceResize, RESIZE_DEBOUNCE_TIME);
}
}
function debounceResize() {
resizeCount -= 1;
if (resizeCount <= 0) {
onResize();
}
}
setGlobals = function () {
cw = (w = canvas.width) / 2;
ch = (h = canvas.height) / 2;
mouse.updateBounds();
}
mouse = (function () {
function preventDefault(e) {
e.preventDefault();
}
var mouse = {
x : 0,
y : 0,
w : 0,
alt : false,
shift : false,
ctrl : false,
buttonRaw : 0,
over : false,
bm : [1, 2, 4, 6, 5, 3],
active : false,
bounds : null,
mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",")
};
var m = mouse;
function mouseMove(e) {
var t = e.type;
m.x = e.clientX - m.bounds.left;
m.y = e.clientY - m.bounds.top;
m.alt = e.altKey;
m.shift = e.shiftKey;
m.ctrl = e.ctrlKey;
if (t === "mousedown") {
m.buttonRaw |= m.bm[e.which - 1];
} else if (t === "mouseup") {
m.buttonRaw &= m.bm[e.which + 2];
} else if (t === "mouseout") {
m.buttonRaw = 0;
m.over = false;
} else if (t === "mouseover") {
m.over = true;
} else if (t === "mousewheel") {
m.w = e.wheelDelta;
} else if (t === "DOMMouseScroll") {
m.w = -e.detail;
}
if (m.callbacks) {
m.callbacks.forEach(c => c(e));
}
e.preventDefault();
}
m.updateBounds = function () {
if (m.active) {
m.bounds = m.element.getBoundingClientRect();
}
}
m.addCallback = function (callback) {
if (typeof callback === "function") {
if (m.callbacks === undefined) {
m.callbacks = [callback];
} else {
m.callbacks.push(callback);
}
} else {
throw new TypeError("mouse.addCallback argument must be a function");
}
}
m.start = function (element, blockContextMenu) {
if (m.element !== undefined) {
m.removeMouse();
}
m.element = element === undefined ? document : element;
m.blockContextMenu = blockContextMenu === undefined ? false : blockContextMenu;
m.mouseEvents.forEach(n => {
m.element.addEventListener(n, mouseMove);
});
if (m.blockContextMenu === true) {
m.element.addEventListener("contextmenu", preventDefault, false);
}
m.active = true;
m.updateBounds();
}
m.remove = function () {
if (m.element !== undefined) {
m.mouseEvents.forEach(n => {
m.element.removeEventListener(n, mouseMove);
});
if (m.contextMenuBlocked === true) {
m.element.removeEventListener("contextmenu", preventDefault);
}
m.element = m.callbacks = m.contextMenuBlocked = undefined;
m.active = false;
}
}
return mouse;
})();
resizeCanvas();
mouse.start(canvas, true);
window.addEventListener("resize", resizeCanvas);
function update(timer) { // Main update loop
globalTime = timer;
display(); // call demo code
requestAnimationFrame(update);
}
requestAnimationFrame(update);
/** SimpleFullCanvasMouse.js end **/