我有一个有一些点的画布。当鼠标靠近点时,点会散开,然后当鼠标远离那些点时,它们会回到最后位置。
工作的想法是:
当鼠标到达红色环境(悬停在画布上)时,应通过clearRect操作删除前一个点并放置新坐标。
var offsetX = canvas.offsetLeft;
var offsetY = canvas.offsetTop;
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
for(var i=0, j=particles.length;i<j;i++){
ctx.clearRect(particles[i].x, particles[i].y, 2, 2);
}
for(var i=0, j=particles.length;i<j;i++){
var xDistance = particles[i].x - mouseX;
var yDistance = particles[i].y - mouseY;
var distance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
if (distance < 20) {
angle = Math.atan2(yDistance,xDistance);
particles[i].x += Math.cos(angle) * distance;
particles[i].y += Math.sin(angle) * distance;
}
ctx.fillRect(particles[i].x, particles[i].y, 2, 2);
}
请帮我解决我的问题。
这是我的代码演示:jsfiddle
答案 0 :(得分:3)
问题
您的问题是跟踪要清除的内容。绘制函数有时可以绘制超过3或4个像素,而不是2,因为您没有将位置四舍五入为整数。
简单的解决方案。
而不是清除每个点只清除整个画布。一次清除要求比许多要快得多,尺寸差别不大,因为它是用于清理的硬件。
将鼠标事件中的clear循环替换为
/* remove
for(var i=0, j=particles.length;i<j;i++){
ctx.clearRect(particles[i].x, particles[i].y, 2, 2);
} */
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
有关此类动画的更多详情,请参阅https://stackoverflow.com/a/28391058/3877726
答案 1 :(得分:1)
下面怎么样?这里所有渲染都在一个setInterval函数中,鼠标事件只是更新与每个粒子相关的参数。无论何时调用它们,渲染函数都会使用这些参数。这允许您介绍您正在寻找的“渐进”效果。此外,您不必担心清除画布的微小部分,因为setInterval函数会清除所有内容并根据最初设置的值或鼠标事件设置的值重绘所有内容。
我在粒子对象中添加了一个x0和y0属性,让它知道如果它被鼠标事件移动了它应该返回的位置。 deltaY和deltaX让我们知道每个坐标元素增加多少。
这是我的小提琴:https://jsfiddle.net/kotman12/5p9tko50/
var canvas = document.getElementById("scene");
var ctx = canvas.getContext("2d");
var particles = [];
function drawScene(){
canvas.width = png.width+200;
canvas.height = png.height+200;
//canvas.addEventListener("mouseover", doMouseOver, false);
canvas.addEventListener('mousemove', move, false);
//canvas.addEventListener('mouseout', doMouseOut, false);
//canvas.addEventListener('click', doClick, false);
ctx.drawImage(png, 0, 0);
var data = ctx.getImageData(0, 0, png.width, png.height);
ctx.clearRect(0,0,canvas.width, canvas.height);
for (var y = 0, y2 = data.height; y < y2; y=y+4) {
for (var x = 0, x2 = data.width; x < x2; x=x+4) {
if (data.data[(y * 4 * data.width) + (x * 4) + 3] > 128) {
var particle = {
x : x+100,
y : y+100,
y0: y+100,
x0: x+100,
xDelta: 0,
yDelta: 0
};
particles.push(particle);
}
}
}
console.log(particles);
ctx.fillStyle = "White";
var renderStuff = setInterval(function() {
ctx.clearRect(0,0,canvas.width, canvas.height);
for(var i=0, j=particles.length;i<j;i++){
var particle = particles[i];
ctx.save();
// ctx.rotate((Math.PI/180)*2);
// ctx.translate(100, 100);
if(Math.sqrt(Math.pow(particle.x-particle.x0,2)+Math.pow(particle.y-particle.y0, 2)) > 1){
particle.x += particle.xDelta/200;
particle.y += particle.yDelta/200;
}else{
particle.x = particle.x0;
particle.y = particle.y0;
}
ctx.fillRect(particle.x, particle.y, 2, 2);
// ctx.restore();
}
}, 1);
}
function move(e){
// madami k hover hast
// console.log(2);
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
//ctx.clearRect(0,0,canvas.width, canvas.height);
/*for(var i=0, j=particles.length;i<j;i++){
ctx.clearRect(particles[i].x, particles[i].y, 2, 2);
}*/
for(var i=0, j=particles.length;i<j;i++){
var xDistance = particles[i].x - mouseX;
var yDistance = particles[i].y - mouseY;
var distance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
if (distance < 20) {
angle = Math.atan2(yDistance,xDistance);
particles[i].x += Math.cos(angle) * distance;
particles[i].y += Math.sin(angle) * distance;
particles[i].yDelta = particles[i].y0 - particles[i].y;
particles[i].xDelta = particles[i].x0 - particles[i].x;
}
/* else if(Math.abs(particle.x-particle.x0) > .01){
particle.x += particle.xDelta/400;
particle.y += particle.yDelta/400;
}*/
//ctx.fillRect(particles[i].x, particles[i].y, 2, 2);
}
}