>我在图像画布上创建了一个光标轨迹,其中图像画布位于背景中,光标轨迹位于图像画布顶部的第二个画布上。我目前面临的问题是,我无法创建一条逐渐消失的痕迹。
我已经看到了有关如何使用 fillStyle 使其以纯背景淡入淡出的提示,但我不知道如何使淡入淡出的光标轨迹以图像作为背景。
<!DOCTYPE html>
<html>
<head>
<style>
.stack {
position: relative;
}
.stack canvas {
position: absolute;
left: 0;
top: 0;
}
.stack,
#main_canvas {
background-size: contain;
width: 100%;
margin: auto;
}
</style>
</head>
<body>
<div class="stack">
<canvas id="main_canvas"> main canvas</canvas>
</div>
<script>
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var RADIUS = 70;
var RADIUS_SCALE = 1;
var RADIUS_SCALE_MIN = 1;
var RADIUS_SCALE_MAX = 1.5;
var QUANTITY = 25;
var canvas;
var canvas_bg;
var context;
var context_bg;
var particles;
var slider_image;
var mouseX = SCREEN_WIDTH * 0.5;
var mouseY = SCREEN_HEIGHT * 0.5;
var mouseIsDown = false;
var ind = 0;
function init() {
canvas = document.getElementById("main_canvas");
canvas_bg = document.createElement("canvas"); //<canvas> predefined
canvas.setAttribute("alt", "countless stars");
if (canvas && canvas.getContext) {
windowResizeHandler();
//background canvas
create_sliders();
//main canvas for creating mouse trails
context = canvas.getContext("2d");
// Register event listeners
window.addEventListener("mousemove", documentMouseMoveHandler, false);
window.addEventListener("mousedown", documentMouseDownHandler, false);
window.addEventListener("mouseup", documentMouseUpHandler, false);
document.addEventListener(
"touchstart",
documentTouchStartHandler,
false
);
document.addEventListener(
"touchmove",
documentTouchMoveHandler,
false
);
window.addEventListener("resize", windowResizeHandler, false);
createParticles();
setInterval(loop, 1000 / 60);
}
}
function create_sliders() {
slider_image = new Image();
slider_image.src =
"https://images.pexels.com/photos/956999/milky-way-starry-sky-night-sky-star-956999.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940";
canvas_bg.width = canvas.width;
canvas_bg.height = canvas.height;
// insert into DOM on top:
canvas.parentNode.insertBefore(canvas_bg, canvas);
context_bg = canvas_bg.getContext("2d");
context_bg.drawImage(slider_image, 0, 0, canvas.width, canvas.height);
}
function createParticles() {
particles = [];
for (var i = 0; i < QUANTITY; i++) {
var particle = {
size: 1,
position: { x: mouseX, y: mouseY },
offset: { x: 0, y: 0 },
shift: { x: mouseX, y: mouseY },
speed: 0.01 + Math.random() * 0.04,
targetSize: 1,
fillColor:
"#" + ((Math.random() * 0x404040 + 0xaaaaaa) | 0).toString(16),
orbit: RADIUS * 0.5 + RADIUS * 0.5 * Math.random()
};
particles.push(particle);
}
}
function documentMouseMoveHandler(event) {
mouseX = event.clientX - (window.innerWidth - SCREEN_WIDTH) * 0.5;
mouseY = event.clientY - (window.innerHeight - SCREEN_HEIGHT) * 0.5;
}
function documentMouseDownHandler(event) {
mouseIsDown = true;
}
function documentMouseUpHandler(event) {
mouseIsDown = false;
}
function documentTouchStartHandler(event) {
if (event.touches.length == 1) {
event.preventDefault();
mouseX =
event.touches[0].pageX - (window.innerWidth - SCREEN_WIDTH) * 0.5;
mouseY =
event.touches[0].pageY - (window.innerHeight - SCREEN_HEIGHT) * 0.5;
}
}
function documentTouchMoveHandler(event) {
if (event.touches.length == 1) {
event.preventDefault();
mouseX =
event.touches[0].pageX - (window.innerWidth - SCREEN_WIDTH) * 0.5;
mouseY =
event.touches[0].pageY - (window.innerHeight - SCREEN_HEIGHT) * 0.5;
}
}
function windowResizeHandler() {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
}
function loop() {
if (mouseIsDown) {
RADIUS_SCALE += (RADIUS_SCALE_MAX - RADIUS_SCALE) * 0.02;
} else {
RADIUS_SCALE -= (RADIUS_SCALE - RADIUS_SCALE_MIN) * 0.02;
}
RADIUS_SCALE = Math.min(RADIUS_SCALE, RADIUS_SCALE_MAX);
// context.fillStyle = 'rgba(0,0,0,0.05)';
context.fillStyle = "rgba(0, 0, 0, 0)";
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
for (i = 0, len = particles.length; i < len; i++) {
var particle = particles[i];
var lp = { x: particle.position.x, y: particle.position.y };
// Rotation
particle.offset.x += particle.speed;
particle.offset.y += particle.speed;
// Follow mouse with some lag
particle.shift.x += (mouseX - particle.shift.x) * particle.speed;
particle.shift.y += (mouseY - particle.shift.y) * particle.speed;
// Apply position
particle.position.x =
particle.shift.x +
Math.cos(i + particle.offset.x) * (particle.orbit * RADIUS_SCALE);
particle.position.y =
particle.shift.y +
Math.sin(i + particle.offset.y) * (particle.orbit * RADIUS_SCALE);
// Limit to screen bounds
particle.position.x = Math.max(
Math.min(particle.position.x, SCREEN_WIDTH),
0
);
particle.position.y = Math.max(
Math.min(particle.position.y, SCREEN_HEIGHT),
0
);
particle.size += (particle.targetSize - particle.size) * 0.05;
if (Math.round(particle.size) == Math.round(particle.targetSize)) {
particle.targetSize = 1 + Math.random() * 7;
}
if (particle.position) context.beginPath();
context.fillStyle = particle.fillColor;
context.strokeStyle = particle.fillColor;
context.lineWidth = particle.size;
context.moveTo(lp.x, lp.y);
context.lineTo(particle.position.x, particle.position.y);
context.stroke();
context.arc(
particle.position.x,
particle.position.y,
particle.size / 2,
0,
Math.PI * 2,
true
);
context.fill();
}
}
window.onload = init;
</script>
</body>
</html>
目前,较旧的小径不会消失,它正在创造更像我不想要的油漆效果。
淡
出粒子的一种方法是将(当前透明(drawRect
调用替换为drawImage
,该在将粒子添加到当前帧之前,在每个帧上绘制背景图像的半透明副本:
In your loop() function:
// Instead of this:
// context.fillStyle = "rgba(0, 0, 0, 0)";
// context.fillRect(0, 0, context.canvas.width, context.canvas.height);
// Do this:
context.save();
context.globalAlpha = 0.1;
context.drawImage(slider_image, 0, 0, canvas.width, canvas.height);
context.restore();
for (i = 0, len = particles.length; i < len; i++) {
...