Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dot pattern with html canvas

What I currently have is a lot of html elements, along with jQuery and css to create a dot pattern that has an effect based on mouse movement. It is hard to explain so I made an example. http://jsfiddle.net/sebastianscholten/u6ebt390/

var mX, mY, distance;

function theDistance(elem, mouseX, mouseY) {
    return Math.floor(Math.sqrt(Math.pow(mouseX - (elem.offset().left+(elem.width()/2)), 2) + Math.pow(mouseY - (elem.offset().top+(elem.height()/2)), 2)));
}

$(document).mousemove(function(e) {  
    mX = e.pageX;
    mY = e.pageY;
    cutoff = 100;
    $('.element').each(function(){
        distance = theDistance($(this), mX, mY);
        if (distance <= cutoff) {
            $(this).css('transform', 'scale(' + (distance*(1/cutoff)-1) + ')');
        } else {
            $(this).css('transform', 'scale(0)');
        }
    });


});

The problem is that the performance is buggy so I thought about making the same effect with an html canvas. I have no idea if it will work though.

Do you guys know of any other way I can create the same effect without a lot of html elements. Thanks.

EDIT: Thanks markE for your answer. It helped me a lot. This what I came up with.

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var circleRadius = 1;
var circleMargin = 10;
var canvasW = c.width;
var canvasH = c.height;

var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;

var circleAmountX = canvasW / (circleRadius + (2 * circleMargin));
var circleAmountY = canvasH / (circleRadius + (2 * circleMargin));

function draw(mouseX, mouseY) {
    ctx.clearRect(0, 0, canvasW, canvasH);
    for (i = 0; i < circleAmountX + 1; i++) {
        for (k = 0; k < circleAmountY + 1; k++) {

            var x = i * (circleRadius + circleMargin * 2);
            var y = k * (circleRadius + circleMargin * 2);

            var dx = mouseX - x;
            var dy = mouseY - y;

            var inflation = 1;
            var inflationAmount = 6;
            var cutoff = 150;

            var distance = Math.sqrt(dx * dx + dy * dy);
            if (distance <= cutoff && distance > 0) {
                inflation = inflationAmount - (distance / ((cutoff / inflationAmount) + 2));
            } else if (distance = 0) {
                inflation = inflationAmount;
            }
            ctx.beginPath();
            ctx.arc(x, y, circleRadius * inflation, 0, 2 * Math.PI);
            ctx.fill();
            ctx.closePath();
        }
    }
}

draw(0, 0);

$("#canvas").mousemove(function (e) {
    var mX = parseInt(e.clientX - offsetX);
    var mY = parseInt(e.clientY - offsetY);

    draw(mX, mY);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<canvas id="canvas" width=500 height=500></canvas>
like image 782
Sebastian Scholten Avatar asked Sep 30 '22 18:09

Sebastian Scholten


1 Answers

Yes, you can use canvas for better performance:

  • Listen for mousemove events

  • calculate the distance between the mouse & a circle center:

      var dx=mouseX-centerX;
      var dy=mouseY-centerY;
      var distance=Math.sqrt(dx*dx+dy*dy);
    
  • redraw an inflated/deflated circle based on how close the mouse is to the circle

Good luck with your project!

Here's a proof-of-concept with 1 circle:

enter image description hereenter image description hereenter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;



var cx=150;
var cy=150;
var radius=30;
var inflation=.25;

draw();

$("#canvas").mousemove(function(e){handleMouseMove(e);});


function draw(){
  ctx.clearRect(0,0,canvas.width,canvas.height);
  ctx.beginPath();
  ctx.arc(150,150,inflation,0,Math.PI*2);
  ctx.closePath();
  ctx.fill();
  ctx.stroke();
}

function handleMouseMove(e){
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  var dx=mouseX-cx;
  var dy=mouseY-cy;
  var distance=Math.sqrt(dx*dx+dy*dy);
  if(distance<radius){
    inflation=radius;
  }else if(distance<50){
    inflation=radius*.75;
  }else if(distance<75){
    inflation=radius*.50;
  }else{
    inflation=radius*.25;
  }
  draw();    

}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Approach the circle with the mouse</h4>
<canvas id="canvas" width=300 height=300></canvas>
like image 61
markE Avatar answered Oct 03 '22 00:10

markE